From d64be36ead0ce792f249208635bc8db368d6cdd2 Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 19 Nov 2020 01:06:38 +0000 Subject: [PATCH] Security-59754.41.1.tar.gz --- .swiftlint.yml | 18 +- Analytics/Clients/LocalKeychainAnalytics.h | 2 + Analytics/Clients/LocalKeychainAnalytics.m | 4 + Analytics/Clients/SOSAnalytics.h | 2 +- Analytics/SFAnalytics.h | 9 +- Analytics/SFAnalytics.m | 57 + Analytics/SFAnalytics.plist | 13 + Analytics/SFAnalyticsDefines.h | 1 + Analytics/SFAnalyticsSQLiteStore.h | 4 +- Analytics/SQLite/SFSQLite.m | 3 +- CMS/CMSDecoder.h | 36 +- CMS/CMSEncoder.h | 46 +- CMS/CMSPrivate.h | 2 +- CMS/SecCmsBase.h | 6 +- CMS/SecCmsContentInfo.h | 44 +- CMS/SecCmsDecoder.h | 8 +- CMS/SecCmsDigestContext.h | 6 +- CMS/SecCmsDigestedData.h | 2 +- CMS/SecCmsEncoder.h | 8 +- CMS/SecCmsMessage.h | 8 +- CMS/SecCmsRecipientInfo.h | 12 +- CMS/SecCmsSignedData.h | 8 +- CMS/SecCmsSignerInfo.h | 26 +- CircleJoinRequested/Applicant.m | 12 +- CircleJoinRequested/CircleJoinRequested.m | 3 +- KVSKeychainSyncingProxy/CKDAKSLockMonitor.m | 5 +- KVSKeychainSyncingProxy/CKDKVSProxy.m | 10 +- KVSKeychainSyncingProxy/CKDKVSStore.h | 2 +- KVSKeychainSyncingProxy/CKDKVSStore.m | 94 +- KVSKeychainSyncingProxy/CKDStore.h | 2 +- .../XPCNotificationDispatcher.m | 4 +- KVSKeychainSyncingProxy/cloudkeychainproxy.m | 538 +- KeychainCircle/KCAESGCMDuplexSession.m | 43 +- KeychainCircle/KCError.h | 2 + KeychainCircle/KCJoiningAcceptSession.m | 101 +- KeychainCircle/KCJoiningMessages.h | 2 +- KeychainCircle/KCJoiningMessages.m | 26 +- .../KCJoiningRequestCircleSession.m | 91 +- .../KCJoiningRequestSecretSession.m | 45 +- KeychainCircle/KCSRPContext.m | 43 +- KeychainCircle/PairingChannel.m | 31 +- KeychainCircle/Tests/FakeSOSControl.m | 19 +- KeychainCircle/Tests/KCJoiningSessionTest.m | 62 +- KeychainCircle/Tests/KCParing.plist | 9 +- KeychainCircle/Tests/KCSRPTests.m | 3 +- KeychainCircle/Tests/KCTLKRequestTest.m | 37 +- KeychainCircle/Tests/KeychainCircle.plist | 54 +- KeychainEntitledTestApp_ios/AppDelegate.h | 17 - KeychainEntitledTestApp_ios/AppDelegate.m | 51 - .../AppIcon.appiconset/Contents.json | 98 - KeychainEntitledTestApp_ios/Info.plist | 45 - KeychainEntitledTestApp_ios/ViewController.h | 15 - KeychainEntitledTestApp_ios/ViewController.m | 29 - KeychainEntitledTestApp_mac/AppDelegate.h | 15 - KeychainEntitledTestApp_mac/AppDelegate.m | 27 - KeychainEntitledTestApp_mac/ViewController.h | 15 - KeychainEntitledTestApp_mac/main.m | 13 - .../KeychainSyncAccountNotification.m | 4 +- Modules/OctagonTrust.modulemap | 6 + Modules/Security.iOS.modulemap | 2 +- Modules/Security.macOS.modulemap | 2 +- Modules/Security.macOS.private.modulemap | 2 +- OSX/Breadcrumb/README | 99 - OSX/Breadcrumb/SecBreadcrumb.c | 397 -- OSX/Breadcrumb/SecBreadcrumb.h | 84 - OSX/Breadcrumb/bc-10-knife-on-bread.m | 105 - OSX/Breadcrumb/breadcrumb_regressions.h | 7 - .../Keychain Circle Notification.8 | 6 +- OSX/Keychain/KDCirclePeer.m | 16 +- OSX/Keychain/KDSecCircle.m | 15 +- OSX/Modules | 1 - .../SecurityTests-Entitlements.plist | 6 + OSX/SecurityTestsOSX/testlist.h | 1 - OSX/authd/PreloginUserDb.h | 6 + OSX/authd/PreloginUserDb.m | 548 ++ OSX/authd/authd-Entitlements.plist | 6 +- OSX/authd/authd_private.h | 4 +- OSX/authd/authdb.c | 9 +- OSX/authd/authitems.c | 5 +- OSX/authd/authorization.plist | 123 +- OSX/authd/authtoken.c | 2 + OSX/authd/authutilities.c | 12 +- OSX/authd/authutilities.h | 4 +- OSX/authd/com.apple.authd.sb | 8 +- OSX/authd/crc.h | 2 +- OSX/authd/credential.c | 28 +- OSX/authd/credential.h | 3 + OSX/authd/engine.c | 291 +- OSX/authd/engine.h | 2 +- OSX/authd/main.c | 9 +- OSX/authd/process.c | 2 + OSX/authd/rule.c | 28 +- OSX/authd/rule.h | 3 - OSX/authd/server.c | 97 +- OSX/authd/server.h | 5 +- OSX/authd/session.c | 2 + OSX/authd/tests/authdtestlist.h | 1 + OSX/authd/tests/authdtests.m | 40 + OSX/config/lib.xcconfig | 2 +- OSX/config/security_framework_macos.xcconfig | 13 +- OSX/config/security_macos.xcconfig | 2 +- OSX/include/security_asn1 | 1 - OSX/include/security_cdsa_client | 1 - OSX/include/security_cdsa_plugin | 1 - OSX/include/security_cdsa_utilities | 1 - OSX/include/security_cdsa_utils | 1 - OSX/include/security_codesigning | 1 - OSX/include/security_comcryption | 1 - OSX/include/security_cryptkit | 1 - OSX/include/security_filedb | 1 - OSX/include/security_keychain | 1 - OSX/include/security_ocspd | 1 - OSX/include/security_pkcs12 | 1 - OSX/include/security_smime | 1 - OSX/include/security_utilities | 1 - OSX/include/securityd_client | 1 - OSX/lib/en.lproj/InfoPlist.strings | Bin 290 -> 290 bytes .../en.lproj/authorization.buttons.strings | 4 + .../authorization.dfr.prompts.strings | 6 +- .../en.lproj/authorization.prompts.strings | 10 +- OSX/lib/framework.sb | 11 - OSX/libsecurity_apple_csp/lib/DH_keys.cpp | 2 +- OSX/libsecurity_apple_csp/lib/DH_utils.cpp | 2 +- .../lib/FEEAsymmetricContext.cpp | 4 +- OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp | 2 +- OSX/libsecurity_apple_csp/lib/FEEKeys.cpp | 2 +- .../lib/FEESignatureObject.cpp | 2 +- .../lib/RSA_DSA_keys.cpp | 2 +- .../lib/RSA_DSA_signature.cpp | 2 +- .../lib/RSA_DSA_utils.cpp | 6 +- .../lib/RSA_asymmetric.cpp | 2 +- .../lib/pkcs12Derive.cpp | 2 +- OSX/libsecurity_apple_csp/lib/pkcs8.cpp | 6 +- .../open_ssl/bn/bn_asm.c | 2 +- .../open_ssl/bn/bn_ctx.c | 2 +- .../open_ssl/bn/bn_exp.c | 2 +- .../open_ssl/bn/bn_lcl.h | 9 +- .../open_ssl/opensslUtils/opensslAsn1.cpp | 2 +- .../open_ssl/rsa/rsa_saos.c | 8 +- .../open_ssl/rsa/rsa_sign.c | 8 +- .../lib/SSCSPSession.cpp | 4 +- OSX/libsecurity_apple_cspdl/lib/SSContext.cpp | 2 +- .../lib/CLCertExtensions.cpp | 2 +- .../lib/clNssUtils.cpp | 6 +- .../lib/clNssUtils.h | 6 +- .../lib/ocspRequest.cpp | 2 +- .../lib/tpCertGroup.cpp | 158 - .../lib/tpCredRequest.cpp | 2 +- .../lib/tpOcspCache.cpp | 2 +- .../lib/tpPolicies.cpp | 2 +- OSX/libsecurity_apple_x509_tp/lib/tpTime.c | 2 + OSX/libsecurity_asn1/lib/SecNssCoder.cpp | 2 +- OSX/libsecurity_asn1/lib/X509Templates.c | 1 - OSX/libsecurity_asn1/lib/nameTemplates.c | 2 +- OSX/libsecurity_asn1/lib/ocspTemplates.c | 1 - OSX/libsecurity_asn1/lib/plarena.c | 3 +- OSX/libsecurity_asn1/lib/prlog.h | 13 +- OSX/libsecurity_asn1/lib/secasn1d.c | 5 +- OSX/libsecurity_asn1/security_asn1 | 1 - .../lib/Authorization.c | 194 +- .../lib/Authorization.cpp | 69 +- .../lib/Authorization.h | 6 +- .../lib/AuthorizationPlugin.h | 4 +- .../lib/AuthorizationPriv.h | 27 +- .../lib/AuthorizationTagsPriv.h | 33 + .../lib/trampolineClient.cpp | 8 - .../lib/cssmclient.cpp | 2 +- OSX/libsecurity_cdsa_client/lib/cssmclient.h | 2 +- .../lib/ACabstractsession.cpp | 3 +- .../lib/CLabstractsession.cpp | 3 +- .../lib/CSPabstractsession.cpp | 3 +- .../lib/DLabstractsession.cpp | 2 + OSX/libsecurity_cdsa_plugin/lib/DLsession.cpp | 6 +- OSX/libsecurity_cdsa_plugin/lib/DLsession.h | 6 +- OSX/libsecurity_cdsa_plugin/lib/Database.cpp | 6 +- .../lib/DatabaseSession.cpp | 2 +- .../lib/TPabstractsession.cpp | 3 +- .../lib/csputilities.cpp | 5 +- .../lib/cssmplugin.cpp | 24 +- .../lib/pluginsession.cpp | 14 +- .../lib/pluginsession.h | 6 +- OSX/libsecurity_cdsa_plugin/lib/pluginspi.h | 8 +- .../lib/acl_comment.cpp | 2 - .../lib/acl_process.cpp | 5 +- .../lib/acl_threshold.cpp | 3 +- OSX/libsecurity_cdsa_utilities/lib/context.h | 6 +- .../lib/cssmalloc.cpp | 14 +- .../lib/cssmalloc.h | 34 +- .../lib/cssmbridge.h | 9 +- .../lib/cssmdata.cpp | 2 +- OSX/libsecurity_cdsa_utilities/lib/cssmdata.h | 4 +- OSX/libsecurity_cdsa_utilities/lib/cssmdb.h | 11 +- .../lib/cssmerrors.cpp | 2 +- .../lib/cssmerrors.h | 2 +- .../lib/cssmlist.cpp | 8 + OSX/libsecurity_cdsa_utilities/lib/cssmlist.h | 2 + .../lib/cssmpods.cpp | 14 +- OSX/libsecurity_cdsa_utilities/lib/cssmpods.h | 17 +- OSX/libsecurity_cms/lib/CMSUtils.h | 6 +- .../CodeSigningHelper/main.c | 2 +- .../CodeSigningHelper/main.cpp | 6 +- .../antlr2/antlr/ANTLRException.hpp | 2 +- .../antlr2/antlr/CharStreamException.hpp | 2 +- .../antlr2/antlr/CharStreamIOException.hpp | 2 +- .../antlr2/antlr/IOException.hpp | 2 +- .../antlr2/antlr/MismatchedCharException.hpp | 2 +- .../antlr2/antlr/MismatchedTokenException.hpp | 2 +- .../antlr2/antlr/NoViableAltException.hpp | 2 +- .../antlr/NoViableAltForCharException.hpp | 2 +- .../antlr2/antlr/RecognitionException.hpp | 8 +- .../antlr2/antlr/SemanticException.hpp | 2 +- .../antlr2/antlr/TokenStreamException.hpp | 2 +- .../antlr2/antlr/TokenStreamIOException.hpp | 2 +- .../antlr/TokenStreamRecognitionException.hpp | 8 +- .../antlr/TokenStreamRetryException.hpp | 2 +- .../antlr2/src/TokenStreamRewriteEngine.cpp | 41 +- OSX/libsecurity_codesigning/lib/CSCommon.h | 5 + OSX/libsecurity_codesigning/lib/Code.cpp | 2 +- OSX/libsecurity_codesigning/lib/Code.h | 2 +- .../lib/CodeSigner.cpp | 10 +- OSX/libsecurity_codesigning/lib/CodeSigner.h | 2 +- .../lib/Requirements.cpp | 2 +- .../lib/Requirements.h | 2 +- .../lib/SecAssessment.cpp | 4 +- OSX/libsecurity_codesigning/lib/SecCode.cpp | 27 + OSX/libsecurity_codesigning/lib/SecCode.h | 30 +- OSX/libsecurity_codesigning/lib/SecCodePriv.h | 4 + .../lib/SecCodeSigner.h | 11 +- .../lib/SecStaticCode.cpp | 16 +- .../lib/SecStaticCode.h | 3 +- .../lib/StaticCode.cpp | 627 ++- OSX/libsecurity_codesigning/lib/StaticCode.h | 9 +- .../lib/bundlediskrep.cpp | 2 +- .../lib/codedirectory.cpp | 1 + OSX/libsecurity_codesigning/lib/cserror.cpp | 2 +- OSX/libsecurity_codesigning/lib/cserror.h | 2 +- OSX/libsecurity_codesigning/lib/cskernel.cpp | 2 +- OSX/libsecurity_codesigning/lib/csprocess.h | 2 +- .../lib/csutilities.cpp | 100 +- OSX/libsecurity_codesigning/lib/csutilities.h | 2 + .../lib/dirscanner.cpp | 6 +- OSX/libsecurity_codesigning/lib/machorep.cpp | 42 +- OSX/libsecurity_codesigning/lib/machorep.h | 1 + .../lib/notarization.cpp | 10 + .../lib/notarization.h | 1 + .../lib/piddiskrep.cpp | 7 +- OSX/libsecurity_codesigning/lib/reqinterp.cpp | 139 +- OSX/libsecurity_codesigning/lib/reqinterp.h | 1 + OSX/libsecurity_codesigning/lib/signer.cpp | 44 +- OSX/libsecurity_codesigning/lib/signer.h | 3 +- OSX/libsecurity_codesigning/lib/signerutils.h | 2 +- OSX/libsecurity_codesigning/lib/xpcengine.cpp | 8 +- OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp | 4 +- .../lib/CurveParamDocs/schoof.c | 1 - .../lib/CurveParamDocs/schoofs.c | 1 - OSX/libsecurity_cryptkit/lib/feeFEED.c | 8 - OSX/libsecurity_cssm/lib/attachment.cpp | 12 +- OSX/libsecurity_cssm/lib/cssm.cpp | 2 +- OSX/libsecurity_cssm/lib/cssmcontext.h | 8 +- OSX/libsecurity_cssm/lib/cssmerr.h | 18 +- OSX/libsecurity_cssm/lib/module.cpp | 2 +- OSX/libsecurity_cssm/lib/transition.cpp | 1 + OSX/libsecurity_filedb/lib/AppleDatabase.cpp | 32 +- OSX/libsecurity_filedb/lib/AppleDatabase.h | 8 +- OSX/libsecurity_filedb/lib/AtomicFile.cpp | 10 +- OSX/libsecurity_filedb/lib/AtomicFile.h | 4 +- OSX/libsecurity_filedb/lib/DbIndex.cpp | 8 +- .../lib/ReadWriteSection.cpp | 7 +- OSX/libsecurity_filedb/lib/ReadWriteSection.h | 2 +- OSX/libsecurity_keychain/Security | 1 - .../lib/CertificateValues.cpp | 2 +- .../lib/CertificateValues.h | 2 +- .../lib/DLDBListCFPref.cpp | 11 +- .../lib/ExtendedAttribute.cpp | 2 +- .../lib/ExtendedAttribute.h | 2 +- OSX/libsecurity_keychain/lib/Identity.cpp | 2 +- OSX/libsecurity_keychain/lib/Identity.h | 2 +- .../lib/IdentityCursor.cpp | 6 +- OSX/libsecurity_keychain/lib/IdentityCursor.h | 4 +- OSX/libsecurity_keychain/lib/Item.cpp | 12 +- OSX/libsecurity_keychain/lib/Item.h | 6 +- OSX/libsecurity_keychain/lib/KCCursor.cpp | 2 +- OSX/libsecurity_keychain/lib/KCCursor.h | 2 +- OSX/libsecurity_keychain/lib/KeyItem.cpp | 10 +- OSX/libsecurity_keychain/lib/KeyItem.h | 2 +- OSX/libsecurity_keychain/lib/Keychains.h | 4 +- .../lib/LegacyAPICounts.h} | 26 +- .../lib/LegacyAPICounts.m | 106 + OSX/libsecurity_keychain/lib/Password.cpp | 2 +- OSX/libsecurity_keychain/lib/Password.h | 2 +- OSX/libsecurity_keychain/lib/Policies.cpp | 2 +- OSX/libsecurity_keychain/lib/Policies.h | 2 +- OSX/libsecurity_keychain/lib/PolicyCursor.cpp | 2 +- OSX/libsecurity_keychain/lib/PolicyCursor.h | 2 +- OSX/libsecurity_keychain/lib/SecACL.cpp | 7 + OSX/libsecurity_keychain/lib/SecAccess.cpp | 14 +- OSX/libsecurity_keychain/lib/SecAccess.h | 4 +- OSX/libsecurity_keychain/lib/SecAccessPriv.h | 5 +- OSX/libsecurity_keychain/lib/SecBase.cpp | 5 +- OSX/libsecurity_keychain/lib/SecBridge.h | 10 + .../lib/SecCertificate.cpp | 33 +- .../lib/SecCertificateBundle.cpp | 82 - .../lib/SecCertificateBundle.h | 84 - OSX/libsecurity_keychain/lib/SecExport.cpp | 1 + OSX/libsecurity_keychain/lib/SecIdentity.cpp | 375 +- .../lib/SecIdentitySearch.cpp | 2 +- .../lib/SecImportExportPem.cpp | 2 + .../lib/SecImportExportPkcs8.cpp | 2 +- OSX/libsecurity_keychain/lib/SecItem.cpp | 70 +- .../lib/SecItemConstants.c | 7 + OSX/libsecurity_keychain/lib/SecKey.cpp | 5 +- OSX/libsecurity_keychain/lib/SecKeychain.cpp | 197 +- OSX/libsecurity_keychain/lib/SecKeychain.h | 52 +- .../lib/SecKeychainAddIToolsPassword.cpp | 46 - .../lib/SecKeychainItem.cpp | 44 +- .../lib/SecKeychainItem.h | 28 +- .../lib/SecKeychainItemExtendedAttributes.cpp | 14 +- .../lib/SecKeychainItemExtendedAttributes.h | 6 +- .../lib/SecKeychainItemPriv.h | 30 +- .../lib/SecKeychainPriv.h | 8 +- .../lib/SecKeychainSearch.cpp | 2 +- .../lib/SecKeychainSearch.h | 6 +- OSX/libsecurity_keychain/lib/SecPassword.cpp | 14 +- OSX/libsecurity_keychain/lib/SecPassword.h | 6 +- OSX/libsecurity_keychain/lib/SecPolicy.cpp | 48 - .../lib/SecPolicySearch.cpp | 2 - .../lib/SecTrustOSXEntryPoints.cpp | 13 +- .../lib/SecTrustSettings.cpp | 100 +- .../lib/SecTrustedApplication.cpp | 2 - .../lib/SecTrustedApplication.h | 6 +- .../lib/SecTrustedApplicationPriv.h | 20 +- .../lib/SecWrappedKeys.cpp | 2 +- .../lib/StorageManager.cpp | 5 +- .../lib/TrustAdditions.cpp | 11 +- .../lib/TrustRevocation.cpp | 2 +- .../lib/TrustSettings.cpp | 10 +- OSX/libsecurity_keychain/lib/TrustSettings.h | 5 + .../lib/TrustSettingsUtils.cpp | 1 - .../regressions/kc-key-helpers.h | 15 +- .../xpc-tsa/timestampclient.m | 3 +- .../lib/AppleManifest.cpp | 7 +- OSX/libsecurity_manifest/lib/Manifest.cpp | 2 +- OSX/libsecurity_manifest/lib/Manifest.h | 2 +- .../lib/SecureDownloadInternal.c | 2 + OSX/libsecurity_mds/lib/MDSSession.cpp | 2 +- OSX/libsecurity_mds/lib/MDSSession.h | 6 +- OSX/libsecurity_mds/lib/mdsapi.cpp | 3 +- OSX/libsecurity_ocspd/client/ocspdClient.cpp | 5 +- OSX/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp | 2 +- OSX/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp | 2 +- OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp | 4 +- OSX/libsecurity_sd_cspdl/lib/SDContext.cpp | 2 +- OSX/libsecurity_smime/lib/cert.c | 106 +- OSX/libsecurity_smime/lib/cmsdigest.c | 2 +- OSX/libsecurity_smime/lib/cmssiginfo.c | 61 +- OSX/libsecurity_smime/lib/tsaSupport.c | 5 +- OSX/libsecurity_smime/lib/tsaTemplates.c | 1 - .../regressions/cms-01-basic.c | 16 +- .../regressions/cms-01-basic.h | 89 +- OSX/libsecurity_ssl/Security | 1 - OSX/libsecurity_ssl/lib/CipherSuite.h | 2 +- OSX/libsecurity_ssl/lib/SSLRecordInternal.c | 4 +- OSX/libsecurity_ssl/lib/SecureTransportPriv.h | 48 +- OSX/libsecurity_ssl/lib/sslCipherSpecs.c | 1 - OSX/libsecurity_ssl/lib/sslContext.c | 22 +- OSX/libsecurity_ssl/lib/sslCrypto.c | 2 +- OSX/libsecurity_ssl/lib/sslKeychain.c | 2 +- OSX/libsecurity_ssl/lib/sslRecord.c | 1 - OSX/libsecurity_ssl/lib/sslTransport.c | 7 +- OSX/libsecurity_ssl/lib/tlsCallbacks.c | 2 + .../STLegacyTests+falsestart.m | 9 +- .../STLegacyTests+sessionstate.m | 5 +- .../STLegacyTests+tls12.m | 8 +- .../SecureTransportTests_ios.xctestplan | 24 + .../SecureTransportTests_macos.xctestplan | 24 + .../SecureTransport_iosTests.plist | 9 +- .../SecureTransport_macosTests.plist | 9 +- .../regressions/ssl-50-server.c | 4 +- .../regressions/ssl-51-state.c | 5 +- OSX/libsecurity_ssl/security_ssl | 1 - .../lib/SecDecodeTransform.h | 2 +- .../lib/SecDigestTransform.h | 2 +- .../lib/SecEncodeTransform.h | 2 +- .../lib/SecEncryptTransform.h | 2 +- .../lib/SecSignVerifyTransform.c | 12 +- .../lib/SecSignVerifyTransform.h | 2 +- OSX/libsecurity_transform/lib/Transform.cpp | 15 +- OSX/libsecurity_transform/misc/speed-test.mm | 2 +- .../lib/SecTranslocate.cpp | 47 +- .../lib/SecTranslocate.h | 27 + .../lib/SecTranslocateClient.cpp | 38 +- .../lib/SecTranslocateClient.hpp | 4 + .../lib/SecTranslocateEnumUtils.hpp | 40 + .../lib/SecTranslocateInterface.hpp | 1 + .../lib/SecTranslocateServer.cpp | 22 + .../lib/SecTranslocateServer.hpp | 1 + .../lib/SecTranslocateShared.cpp | 202 +- .../lib/SecTranslocateShared.hpp | 30 +- .../lib/SecTranslocateUtilities.hpp | 2 +- .../lib/SecTranslocateXPCServer.cpp | 25 +- OSX/libsecurity_utilities/lib/alloc.cpp | 28 +- OSX/libsecurity_utilities/lib/alloc.h | 42 +- OSX/libsecurity_utilities/lib/cfclass.cpp | 12 +- OSX/libsecurity_utilities/lib/cfclass.h | 12 +- OSX/libsecurity_utilities/lib/cfmunge.cpp | 20 +- OSX/libsecurity_utilities/lib/daemon.cpp | 27 - OSX/libsecurity_utilities/lib/daemon.h | 1 - .../lib/debugging_internal.cpp | 6 +- OSX/libsecurity_utilities/lib/errors.cpp | 8 +- OSX/libsecurity_utilities/lib/errors.h | 8 +- OSX/libsecurity_utilities/lib/globalizer.cpp | 4 +- OSX/libsecurity_utilities/lib/globalizer.h | 4 +- OSX/libsecurity_utilities/lib/mach++.cpp | 7 +- OSX/libsecurity_utilities/lib/mach++.h | 27 +- OSX/libsecurity_utilities/lib/macho++.cpp | 11 +- OSX/libsecurity_utilities/lib/macho++.h | 2 +- OSX/libsecurity_utilities/lib/muscle++.cpp | 7 +- OSX/libsecurity_utilities/lib/muscle++.h | 2 +- OSX/libsecurity_utilities/lib/pcsc++.cpp | 2 +- OSX/libsecurity_utilities/lib/pcsc++.h | 2 +- OSX/libsecurity_utilities/lib/refcount.h | 2 +- OSX/libsecurity_utilities/lib/seccfobject.cpp | 8 +- OSX/libsecurity_utilities/lib/seccfobject.h | 18 +- OSX/libsecurity_utilities/lib/simpleprefs.cpp | 2 +- OSX/libsecurity_utilities/lib/sqlite++.h | 4 +- OSX/libsecurity_utilities/lib/superblob.h | 7 +- .../lib/trackingallocator.cpp | 6 +- .../lib/trackingallocator.h | 6 +- OSX/libsecurity_utilities/lib/unix++.h | 2 + OSX/libsecurity_utilities/lib/unixchild.cpp | 7 +- OSX/libsecurity_utilities/lib/utilities.h | 2 + .../lib/utility_config.h | 2 +- OSX/libsecurityd/lib/sec_xdr.c | 2 +- OSX/libsecurityd/lib/sec_xdr_array.c | 2 +- OSX/libsecurityd/lib/sec_xdr_reference.c | 2 +- OSX/libsecurityd/lib/xdr_auth.c | 1 - OSX/libsecurityd/lib/xdr_cssm.c | 2 +- OSX/macos_tapi_hacks.h | 8 + OSX/regressions/test/testenv.h | 1 - OSX/regressions/test/testenv.m | 29 +- OSX/regressions/test/testmore.h | 30 +- .../Security/AppleExternalRootCertificates.h | 106 + .../Regressions/otr/otr-00-identity.c | 57 +- .../Regressions/secitem/si-21-sectrust-asr.c | 2 +- .../Regressions/secitem/si-23-sectrust-ocsp.c | 696 --- .../Regressions/secitem/si-23-sectrust-ocsp.h | 1603 ------ .../Regressions/secitem/si-24-sectrust-itms.c | 2 +- .../secitem/si-26-sectrust-copyproperties.c | 7 +- .../secitem/si-32-sectrust-pinning-required.h | 133 +- .../secitem/si-32-sectrust-pinning-required.m | 11 +- .../Regressions/secitem/si-34-cms-timestamp.m | 29 +- .../Regressions/secitem/si-66-smime.c | 80 +- .../secitem/si-67-sectrust-blocklist.c | 154 - .../Global Trustee.cer.h | 150 - .../UTN-USERFirst-Hardware.cer.h | 99 - .../addons.mozilla.org.cer.h | 131 - .../login.live.com.cer.h | 130 - .../login.skype.com.cer.h | 130 - .../login.yahoo.com.1.cer.h | 129 - .../login.yahoo.com.2.cer.h | 129 - .../login.yahoo.com.cer.h | 130 - .../mail.google.com.cer.h | 130 - .../www.google.com.cer.h | 129 - .../Regressions/secitem/si-74-OTAPKISigner.c | 1007 ---- .../Regressions/secitem/si-82-token-ag.c | 7 +- .../secitem/si-84-sectrust-allowlist.m | 490 -- .../Regressions/secitem/si-95-cms-basic.c | 2 +- .../Regressions/secitem/si-95-cms-basic.h | 89 +- .../secitem/si_77_SecAccessControl.c | 6 +- .../Regressions/vmdh/vmdh-41-example.c | 6 +- .../Regressions/vmdh/vmdh-42-example2.c | 6 +- OSX/sec/Security/SecAccessControl.m | 2 +- OSX/sec/Security/SecBase64.c | 2 +- OSX/sec/Security/SecCTKKey.m | 57 +- OSX/sec/Security/SecCertificate.c | 640 ++- OSX/sec/Security/SecCertificateInternal.h | 6 +- OSX/sec/Security/SecCertificateRequest.c | 134 +- OSX/sec/Security/SecDH.c | 21 +- OSX/sec/Security/SecECKey.m | 13 +- OSX/sec/Security/SecExports.exp-in | 73 +- OSX/sec/Security/SecFramework.c | 26 - OSX/sec/Security/SecFramework.h | 3 - OSX/sec/Security/SecFrameworkStrings.h | 4 +- OSX/sec/Security/SecItem.c | 182 +- OSX/sec/Security/SecItem.m | 32 +- OSX/sec/Security/SecItemBackup.c | 37 +- OSX/sec/Security/SecItemBackup.h | 20 +- OSX/sec/Security/SecItemConstants.c | 7 + OSX/sec/Security/SecItemInternal.h | 5 + OSX/sec/Security/SecItemRateLimit.h | 9 + OSX/sec/Security/SecItemRateLimit.m | 199 + OSX/sec/Security/SecItemRateLimit_tests.h | 52 + OSX/sec/Security/SecItemShim.h | 2 - OSX/sec/Security/SecKey.m | 2 +- OSX/sec/Security/SecKeyAdaptors.m | 11 +- OSX/sec/Security/SecKeyProxy.m | 6 +- OSX/sec/Security/SecOTR.h | 7 +- OSX/sec/Security/SecOTRDHKey.c | 5 +- OSX/sec/Security/SecOTRFullIdentity.c | 102 +- OSX/sec/Security/SecOTRIdentityPriv.h | 3 +- OSX/sec/Security/SecOTRPacketData.h | 130 +- OSX/sec/Security/SecOTRPublicIdentity.c | 1 + OSX/sec/Security/SecOTRSession.c | 6 - OSX/sec/Security/SecOTRSession.h | 4 - OSX/sec/Security/SecPolicy.c | 629 ++- OSX/sec/Security/SecPolicy.list | 7 +- OSX/sec/Security/SecPolicyChecks.list | 14 +- OSX/sec/Security/SecPolicyLeafCallbacks.c | 19 +- OSX/sec/Security/SecRSAKey.c | 7 +- OSX/sec/Security/SecRecoveryKey.m | 4 +- OSX/sec/Security/SecServerEncryptionSupport.c | 6 +- OSX/sec/Security/SecSharedCredential.c | 51 +- OSX/sec/Security/SecSharedCredential.m | 247 + OSX/sec/Security/SecTrust.c | 38 +- OSX/sec/Security/SecTrustInternal.h | 9 +- OSX/sec/Security/SecTrustStore.c | 94 +- OSX/sec/Security/SecuritydXPC.c | 42 +- OSX/sec/Security/SecuritydXPC.h | 1 + OSX/sec/Security/ios_tapi_hacks.h | 3 + OSX/sec/Security/p12pbegen.c | 2 + OSX/sec/SharedWebCredential/swcagent.m | 4 +- OSX/sec/ipc/client.c | 78 +- OSX/sec/ipc/client_endpoint.m | 62 +- OSX/sec/ipc/com.apple.secd.plist | 9 + OSX/sec/ipc/com.apple.securityd.plist | 9 + OSX/sec/ipc/securityd_client.h | 39 +- OSX/sec/ipc/server.c | 244 +- OSX/sec/ipc/server_endpoint.m | 3 + OSX/sec/ipc/server_entitlement_helpers.c | 46 +- OSX/sec/ipc/server_security_helpers.h | 3 + OSX/sec/ipc/server_security_helpers.m | 34 +- OSX/sec/ipc/server_xpc.m | 28 +- OSX/sec/os_log/com.apple.security.ckks.plist | 37 + OSX/sec/os_log/com.apple.securityd.plist | 20 + OSX/sectests/SecurityTests-Entitlements.plist | 6 + OSX/sectests/testlist.h | 1 - OSX/shared_regressions/shared_regressions.h | 15 - .../bad_SAN_seq_length.cer | Bin 0 -> 1000 bytes .../bad_general_name_type.cer | Bin 0 -> 1000 bytes .../san_zero_length_sequence.cer | Bin 0 -> 812 bytes .../ExtensionFailureCerts/zero_length_aia.cer | Bin 0 -> 1385 bytes .../zero_length_certificate_policies.cer | Bin 0 -> 916 bytes .../zero_length_crldps.cer | Bin 0 -> 1156 bytes .../parse_fail_explicit_paramaters.cer | Bin 0 -> 830 bytes .../NameFailureCerts/rdn_short_length.cer | Bin 0 -> 1000 bytes .../NameFailureCerts/zero_length_rdn.cer | Bin 0 -> 1000 bytes .../zero_length_critical_policy_mappings.cer | Bin 0 -> 1329 bytes .../ParseFailureCerts/zero_length_ekus.cer | Bin 0 -> 974 bytes .../zero_length_extensions.cer | Bin 0 -> 585 bytes .../zero_length_general_subtrees.cer | Bin 0 -> 1009 bytes ...general_name_type_constructed_uri_name.cer | Bin 0 -> 1000 bytes .../general_name_type_directory_name.cer | Bin 0 -> 1000 bytes .../general_name_type_dns_name.cer | Bin 0 -> 1000 bytes .../general_name_type_edi_party_name.cer | Bin 0 -> 1000 bytes .../general_name_type_ip_address.cer | Bin 0 -> 1000 bytes .../general_name_type_other_name.cer | Bin 0 -> 1000 bytes .../general_name_type_registered_id.cer | Bin 0 -> 1000 bytes .../general_name_type_rfc822_name.cer | Bin 0 -> 1000 bytes .../general_name_type_uri_name.cer | Bin 0 -> 1000 bytes .../general_name_type_x400_name.cer | Bin 0 -> 1000 bytes .../AAACertificateServices.cer | Bin 0 -> 1078 bytes .../ApplePublicServerRSA12-G1.cer | Bin 0 -> 1172 bytes .../NSPinnedDomainsParsingTest.plist | 100 + .../NSPinnedDomains_ca.plist | 24 + .../NSPinnedDomains_leaf.plist | 26 + .../NSPinnedDomains_leaf_and_ca.plist | 33 + .../NSPinnedDomains_with_empty_spki.plist | 18 + .../NSPinnedDomains_with_invalid_spki.plist | 21 + .../NSPinnedDomains_without_spki.plist | 15 + .../OCSP_TestCA.cer | Bin 0 -> 601 bytes .../PinningPolicyTrustTest.plist | 535 +- .../TestAppleWWDR-G3.cer | Bin 0 -> 1141 bytes .../ids_init_public.cer | Bin 0 -> 2116 bytes .../si-20-sectrust-policies-data/ids_test.cer | Bin 1146 -> 1163 bytes .../ocsp_missing_eku.cer | Bin 0 -> 648 bytes .../ocsp_missing_ku.cer | Bin 0 -> 669 bytes .../ocsp_responder.cer | Bin 0 -> 664 bytes .../ocsp_subca.cer | Bin 0 -> 668 bytes .../test_iPh0ne_distribution.cer | Bin 0 -> 1494 bytes .../test_iphone_distribution.cer | Bin 0 -> 1494 bytes OSX/shared_regressions/si-44-seckey-aks.m | 164 +- OSX/shared_regressions/si-44-seckey-proxy.m | 5 +- OSX/shared_regressions/si-88-sectrust-valid.m | 308 -- .../Regressions/su-10-cfstring-der.c | 4 +- OSX/utilities/Regressions/su-11-cfdata-der.c | 4 +- .../Regressions/su-12-cfboolean-der.c | 4 +- .../Regressions/su-13-cfnumber-der.c | 4 +- OSX/utilities/Regressions/su-14-cfarray-der.c | 4 +- .../Regressions/su-15-cfdictionary-der.c | 4 +- OSX/utilities/Regressions/su-16-cfdate-der.c | 8 +- OSX/utilities/Regressions/su-17-cfset-der.c | 4 +- OSX/utilities/Regressions/su-40-secdb.c | 13 +- .../Regressions/su-41-secdb-stress.c | 21 +- OSX/utilities/SecADWrapper.c | 102 - OSX/utilities/SecCFCCWrappers.c | 2 + OSX/utilities/SecCFError.c | 180 +- OSX/utilities/SecCFError.h | 146 +- OSX/utilities/SecCFWrappers.h | 27 +- OSX/utilities/SecCoreAnalytics.h | 8 +- OSX/utilities/SecCoreAnalytics.m | 13 +- OSX/utilities/SecDb.c | 182 +- OSX/utilities/SecDb.h | 8 - OSX/utilities/SecDbInternal.h | 14 + OSX/utilities/SecFileLocations.c | 14 + OSX/utilities/SecFileLocations.h | 2 + OSX/utilities/SecXPCError.c | 2 +- OSX/utilities/SecXPCHelper.h | 2 +- OSX/utilities/SecXPCHelper.m | 32 +- OSX/utilities/debugging.c | 19 - OSX/utilities/debugging.h | 3 + OSX/utilities/der_array.c | 16 +- OSX/utilities/der_boolean.c | 11 +- OSX/utilities/der_data.c | 39 +- OSX/utilities/der_date.c | 95 +- OSX/utilities/der_date.h | 2 + OSX/utilities/der_dictionary.c | 32 +- OSX/utilities/der_null.c | 9 +- OSX/utilities/der_number.c | 22 +- OSX/utilities/der_plist.c | 54 +- OSX/utilities/der_plist.h | 9 +- OSX/utilities/der_plist_internal.c | 9 + OSX/utilities/der_plist_internal.h | 28 +- OSX/utilities/der_set.c | 17 +- OSX/utilities/der_set.h | 2 +- OSX/utilities/der_string.c | 16 +- OSX/utilities/entitlements.c | 66 + OSX/utilities/entitlements.h | 41 + OSX/utilities/simulate_crash.m | 2 +- .../utilities/simulatecrash_assert.h | 33 +- RegressionTests/Security.plist | 40 +- RegressionTests/bats_utd_plist.h | 45 + .../secitemnotifications.m | 54 +- .../secitemstresstest/secitemstresstest.m | 6 +- RegressionTests/secseccodeapitest.c | 253 + Security.exp-in | 56 +- Security.xcodeproj/project.pbxproj | 4518 ++++++++--------- .../xcshareddata/xcschemes/CKKSTests.xcscheme | 2 +- .../xcschemes/OctagonTests.xcscheme | 2 +- .../SecureTransportTests_ios.xcscheme | 58 + .../SecureTransportTests_macos.xcscheme | 74 + .../xcschemes/TrustTests_ios.xcscheme | 11 +- .../xcschemes/TrustTests_macos.xcscheme | 11 +- .../xcschemes/TrustedPeers.xcscheme | 11 +- .../xcschemes/ios - Debug.xcscheme | 45 +- .../xcschemes/ios - Release.xcscheme | 35 +- .../xcschemes/ios - secdtests.xcscheme | 15 +- .../xcschemes/osx - World.xcscheme | 59 +- .../xcschemes/osx - secdtests.xcscheme | 31 +- .../xcschemes/osx - sectests.xcscheme | 11 +- .../xcschemes/secdmockaks.xcscheme | 2 +- .../SecurityTests-Entitlements.plist | 3 + .../ssl-policy-certs/subCA_EKU_Root.cer | Bin 0 -> 652 bytes .../ssl-policy-certs/subCA_EKU_anyEKU_ca.cer | Bin 0 -> 683 bytes .../subCA_EKU_anyEKU_leaf.cer | Bin 0 -> 670 bytes .../ssl-policy-certs/subCA_EKU_noEKU_ca.cer | Bin 0 -> 664 bytes .../ssl-policy-certs/subCA_EKU_noEKU_leaf.cer | Bin 0 -> 667 bytes .../ssl-policy-certs/subCA_EKU_smime_ca.cer | Bin 0 -> 689 bytes .../ssl-policy-certs/subCA_EKU_smime_leaf.cer | Bin 0 -> 671 bytes .../ssl-policy-certs/subCA_EKU_ssl_ca.cer | Bin 0 -> 695 bytes .../ssl-policy-certs/subCA_EKU_ssl_leaf.cer | Bin 0 -> 678 bytes SecurityTool/macOS/authz.c | 7 +- SecurityTool/macOS/createFVMaster.c | 34 +- SecurityTool/macOS/db_commands.cpp | 2 +- SecurityTool/macOS/identity_find.m | 2 +- SecurityTool/macOS/key_create.c | 8 +- SecurityTool/macOS/keychain_add.c | 28 +- SecurityTool/macOS/keychain_import.c | 6 +- SecurityTool/macOS/keychain_lock.c | 5 +- SecurityTool/macOS/keychain_utilities.c | 7 +- SecurityTool/macOS/readline.c | 8 +- SecurityTool/macOS/requirement.c | 3 +- SecurityTool/macOS/trusted_cert_ssl.m | 18 +- SecurityTool/sharedTool/KeychainCheck.m | 6 - SecurityTool/sharedTool/SecurityCommands.h | 23 + .../sharedTool/add_internet_password.c | 8 +- SecurityTool/sharedTool/builtin_commands.h | 3 + .../sharedTool/ca_revocation_additions.m | 289 ++ .../sharedTool/iOS/entitlements.plist | 2 + .../sharedTool/macOS/entitlements.plist | 2 + SecurityTool/sharedTool/policy_dryrun.m | 17 +- SecurityTool/sharedTool/scep.c | 76 +- SecurityTool/sharedTool/sos.m | 39 +- SecurityTool/sharedTool/sub_commands.h | 3 + SecurityTool/sharedTool/trust_update.m | 24 +- SharedMocks/NSXPCConnectionMock.m | 3 +- .../SWCViewController.h | 2 + .../SWCViewController.m | 2 +- .../entitlements.plist | 19 + TestPlan.xctestplan | 18 - base/SecBase.h | 44 +- base/SecBasePriv.h | 2 +- base/SecInternal.h | 2 +- codesign_wrapper/check_entitlements.c | 2 +- cssm/cssmapple.h | 4 +- experiment/SecExperiment.m | 29 +- experiment/SecExperimentInternal.h | 4 +- experiment/tool/experimentTool.m | 6 +- featureflags/Security.plist | 27 +- .../OctagonTrust/OTCDPRecoveryInformation.h | 1 + .../OTEscrowAuthenticationInformation.h | 1 + header_symlinks/OctagonTrust/OTEscrowRecord.h | 1 + .../OctagonTrust/OTEscrowRecordMetadata.h | 1 + .../OTEscrowRecordMetadataClientMetadata.h | 1 + .../OctagonTrust/OTEscrowTranslation.h | 1 + .../OctagonTrust/OTICDPRecordContext.h | 1 + .../OctagonTrust/OTICDPRecordSilentContext.h | 1 + header_symlinks/OctagonTrust/OctagonTrust.h | 1 + header_symlinks/Security/SFSignInAnalytics.h | 1 - header_symlinks/Security/SecExperimentPriv.h | 2 +- .../Security/certExtensionTemplates.h | 2 +- .../macOS/Security/SecBreadcrumb.h | 1 - .../macOS/Security/SecCertificateBundle.h | 1 - keychain/CoreDataKeychain/SecCDKeychain.m | 2 + .../KeychainDataclassOwner.m | 24 +- .../KeychainStasher-Info.plist | 24 + .../KeychainStasher.entitlements | 10 + keychain/KeychainStasher/KeychainStasher.h | 5 + keychain/KeychainStasher/KeychainStasher.m | 116 + .../KeychainStasher/KeychainStasherProtocol.h | 13 + .../com.apple.security.KeychainStasher.plist | 25 + .../com.apple.security.KeychainStasher.sb | 22 + keychain/KeychainStasher/main.m | 72 + keychain/OctagonTrust/Info.plist | 22 + keychain/OctagonTrust/OTEscrowTranslation.h | 69 + keychain/OctagonTrust/OTEscrowTranslation.m | 396 ++ keychain/OctagonTrust/OctagonTrust.h | 109 + keychain/OctagonTrust/OctagonTrust.m | 657 +++ .../categories/OctagonTrustEscrowRecoverer.h | 27 + .../ot-tests/OctagonTrustTests+Errors.m | 221 + .../OctagonTrustTests-EscrowRecords.m | 722 +++ .../OctagonTrustTests-EscrowTestVectors.h | 415 ++ .../ot-tests/OctagonTrustTests-Info.plist} | 2 +- .../OctagonTrust/ot-tests/OctagonTrustTests.h | 56 + .../reset_ick_account | 20 +- .../CKBridge/SOSCloudKeychainClient.c | 4 +- keychain/SecureObjectSync/CKDSimulatedStore.h | 2 +- keychain/SecureObjectSync/CKDSimulatedStore.m | 12 +- .../Regressions/CKDSimulatedAccount.m | 3 +- .../Regressions/SOSRegressionUtilities.h | 3 + .../Regressions/SOSRegressionUtilities.m | 12 +- .../Regressions/SOSTestDataSource.c | 2 +- .../Regressions/sc-130-resignationticket.c | 12 +- .../Regressions/sc-150-backupkeyderivation.c | 14 +- .../Regressions/sc-153-backupslicekeybag.c | 47 +- .../Regressions/sc-20-keynames.m | 9 +- .../Regressions/sc-25-soskeygen.c | 18 +- .../Regressions/sc-30-peerinfo.c | 9 +- .../Regressions/sc-31-peerinfo-simplefuzz.c | 8 +- .../Regressions/sc-40-circle.c | 10 +- .../Regressions/sc-42-circlegencount.c | 12 +- .../Regressions/sc-45-digestvector.c | 11 +- keychain/SecureObjectSync/SOSAccount.h | 20 +- keychain/SecureObjectSync/SOSAccount.m | 795 +-- keychain/SecureObjectSync/SOSAccountBackup.m | 13 +- .../SOSAccountCloudParameters.m | 12 +- .../SOSAccountConfiguration.proto | 1 + .../SecureObjectSync/SOSAccountCredentials.m | 33 +- .../SecureObjectSync/SOSAccountFullPeerInfo.m | 91 +- keychain/SecureObjectSync/SOSAccountGhost.m | 208 +- keychain/SecureObjectSync/SOSAccountLog.m | 1 - .../SecureObjectSync/SOSAccountPersistence.m | 35 +- keychain/SecureObjectSync/SOSAccountPriv.h | 22 +- .../SecureObjectSync/SOSAccountRecovery.m | 5 +- keychain/SecureObjectSync/SOSAccountRings.m | 30 +- .../SecureObjectSync/SOSAccountTransaction.m | 46 +- keychain/SecureObjectSync/SOSAccountTrust.m | 8 +- .../SOSAccountTrustClassic+Circle.h | 3 +- .../SOSAccountTrustClassic+Circle.m | 101 +- .../SOSAccountTrustClassic+Expansion.h | 1 - .../SOSAccountTrustClassic+Expansion.m | 64 +- .../SOSAccountTrustClassic+Identity.h | 2 +- .../SOSAccountTrustClassic+Identity.m | 59 +- .../SecureObjectSync/SOSAccountTrustClassic.h | 2 +- .../SecureObjectSync/SOSAccountTrustClassic.m | 47 +- keychain/SecureObjectSync/SOSAccountUpdate.m | 37 +- .../SecureObjectSync/SOSAccountViewSync.m | 2 +- keychain/SecureObjectSync/SOSAuthKitHelpers.m | 39 +- .../SecureObjectSync/SOSBackupSliceKeyBag.m | 23 +- keychain/SecureObjectSync/SOSChangeTracker.h | 2 + keychain/SecureObjectSync/SOSCircle.c | 2 +- keychain/SecureObjectSync/SOSCircleDer.c | 25 +- keychain/SecureObjectSync/SOSCirclePriv.h | 2 + keychain/SecureObjectSync/SOSCloudCircle.h | 25 +- keychain/SecureObjectSync/SOSCloudCircle.m | 527 +- .../SecureObjectSync/SOSCloudCircleInternal.h | 18 + keychain/SecureObjectSync/SOSCoder.c | 17 +- keychain/SecureObjectSync/SOSControlHelper.m | 61 +- keychain/SecureObjectSync/SOSControlServer.m | 28 +- keychain/SecureObjectSync/SOSECWrapUnwrap.c | 6 +- keychain/SecureObjectSync/SOSEngine.c | 48 +- keychain/SecureObjectSync/SOSEngine.h | 1 + keychain/SecureObjectSync/SOSExports.exp-in | 18 +- keychain/SecureObjectSync/SOSFullPeerInfo.h | 1 + keychain/SecureObjectSync/SOSFullPeerInfo.m | 44 +- keychain/SecureObjectSync/SOSGenCount.c | 2 +- keychain/SecureObjectSync/SOSInternal.h | 8 + keychain/SecureObjectSync/SOSInternal.m | 46 +- keychain/SecureObjectSync/SOSIntervalEvent.m | 17 +- keychain/SecureObjectSync/SOSKVSKeys.h | 1 + keychain/SecureObjectSync/SOSMessage.c | 22 +- keychain/SecureObjectSync/SOSPeerInfo.h | 15 +- keychain/SecureObjectSync/SOSPeerInfo.m | 72 +- keychain/SecureObjectSync/SOSPeerInfoDER.m | 7 +- keychain/SecureObjectSync/SOSPeerInfoPriv.h | 5 + keychain/SecureObjectSync/SOSPeerInfoV2.h | 2 + keychain/SecureObjectSync/SOSPeerInfoV2.m | 2 +- keychain/SecureObjectSync/SOSPeerOTRTimer.m | 5 - .../SecureObjectSync/SOSPeerRateLimiter.m | 6 +- keychain/SecureObjectSync/SOSPiggyback.m | 4 +- keychain/SecureObjectSync/SOSRecoveryKeyBag.m | 4 +- keychain/SecureObjectSync/SOSRingBackup.m | 1 - keychain/SecureObjectSync/SOSRingBasic.m | 1 - .../SOSRingConcordanceTrust.c | 1 - keychain/SecureObjectSync/SOSRingDER.c | 9 +- .../SecureObjectSync/SOSRingPeerInfoUtils.c | 1 - keychain/SecureObjectSync/SOSRingRecovery.m | 1 - keychain/SecureObjectSync/SOSRingUtils.c | 24 +- keychain/SecureObjectSync/SOSRingV0.m | 1 - keychain/SecureObjectSync/SOSTransport.m | 2 +- .../SecureObjectSync/SOSTransportCircle.m | 3 +- .../SecureObjectSync/SOSTransportCircleCK.m | 7 +- .../SecureObjectSync/SOSTransportCircleKVS.m | 5 +- .../SOSTransportKeyParameter.m | 5 +- .../SecureObjectSync/SOSTransportMessage.m | 15 +- .../SecureObjectSync/SOSTransportMessageKVS.m | 10 +- keychain/SecureObjectSync/SOSTypes.h | 8 +- keychain/SecureObjectSync/SOSUserKeygen.m | 48 +- keychain/SecureObjectSync/SOSViews.m | 20 + .../Tool/accountCirclesViewsPrint.m | 3 +- .../SecureObjectSync/Tool/keychain_sync.m | 17 +- .../SOSAccountConfiguration.h | 8 +- .../SOSAccountConfiguration.m | 50 + keychain/SecurityUnitTests/SecItemTests.m | 4 +- keychain/SecurityUnitTests/SecKeyTests.m | 24 +- keychain/SigninMetrics/OctagonSignPosts.h | 12 +- keychain/SigninMetrics/SFSignInAnalytics.h | 87 - keychain/SigninMetrics/SFSignInAnalytics.m | 460 -- .../tests/SFSignInAnalyticsTests.m | 514 -- .../SecRemoteDevice.m | 7 +- .../OctagonTriesteTests/OctagonTests.swift | 5 - .../BottledPeer/BottledPeer.swift | 41 +- .../BottledPeer/EscrowKeys.swift | 31 +- keychain/TrustedPeersHelper/Client.swift | 289 +- keychain/TrustedPeersHelper/Container.swift | 1508 +++--- .../TrustedPeersHelper/ContainerMap.swift | 71 +- .../Container_BottledPeers.swift | 133 +- .../Container_EscrowRecords.swift | 202 + .../Container_MachineIDs.swift | 6 +- .../TrustedPeersHelper/Container_Peers.swift | 42 + .../Container_RecoveryKey.swift | 39 +- .../Container_UserSync.swift | 41 + .../TrustedPeersHelper/OctagonPeerKeys.swift | 2 +- keychain/TrustedPeersHelper/Policy.swift | 142 +- .../RecoveryKey/RecoverKeySet.swift | 25 +- .../RecoveryKey/RecoveryKey.swift | 30 +- .../TrustedPeersHelper/TPHObjcTranslation.m | 2 +- .../TrustedPeersHelper-Bridging-Header.h | 10 +- .../TrustedPeersHelper-entitlements.plist | 21 + .../TrustedPeersHelper_2.xcdatamodel/contents | 51 +- .../TrustedPeersHelperProtocol.h | 58 +- .../TrustedPeersHelperProtocol.m | 81 +- .../com.apple.TrustedPeersHelper.sb | 41 + keychain/TrustedPeersHelper/main.swift | 31 + .../proto/generated_source/OTBottleContents.h | 1 - .../.swiftlint.yml | 1 + .../ContainerSync.swift | 90 +- .../FakeCuttlefish.swift | 130 +- .../MockCuttlefish.swift | 5 +- ...ustedPeersHelperUnitTests-BridgingHeader.h | 1 + .../TrustedPeersHelperUnitTests.swift | 957 +++- keychain/analytics/SecEventMetric.m | 3 +- keychain/analytics/SecMetrics.m | 4 +- keychain/behavior/SFBehavior.h | 72 - keychain/behavior/SFBehavior.m | 140 - keychain/ckks/CKKS.h | 120 +- keychain/ckks/CKKS.m | 76 +- keychain/ckks/CKKSAccountStateTracker.h | 1 + keychain/ckks/CKKSAccountStateTracker.m | 54 +- keychain/ckks/CKKSAnalytics.h | 22 +- keychain/ckks/CKKSAnalytics.m | 64 +- .../ckks/CKKSCheckKeyHierarchyOperation.h | 23 + .../ckks/CKKSCheckKeyHierarchyOperation.m | 198 + keychain/ckks/CKKSConstants.m | 11 +- keychain/ckks/CKKSControl.h | 2 + keychain/ckks/CKKSControl.m | 40 +- keychain/ckks/CKKSControlProtocol.h | 2 +- keychain/ckks/CKKSControlProtocol.m | 36 +- keychain/ckks/CKKSControlServer.m | 4 +- keychain/ckks/CKKSCreateCKZoneOperation.h | 23 + keychain/ckks/CKKSCreateCKZoneOperation.m | 121 + keychain/ckks/CKKSCurrentKeyPointer.m | 4 +- keychain/ckks/CKKSDeleteCKZoneOperation.h | 22 + keychain/ckks/CKKSDeleteCKZoneOperation.m | 101 + keychain/ckks/CKKSDeviceStateEntry.m | 4 +- .../CKKSFetchAllRecordZoneChangesOperation.m | 42 +- keychain/ckks/CKKSFixups.h | 6 +- keychain/ckks/CKKSFixups.m | 70 +- keychain/ckks/CKKSGroupOperation.m | 73 +- keychain/ckks/CKKSHealKeyHierarchyOperation.h | 12 +- keychain/ckks/CKKSHealKeyHierarchyOperation.m | 185 +- keychain/ckks/CKKSHealTLKSharesOperation.h | 18 +- keychain/ckks/CKKSHealTLKSharesOperation.m | 390 +- keychain/ckks/CKKSIncomingQueueEntry.h | 3 +- keychain/ckks/CKKSIncomingQueueEntry.m | 2 + keychain/ckks/CKKSIncomingQueueOperation.h | 19 +- keychain/ckks/CKKSIncomingQueueOperation.m | 638 ++- keychain/ckks/CKKSItem.m | 28 +- keychain/ckks/CKKSItemEncrypter.m | 6 +- keychain/ckks/CKKSKey.h | 16 + keychain/ckks/CKKSKey.m | 153 +- keychain/ckks/CKKSKeychainBackedKey.m | 32 +- keychain/ckks/CKKSKeychainView.h | 164 +- keychain/ckks/CKKSKeychainView.m | 3412 +++++-------- keychain/ckks/CKKSLocalResetOperation.h | 26 + keychain/ckks/CKKSLocalResetOperation.m | 120 + keychain/ckks/CKKSLocalSynchronizeOperation.m | 36 +- keychain/ckks/CKKSLockStateTracker.m | 25 +- keychain/ckks/CKKSLogging.m | 33 + keychain/ckks/CKKSManifest.m | 16 +- keychain/ckks/CKKSManifestLeafRecord.m | 8 +- keychain/ckks/CKKSMirrorEntry.m | 2 +- keychain/ckks/CKKSNewTLKOperation.h | 9 +- keychain/ckks/CKKSNewTLKOperation.m | 99 +- keychain/ckks/CKKSNotifier.m | 4 +- keychain/ckks/CKKSOperationDependencies.h | 72 + keychain/ckks/CKKSOperationDependencies.m | 71 + keychain/ckks/CKKSOutgoingQueueEntry.h | 7 +- keychain/ckks/CKKSOutgoingQueueEntry.m | 137 +- keychain/ckks/CKKSOutgoingQueueOperation.h | 17 +- keychain/ckks/CKKSOutgoingQueueOperation.m | 287 +- keychain/ckks/CKKSPeer.m | 6 +- keychain/ckks/CKKSPeerProvider.h | 11 + keychain/ckks/CKKSPeerProvider.m | 200 + .../ckks/CKKSProcessReceivedKeysOperation.h | 18 +- .../ckks/CKKSProcessReceivedKeysOperation.m | 158 +- keychain/ckks/CKKSProvideKeySetOperation.h | 1 - keychain/ckks/CKKSProvideKeySetOperation.m | 32 +- keychain/ckks/CKKSRateLimiter.m | 4 +- keychain/ckks/CKKSReachabilityTracker.m | 10 +- keychain/ckks/CKKSRecordHolder.m | 2 +- .../CKKSReencryptOutgoingItemsOperation.h | 12 +- .../CKKSReencryptOutgoingItemsOperation.m | 74 +- keychain/ckks/CKKSResultOperation.h | 2 +- keychain/ckks/CKKSResultOperation.m | 27 +- keychain/ckks/CKKSSIV.h | 6 + keychain/ckks/CKKSSIV.m | 14 +- keychain/ckks/CKKSSQLDatabaseObject.h | 27 + keychain/ckks/CKKSSQLDatabaseObject.m | 112 +- keychain/ckks/CKKSScanLocalItemsOperation.h | 21 +- keychain/ckks/CKKSScanLocalItemsOperation.m | 636 ++- keychain/ckks/CKKSStates.h | 50 + keychain/ckks/CKKSStates.m | 65 + keychain/ckks/CKKSSynchronizeOperation.m | 23 +- keychain/ckks/CKKSTLKShare.h | 2 +- keychain/ckks/CKKSTLKShare.m | 13 +- keychain/ckks/CKKSTLKShareRecord.m | 2 +- .../CKKSUpdateCurrentItemPointerOperation.m | 50 +- .../ckks/CKKSUpdateDeviceStateOperation.m | 12 +- keychain/ckks/CKKSViewManager.h | 30 +- keychain/ckks/CKKSViewManager.m | 370 +- keychain/ckks/CKKSZone.h | 138 - keychain/ckks/CKKSZone.m | 465 -- keychain/ckks/CKKSZoneChangeFetcher.h | 10 +- keychain/ckks/CKKSZoneChangeFetcher.m | 53 +- keychain/ckks/CKKSZoneModifier.m | 31 +- keychain/ckks/CKKSZoneStateEntry.h | 5 +- keychain/ckks/CKKSZoneStateEntry.m | 32 +- keychain/ckks/CloudKitCategories.m | 2 +- keychain/ckks/CloudKitDependencies.h | 8 +- keychain/ckks/NSOperationCategories.m | 4 +- keychain/ckks/OctagonAPSReceiver.h | 26 +- keychain/ckks/OctagonAPSReceiver.m | 222 +- keychain/ckks/RateLimiter.m | 14 +- keychain/ckks/tests/AutoreleaseTest.c | 3 +- .../ckks/tests/CKKSAESSIVEncryptionTests.m | 54 +- keychain/ckks/tests/CKKSAPSHandlingTests.m | 25 +- keychain/ckks/tests/CKKSCloudKitTests.m | 605 --- keychain/ckks/tests/CKKSConditionTests.m | 1 - .../ckks/tests/CKKSDeviceStateUploadTests.m | 20 +- keychain/ckks/tests/CKKSFetchTests.m | 20 +- keychain/ckks/tests/CKKSLoggerTests.m | 24 +- keychain/ckks/tests/CKKSManifestTests.m | 29 +- .../ckks/tests/CKKSMockSOSPresentAdapter.h | 7 + .../ckks/tests/CKKSMockSOSPresentAdapter.m | 35 +- keychain/ckks/tests/CKKSOperationTests.m | 32 + keychain/ckks/tests/CKKSSOSTests.m | 59 +- keychain/ckks/tests/CKKSSQLTests.m | 143 +- .../tests/CKKSServerValidationRecoveryTests.m | 6 +- .../tests/CKKSTLKSharingEncryptionTests.m | 74 +- keychain/ckks/tests/CKKSTLKSharingTests.m | 65 +- keychain/ckks/tests/CKKSTests+API.m | 306 +- keychain/ckks/tests/CKKSTests+Coalesce.m | 120 +- .../ckks/tests/CKKSTests+CurrentPointerAPI.m | 20 +- .../tests/CKKSTests+ForwardCompatibility.m | 486 ++ .../ckks/tests/CKKSTests+ItemSyncChoice.m | 244 + keychain/ckks/tests/CKKSTests+MultiZone.m | 75 +- keychain/ckks/tests/CKKSTests.m | 1081 +++- .../tests/CloudKitKeychainSyncingFixupTests.m | 75 +- .../tests/CloudKitKeychainSyncingMockXCTest.h | 13 +- .../tests/CloudKitKeychainSyncingMockXCTest.m | 187 +- .../tests/CloudKitKeychainSyncingTestsBase.h | 5 + keychain/ckks/tests/CloudKitMockXCTest.h | 11 +- keychain/ckks/tests/CloudKitMockXCTest.m | 107 +- keychain/ckks/tests/MockCloudKit.h | 3 + keychain/ckks/tests/MockCloudKit.m | 33 +- keychain/ckks/tests/OctagonAPSReceiverTests.m | 52 +- keychain/ckks/tests/RateLimiterTests.m | 6 +- keychain/ckks/tests/gen_test_plist.py | 5 +- keychain/ckksctl/ckksctl.m | 22 +- .../escrowrequest/EscrowRequestController.m | 1 + .../escrowrequest/EscrowRequestXPCProtocol.m | 34 +- keychain/headers/SecAccessControl.h | 2 +- keychain/headers/SecIdentityPriv.h | 85 - keychain/headers/SecImportExport.h | 12 +- keychain/headers/SecImportExportPriv.h | 2 +- keychain/headers/SecItem.h | 10 +- keychain/headers/SecItemPriv.h | 48 +- keychain/headers/SecKey.h | 52 +- keychain/headers/SecKeyPriv.h | 12 +- keychain/headers/SecSharedCredential.h | 19 +- keychain/ot/CuttlefishXPCWrapper.m | 117 +- keychain/ot/OTClientStateMachine.m | 3 +- keychain/ot/OTClientVoucherOperation.m | 3 +- keychain/ot/OTClique+Private.h | 24 + keychain/ot/OTClique.h | 54 +- keychain/ot/OTClique.m | 418 +- keychain/ot/OTConstants.h | 16 + keychain/ot/OTConstants.m | 116 +- keychain/ot/OTControl.h | 24 +- keychain/ot/OTControl.m | 49 +- keychain/ot/OTControlProtocol.h | 25 +- keychain/ot/OTControlProtocol.m | 72 +- keychain/ot/OTCuttlefishAccountStateHolder.h | 3 - keychain/ot/OTCuttlefishAccountStateHolder.m | 34 - keychain/ot/OTCuttlefishContext.h | 21 +- keychain/ot/OTCuttlefishContext.m | 791 ++- keychain/ot/OTDefines.h | 8 +- keychain/ot/OTDefines.m | 2 - .../ot/OTDetermineCDPBitStatusOperation.m | 2 +- keychain/ot/OTDeviceInformationAdapter.h | 2 +- keychain/ot/OTDeviceInformationAdapter.m | 2 +- keychain/ot/OTEnsureOctagonKeyConsistency.m | 12 +- keychain/ot/OTEstablishOperation.m | 20 +- keychain/ot/OTFetchCKKSKeysOperation.h | 11 +- keychain/ot/OTFetchCKKSKeysOperation.m | 123 +- keychain/ot/OTFetchViewsOperation.m | 12 +- keychain/ot/OTFollowup.h | 2 +- keychain/ot/OTFollowup.m | 2 +- keychain/ot/OTJoinWithVoucherOperation.h | 10 +- keychain/ot/OTJoinWithVoucherOperation.m | 39 +- keychain/ot/OTJoiningConfiguration.m | 6 +- keychain/ot/OTLocalCuttlefishReset.h | 12 +- keychain/ot/OTLocalCuttlefishReset.m | 45 +- keychain/ot/OTManager.h | 4 + keychain/ot/OTManager.m | 187 +- ...odifyUserControllableViewStatusOperation.h | 47 + ...odifyUserControllableViewStatusOperation.m | 181 + keychain/ot/OTPreloadOctagonKeysOperation.h | 47 + keychain/ot/OTPreloadOctagonKeysOperation.m | 109 + keychain/ot/OTPrepareOperation.m | 14 +- keychain/ot/OTRamping.m | 3 +- .../ot/OTResetCKKSZonesLackingTLKsOperation.m | 18 +- keychain/ot/OTSOSAdapter.h | 6 +- keychain/ot/OTSOSAdapter.m | 135 +- keychain/ot/OTSOSUpgradeOperation.m | 76 +- keychain/ot/OTSetRecoveryKeyOperation.m | 12 +- keychain/ot/OTStates.h | 20 + keychain/ot/OTStates.m | 32 +- keychain/ot/OTUpdateTPHOperation.m | 45 +- .../ot/OTUpdateTrustedDeviceListOperation.m | 60 +- keychain/ot/OTUploadNewCKKSTLKsOperation.h | 1 + keychain/ot/OTUploadNewCKKSTLKsOperation.m | 14 +- keychain/ot/OTVouchWithBottleOperation.h | 6 +- keychain/ot/OTVouchWithBottleOperation.m | 45 +- keychain/ot/OTVouchWithRecoveryKeyOperation.h | 6 +- keychain/ot/OTVouchWithRecoveryKeyOperation.m | 38 +- keychain/ot/OctagonCKKSPeerAdapter.h | 12 +- keychain/ot/OctagonCKKSPeerAdapter.m | 25 +- keychain/ot/OctagonCheckTrustStateOperation.m | 4 +- keychain/ot/OctagonControlServer.m | 2 +- keychain/ot/OctagonFlags.m | 6 +- keychain/ot/OctagonPendingFlag.h | 3 + keychain/ot/OctagonPendingFlag.m | 15 + keychain/ot/OctagonStateMachine.h | 14 +- keychain/ot/OctagonStateMachine.m | 73 +- keychain/ot/OctagonStateMachineHelpers.h | 12 + keychain/ot/OctagonStateMachineHelpers.m | 43 +- keychain/ot/OctagonStateMachineObservers.h | 25 +- keychain/ot/OctagonStateMachineObservers.m | 87 + .../OTAccountMetadataClassC+KeychainSupport.h | 6 +- .../OTAccountMetadataClassC+KeychainSupport.m | 8 +- .../ot/categories/OctagonEscrowRecoverer.h | 6 +- .../ot/proto/OTAccountMetadataClassC.proto | 13 +- .../ot/proto/OTCDPRecoveryInformation.proto | 37 + keychain/ot/proto/OTEscrowRecord.proto | 74 + keychain/ot/proto/OTPairingMessage.proto | 15 + .../OTAccountMetadataClassC.h | 22 +- .../OTAccountMetadataClassC.m | 103 +- .../OTCDPRecoveryInformation.h | 66 + .../OTCDPRecoveryInformation.m | 409 ++ .../OTEscrowAuthenticationInformation.h | 71 + .../OTEscrowAuthenticationInformation.m | 434 ++ .../proto/generated_source/OTEscrowRecord.h | 207 + .../proto/generated_source/OTEscrowRecord.m | 695 +++ .../generated_source/OTEscrowRecordMetadata.h | 73 + .../generated_source/OTEscrowRecordMetadata.m | 452 ++ .../OTEscrowRecordMetadataClientMetadata.h | 86 + .../OTEscrowRecordMetadataClientMetadata.m | 584 +++ .../ot/proto/generated_source/OTGlobalEnums.h | 43 + .../generated_source/OTICDPRecordContext.h | 42 + .../generated_source/OTICDPRecordContext.m | 194 + .../OTICDPRecordSilentContext.h | 42 + .../OTICDPRecordSilentContext.m | 194 + .../proto/generated_source/OTPairingMessage.h | 12 +- .../proto/generated_source/OTPairingMessage.m | 104 + .../OTSponsorToApplicantRound1M2.m | 2 +- .../OTSupportOctagonMessage.h | 43 + .../OTSupportOctagonMessage.m | 151 + .../generated_source/OTSupportSOSMessage.h | 43 + .../generated_source/OTSupportSOSMessage.m | 151 + keychain/ot/proto/source/OTSOSMessage.h | 48 - keychain/ot/tests/gen_test_plist.py | 24 +- keychain/ot/tests/octagon/.swiftlint.yml | 1 + .../octagon/OctagonDataPersistenceTests.swift | 3 +- .../ot/tests/octagon/OctagonPolicyTests.swift | 57 + .../ot/tests/octagon/OctagonTestMocks.swift | 23 +- .../tests/octagon/OctagonTests+Account.swift | 20 +- .../ot/tests/octagon/OctagonTests+CKKS.swift | 405 ++ .../OctagonTests+CKKSConfiguration.swift | 45 +- .../OctagonTests+CloudKitAccount.swift | 72 +- .../octagon/OctagonTests+CoreFollowUp.swift | 28 +- .../octagon/OctagonTests+DeviceList.swift | 121 +- .../octagon/OctagonTests+ErrorHandling.swift | 103 +- .../octagon/OctagonTests+EscrowRecords.swift | 788 +++ .../octagon/OctagonTests+EscrowRecovery.swift | 202 +- .../OctagonTests+EscrowTestVectors.swift | 1872 +++++++ .../OctagonTests+ForwardCompatibility.swift | 319 +- .../octagon/OctagonTests+HealthCheck.swift | 279 +- .../tests/octagon/OctagonTests+Helpers.swift | 71 + .../octagon/OctagonTests+RecoveryKey.swift | 322 +- .../ot/tests/octagon/OctagonTests+Reset.swift | 100 +- .../ot/tests/octagon/OctagonTests+SOS.swift | 31 +- .../octagon/OctagonTests+SOSUpgrade.swift | 403 +- .../octagon/OctagonTests-BridgingHeader.h | 6 + keychain/ot/tests/octagon/OctagonTests.swift | 364 +- .../octagon/OctagonTestsXPCConnections.swift | 4 +- .../OctagonPairingTests+Piggybacking.swift | 504 +- ...OctagonPairingTests+ProxMultiClients.swift | 3 - .../OctagonPairingTests+ProximitySetup.swift | 2 - .../octagon/Pairing/OctagonPairingTests.swift | 55 +- .../ot/tests/octagon/TestsObjcTranslation.h | 8 + .../ot/tests/octagon/TestsObjcTranslation.m | 115 +- keychain/otctl/OTControlCLI.h | 56 +- keychain/otctl/OTControlCLI.m | 281 +- keychain/otctl/otctl.m | 68 + keychain/otpaird/OTPairingConstants.h | 3 +- keychain/otpaird/OTPairingPacketContext.m | 15 +- keychain/otpaird/OTPairingService.m | 16 +- keychain/otpaird/OTPairingSession.m | 3 +- .../otpaird/otpaird.iphoneos.entitlements | 17 +- keychain/otpaird/otpaird.watchos.entitlements | 16 +- keychain/securityd/PolicyReporter.m | 9 +- .../securityd/Regressions/SOSAccountTesting.h | 4 +- .../Regressions/SOSTransportTestTransports.m | 17 +- .../Regressions/SecdTestKeychainUtilities.c | 1 + .../Regressions/secd-100-initialsync.m | 9 +- .../Regressions/secd-130-other-peer-views.m | 8 +- .../Regressions/secd-154-engine-backoff.m | 10 +- .../secd-155-otr-negotiation-monitor.m | 9 +- .../securityd/Regressions/secd-200-logstate.m | 9 +- .../securityd/Regressions/secd-201-coders.m | 9 +- .../Regressions/secd-202-recoverykey.m | 12 +- .../Regressions/secd-210-keyinterest.m | 15 +- .../Regressions/secd-33-keychain-ctk.m | 229 +- .../Regressions/secd-36-ks-encrypt.m | 10 +- .../securityd/Regressions/secd-50-account.m | 20 +- .../securityd/Regressions/secd-50-message.m | 10 +- .../Regressions/secd-51-account-inflate.m | 163 +- .../Regressions/secd-52-account-changed.m | 10 +- .../secd-52-offering-gencount-reset.m | 17 +- .../Regressions/secd-55-account-circle.m | 12 +- .../secd-55-account-incompatibility.m | 10 +- .../Regressions/secd-56-account-apply.m | 10 +- .../secd-57-1-account-last-standing.m | 10 +- .../Regressions/secd-57-account-leave.m | 11 +- .../Regressions/secd-58-password-change.m | 18 +- .../Regressions/secd-59-account-cleanup.m | 9 +- .../secd-60-account-cloud-identity.m | 9 +- ...d-61-account-leave-not-in-kansas-anymore.m | 11 +- .../Regressions/secd-62-account-backup.m | 25 +- .../secd-63-account-resurrection.m | 9 +- .../Regressions/secd-64-circlereset.m | 9 +- .../secd-65-account-retirement-reset.m | 9 +- .../Regressions/secd-66-account-recovery.m | 20 +- .../securityd/Regressions/secd-668-ghosts.m | 218 - .../Regressions/secd-67-prefixedKeyIDs.m | 8 +- .../secd-68-fullPeerInfoIntegrity.m | 121 + .../Regressions/secd-70-engine-corrupt.m | 12 +- .../Regressions/secd-70-engine-smash.m | 11 +- .../securityd/Regressions/secd-70-engine.m | 48 +- .../Regressions/secd-70-otr-remote.m | 9 +- .../Regressions/secd-71-engine-save.m | 11 +- .../Regressions/secd-74-engine-beer-servers.m | 11 +- .../Regressions/secd-75-engine-views.m | 12 +- .../Regressions/secd-80-views-alwayson.m | 6 + .../Regressions/secd-80-views-basic.m | 16 +- .../securityd/Regressions/secd-81-item-acl.m | 24 +- .../secd60-account-cloud-exposure.m | 13 +- .../securityd/Regressions/secd_regressions.h | 2 +- keychain/securityd/SFKeychainControlManager.m | 7 +- keychain/securityd/SFKeychainServer.m | 11 + keychain/securityd/SOSCloudCircleServer.h | 24 +- keychain/securityd/SOSCloudCircleServer.m | 602 +-- keychain/securityd/SecDbBackupManager.h | 19 +- keychain/securityd/SecDbBackupManager.m | 116 +- .../securityd/SecDbBackupManager_Internal.h | 2 +- keychain/securityd/SecDbItem.c | 127 +- keychain/securityd/SecDbItem.h | 18 +- keychain/securityd/SecDbKeychainItem.h | 42 +- keychain/securityd/SecDbKeychainItem.m | 100 +- keychain/securityd/SecDbKeychainItemV7.m | 29 +- .../securityd/SecDbKeychainMetadataKeyStore.h | 11 +- .../securityd/SecDbKeychainMetadataKeyStore.m | 543 +- .../SecDbKeychainSerializedMetadataKey.proto | 9 + .../SecDbKeychainSerializedMetadataKey.h | 55 + .../SecDbKeychainSerializedMetadataKey.m | 294 ++ keychain/securityd/SecDbQuery.c | 20 +- keychain/securityd/SecDbQuery.h | 12 +- keychain/securityd/SecItemBackupServer.c | 10 + keychain/securityd/SecItemBackupServer.h | 1 + keychain/securityd/SecItemDataSource.c | 33 +- keychain/securityd/SecItemDb.c | 167 +- keychain/securityd/SecItemDb.h | 1 + keychain/securityd/SecItemSchema.c | 418 +- keychain/securityd/SecItemServer+SWC.h | 46 + keychain/securityd/SecItemServer+SWC.m | 192 + keychain/securityd/SecItemServer.c | 603 ++- keychain/securityd/SecItemServer.h | 9 +- keychain/securityd/SecKeybagSupport.c | 4 +- keychain/securityd/SecOTRRemote.m | 2 +- keychain/securityd/com.apple.secd.sb | 3 + keychain/securityd/entitlements.plist | 6 + keychain/securityd/spi.c | 10 +- keychain/tpctl/main.swift | 71 +- libsecurity_smime/Security | 1 - libsecurity_smime/lib/CMSDecoder.c | 1 - libsecurity_smime/lib/CMSEncoder.c | 2 +- libsecurity_smime/lib/CMSUtils.h | 6 +- libsecurity_smime/lib/cmsdigest.c | 2 +- libsecurity_smime/lib/cmssiginfo.c | 18 +- libsecurity_smime/lib/crypto-embedded.c | 50 +- libsecurity_smime/security_smime | 1 - ntlm/NtlmGenerator.c | 12 +- ntlm/ntlmBlobPriv.c | 21 +- protocol/SecProtocol.c | 192 +- protocol/SecProtocolConfiguration.h | 5 +- protocol/SecProtocolConfiguration.m | 42 +- protocol/SecProtocolConfigurationTest.m | 49 +- protocol/SecProtocolHelper.m | 10 - protocol/SecProtocolInternal.h | 22 +- protocol/SecProtocolMetadata.h | 5 +- protocol/SecProtocolOptions.h | 36 +- protocol/SecProtocolPriv.h | 243 +- protocol/SecProtocolTest.m | 170 +- protocol/SecProtocolTypes.m | 62 +- protocol/test_data/example1.json | 8 +- secacltests/secacltests-entitlements.plist | 2 + secdtests/secdtests-entitlements.plist | 6 +- secdxctests/CDKeychainTests.m | 4 +- secdxctests/KeychainAPITests.m | 360 +- secdxctests/KeychainAppClipTests.m | 304 ++ secdxctests/KeychainBackupTests.m | 118 + secdxctests/KeychainCryptoTests.m | 156 +- secdxctests/KeychainEntitlementsTest.m | 81 +- secdxctests/KeychainXCTest.h | 4 +- secdxctests/KeychainXCTest.m | 178 +- secdxctests/SFCredentialStoreTests.m | 2 +- secdxctests/secdxctests-entitlements.plist | 33 + sectask/SecEntitlements.h | 20 +- sectask/SecTask.c | 72 +- sectask/SecTask.h | 2 +- sectask/SystemEntitlements.h | 17 + securityd/etc/com.apple.securityd.sb | 3 +- .../project.pbxproj | 18 +- .../securityd_service/main.c | 20 +- .../securityd_service_client.c | 4 +- .../securityd_service_client.h | 2 +- securityd/src/ccaudit_extensions.cpp | 2 +- securityd/src/credential.cpp | 5 +- securityd/src/kcdatabase.cpp | 106 +- securityd/src/keychainstasherinterface.h | 15 + securityd/src/keychainstasherinterface.m | 88 + securityd/src/main.cpp | 76 +- securityd/src/notifications.cpp | 27 - securityd/src/notifications.h | 1 - securityd/src/process.cpp | 3 + securityd/src/securityd.entitlements | 2 + securityd/src/server.cpp | 27 +- securityd/src/token.cpp | 11 - securityd/src/transition.cpp | 7 +- sslViewer/SSLViewer.c | 25 +- supd/Tests/SupdTests.m | 15 +- supd/com.apple.securityuploadd.sb | 81 + supd/main.m | 40 + supd/securityuploadd-Entitlements.plist | 2 + supd/supd.h | 8 +- supd/supd.m | 132 +- supdctl/main.m | 2 - ...st => SecDbBackupTests-Entitlements.plist} | 2 + tests/SecDbBackupTests/SecDbBackupTests.m | 88 +- tests/SecDbBackupTests/SecDbBackupTests.plist | 27 - tests/SecDbBackupTests/SecDbBackupTestsBase.h | 19 + tests/SecDbBackupTests/SecDbBackupTestsBase.m | 74 + .../KeychainEntitledTestApp/AppDelegate.h | 16 + .../KeychainEntitledTestApp/AppDelegate.m | 25 + .../AppIcon.appiconset/Contents.json | 0 .../KeychainEntitledTestApp}/Info.plist | 5 + .../KeychainEntitledTestApp/ViewController.h | 15 + .../KeychainEntitledTestApp}/ViewController.m | 28 +- .../KeychainEntitledTestApp}/main.m | 20 +- .../KeychainEntitledTestRunner.entitlements | 17 +- .../KeychainEntitledTestRunner.m | 14 +- .../DaemonTests/PersonalizationTests.m | 19 + .../DaemonTests/TrustDaemonTestCase.h | 1 - .../EvaluationTests/AllowlistBlocklistTests.m | 409 ++ .../AllowlistBlocklistTests_data.h | 1691 ++++++ .../EvaluationTests/CAIssuerTests.m | 176 + .../EvaluationTests/CAIssuerTests_data.h | 413 ++ tests/TrustTests/EvaluationTests/CTTests.m | 49 + .../TrustTests/EvaluationTests/KeySizeTests.m | 2 +- .../EvaluationTests/NameConstraintsTests.m | 3 + .../EvaluationTests/PathParseTests.m | 7 +- .../EvaluationTests/PathParseTests_data.h | 126 +- .../TrustTests/EvaluationTests/PolicyTests.m | 167 +- .../EvaluationTests/SMIMEPolicyTests.m | 439 ++ .../EvaluationTests/SSLPolicyTests.m | 193 +- .../EvaluationTests/SSLPolicyTests_data.h | 290 ++ .../EvaluationTests/TrustEvaluationTestCase.h | 6 + .../EvaluationTests/TrustEvaluationTestCase.m | 67 +- .../EvaluationTests/TrustSettingsTests.m | 261 +- .../EvaluationTests/TrustSettingsTests_data.h | 8 +- tests/TrustTests/EvaluationTests/ValidTests.m | 224 + .../EvaluationTests/VerifyDateTests.m | 45 +- .../EvaluationTests/VerifyDateTests_data.h | 187 + .../CertificateInterfaceTests.m | 35 + .../CertificateInterfaceTests_data.h | 73 + .../FrameworkTests/CertificateParseTests.m | 17 + .../FrameworkTests/TrustInterfaceTests.m | 38 +- .../SMIMEPolicyTests-data/any_eku.cer | Bin 0 -> 910 bytes .../SMIMEPolicyTests-data/common_name.cer | Bin 0 -> 831 bytes .../SMIMEPolicyTests-data/data_encipher.cer | Bin 0 -> 897 bytes .../digital_signature.cer | Bin 0 -> 900 bytes .../SMIMEPolicyTests-data/email_field.cer | Bin 0 -> 879 bytes .../email_protection.cer | Bin 0 -> 924 bytes .../SMIMEPolicyTests-data/key_agreement.cer | Bin 0 -> 897 bytes .../key_agreement_decipher_only.cer | Bin 0 -> 914 bytes .../key_agreement_encipher_decipher.cer | Bin 0 -> 930 bytes .../key_agreement_encipher_only.cer | Bin 0 -> 913 bytes .../SMIMEPolicyTests-data/key_encipher.cer | Bin 0 -> 895 bytes .../SMIMEPolicyTests-data/no_name.cer | Bin 0 -> 841 bytes .../SMIMEPolicyTests-data/non_repudiation.cer | Bin 0 -> 898 bytes .../TestData/SMIMEPolicyTests-data/root.cer | Bin 0 -> 940 bytes .../SMIMEPolicyTests-data/san_name.cer | Bin 0 -> 871 bytes .../TestCopyProperties_ios.plist | 30 - .../Base.lproj/LaunchScreen.storyboard | 25 - .../TestRunners/Base.lproj/Main.storyboard | 24 - tests/TrustTests/TestRunners/main.m | 13 +- .../TestRunners/trusttests_entitlements.plist | 10 + tests/TrustTests/TrustEvaluationTestHelpers.m | 50 +- tests/TrustTests/gen_test_plist.py | 6 +- tests/secdmockaks/mockaks.h | 2 + tests/secdmockaks/mockaks.m | 220 +- tests/secdmockaks/mockaksKeychain.m | 116 +- tests/stashtester/main.m | 193 + tests/stashtester/stashtester.entitlements | 12 + trust/headers/SecCertificate.h | 26 +- trust/headers/SecCertificatePriv.h | 11 +- trust/headers/SecPolicy.h | 4 +- trust/headers/SecPolicyPriv.h | 416 +- trust/headers/SecTrust.h | 17 +- trust/headers/SecTrustPriv.h | 12 +- trust/headers/SecTrustSettingsPriv.h | 54 +- trust/headers/oids.h | 26 +- trust/trustd/OTATrustUtilities.m | 6 +- trust/trustd/SecCertificateServer.c | 82 +- trust/trustd/SecCertificateServer.h | 8 +- trust/trustd/SecCertificateSource.c | 90 +- trust/trustd/SecCertificateSource.h | 2 - trust/trustd/SecOCSPResponse.c | 17 + trust/trustd/SecOCSPResponse.h | 2 + trust/trustd/SecPinningDb.m | 25 +- trust/trustd/SecPolicyServer.c | 227 +- trust/trustd/SecRevocationDb.c | 164 +- trust/trustd/SecRevocationDb.h | 9 +- trust/trustd/SecRevocationNetworking.h | 1 + trust/trustd/SecRevocationNetworking.m | 123 +- trust/trustd/SecRevocationServer.c | 11 +- trust/trustd/SecTrustExceptionResetCount.m | 13 +- trust/trustd/SecTrustServer.c | 30 +- trust/trustd/SecTrustServer.h | 2 + trust/trustd/SecTrustStoreServer.c | 63 +- trust/trustd/SecTrustStoreServer.h | 11 +- trust/trustd/SecTrustStoreServer.m | 222 +- trust/trustd/iOS/entitlements.plist | 6 + trust/trustd/macOS/com.apple.trustd.sb | 16 + trust/trustd/macOS/entitlements.plist | 6 + trust/trustd/trustd.c | 52 +- trust/trustd/trustd_spi.c | 5 +- xcconfig/PlatformFeatures.xcconfig | 8 +- xcconfig/PlatformLibraries.xcconfig | 28 +- xcconfig/Security.xcconfig | 5 +- xcconfig/all_arches.xcconfig | 1 - ...ork_requiring_modern_objc_runtime.xcconfig | 7 - xcconfig/lib_ios.xcconfig | 2 +- xcconfig/swift_binary.xcconfig | 4 + xcscripts/install-test-framework.sh | 3 +- 1416 files changed, 54327 insertions(+), 29532 deletions(-) delete mode 100644 KeychainEntitledTestApp_ios/AppDelegate.h delete mode 100644 KeychainEntitledTestApp_ios/AppDelegate.m delete mode 100644 KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 KeychainEntitledTestApp_ios/Info.plist delete mode 100644 KeychainEntitledTestApp_ios/ViewController.h delete mode 100644 KeychainEntitledTestApp_ios/ViewController.m delete mode 100644 KeychainEntitledTestApp_mac/AppDelegate.h delete mode 100644 KeychainEntitledTestApp_mac/AppDelegate.m delete mode 100644 KeychainEntitledTestApp_mac/ViewController.h delete mode 100644 KeychainEntitledTestApp_mac/main.m create mode 100644 Modules/OctagonTrust.modulemap delete mode 100644 OSX/Breadcrumb/README delete mode 100644 OSX/Breadcrumb/SecBreadcrumb.c delete mode 100644 OSX/Breadcrumb/SecBreadcrumb.h delete mode 100644 OSX/Breadcrumb/bc-10-knife-on-bread.m delete mode 100644 OSX/Breadcrumb/breadcrumb_regressions.h delete mode 120000 OSX/Modules create mode 100644 OSX/authd/PreloginUserDb.h create mode 100644 OSX/authd/PreloginUserDb.m delete mode 120000 OSX/include/security_asn1 delete mode 120000 OSX/include/security_cdsa_client delete mode 120000 OSX/include/security_cdsa_plugin delete mode 120000 OSX/include/security_cdsa_utilities delete mode 120000 OSX/include/security_cdsa_utils delete mode 120000 OSX/include/security_codesigning delete mode 120000 OSX/include/security_comcryption delete mode 120000 OSX/include/security_cryptkit delete mode 120000 OSX/include/security_filedb delete mode 120000 OSX/include/security_keychain delete mode 120000 OSX/include/security_ocspd delete mode 120000 OSX/include/security_pkcs12 delete mode 120000 OSX/include/security_smime delete mode 120000 OSX/include/security_utilities delete mode 120000 OSX/include/securityd_client delete mode 100644 OSX/lib/framework.sb delete mode 120000 OSX/libsecurity_asn1/security_asn1 delete mode 120000 OSX/libsecurity_keychain/Security rename OSX/{utilities/SecADWrapper.h => libsecurity_keychain/lib/LegacyAPICounts.h} (65%) create mode 100644 OSX/libsecurity_keychain/lib/LegacyAPICounts.m delete mode 100644 OSX/libsecurity_keychain/lib/SecCertificateBundle.cpp delete mode 100644 OSX/libsecurity_keychain/lib/SecCertificateBundle.h delete mode 100644 OSX/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp delete mode 120000 OSX/libsecurity_ssl/Security create mode 100644 OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan create mode 100644 OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_macos.xctestplan delete mode 120000 OSX/libsecurity_ssl/security_ssl create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateEnumUtils.hpp create mode 100644 OSX/sec/Security/AppleExternalRootCertificates.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/Global Trustee.cer.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/UTN-USERFirst-Hardware.cer.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/addons.mozilla.org.cer.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.live.com.cer.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.skype.com.cer.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.1.cer.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.2.cer.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.cer.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/mail.google.com.cer.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/www.google.com.cer.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-84-sectrust-allowlist.m create mode 100644 OSX/sec/Security/SecItemRateLimit.h create mode 100644 OSX/sec/Security/SecItemRateLimit.m create mode 100644 OSX/sec/Security/SecItemRateLimit_tests.h create mode 100644 OSX/sec/Security/SecSharedCredential.m create mode 100644 OSX/sec/os_log/com.apple.security.ckks.plist create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/bad_SAN_seq_length.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/bad_general_name_type.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/san_zero_length_sequence.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_aia.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_certificate_policies.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/zero_length_crldps.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/KeyFailureCerts/parse_fail_explicit_paramaters.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/NameFailureCerts/rdn_short_length.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/NameFailureCerts/zero_length_rdn.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_critical_policy_mappings.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_ekus.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_extensions.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_general_subtrees.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_constructed_uri_name.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_directory_name.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_dns_name.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_edi_party_name.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_ip_address.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_other_name.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_registered_id.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_rfc822_name.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_uri_name.cer create mode 100644 OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_x400_name.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AAACertificateServices.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ApplePublicServerRSA12-G1.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomainsParsingTest.plist create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_ca.plist create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf.plist create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf_and_ca.plist create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_empty_spki.plist create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_invalid_spki.plist create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_without_spki.plist create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/OCSP_TestCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleWWDR-G3.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ids_init_public.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_missing_eku.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_missing_ku.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_responder.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_subca.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/test_iPh0ne_distribution.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/test_iphone_distribution.cer delete mode 100644 OSX/shared_regressions/si-88-sectrust-valid.m delete mode 100644 OSX/utilities/SecADWrapper.c create mode 100644 OSX/utilities/SecDbInternal.h create mode 100644 OSX/utilities/entitlements.c create mode 100644 OSX/utilities/entitlements.h rename keychain/SigninMetrics/SFSignInAnalytics+Internal.h => OSX/utilities/simulatecrash_assert.h (60%) create mode 100644 RegressionTests/secseccodeapitest.c create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/SecureTransportTests_ios.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/SecureTransportTests_macos.xcscheme create mode 100644 SecurityTests/ssl-policy-certs/subCA_EKU_Root.cer create mode 100644 SecurityTests/ssl-policy-certs/subCA_EKU_anyEKU_ca.cer create mode 100644 SecurityTests/ssl-policy-certs/subCA_EKU_anyEKU_leaf.cer create mode 100644 SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_ca.cer create mode 100644 SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_leaf.cer create mode 100644 SecurityTests/ssl-policy-certs/subCA_EKU_smime_ca.cer create mode 100644 SecurityTests/ssl-policy-certs/subCA_EKU_smime_leaf.cer create mode 100644 SecurityTests/ssl-policy-certs/subCA_EKU_ssl_ca.cer create mode 100644 SecurityTests/ssl-policy-certs/subCA_EKU_ssl_leaf.cer create mode 100644 SecurityTool/sharedTool/ca_revocation_additions.m delete mode 100644 TestPlan.xctestplan create mode 120000 header_symlinks/OctagonTrust/OTCDPRecoveryInformation.h create mode 120000 header_symlinks/OctagonTrust/OTEscrowAuthenticationInformation.h create mode 120000 header_symlinks/OctagonTrust/OTEscrowRecord.h create mode 120000 header_symlinks/OctagonTrust/OTEscrowRecordMetadata.h create mode 120000 header_symlinks/OctagonTrust/OTEscrowRecordMetadataClientMetadata.h create mode 120000 header_symlinks/OctagonTrust/OTEscrowTranslation.h create mode 120000 header_symlinks/OctagonTrust/OTICDPRecordContext.h create mode 120000 header_symlinks/OctagonTrust/OTICDPRecordSilentContext.h create mode 120000 header_symlinks/OctagonTrust/OctagonTrust.h delete mode 120000 header_symlinks/Security/SFSignInAnalytics.h delete mode 120000 header_symlinks/macOS/Security/SecBreadcrumb.h delete mode 120000 header_symlinks/macOS/Security/SecCertificateBundle.h create mode 100644 keychain/KeychainStasher/KeychainStasher-Info.plist create mode 100644 keychain/KeychainStasher/KeychainStasher.entitlements create mode 100644 keychain/KeychainStasher/KeychainStasher.h create mode 100644 keychain/KeychainStasher/KeychainStasher.m create mode 100644 keychain/KeychainStasher/KeychainStasherProtocol.h create mode 100644 keychain/KeychainStasher/com.apple.security.KeychainStasher.plist create mode 100644 keychain/KeychainStasher/com.apple.security.KeychainStasher.sb create mode 100644 keychain/KeychainStasher/main.m create mode 100644 keychain/OctagonTrust/Info.plist create mode 100644 keychain/OctagonTrust/OTEscrowTranslation.h create mode 100644 keychain/OctagonTrust/OTEscrowTranslation.m create mode 100644 keychain/OctagonTrust/OctagonTrust.h create mode 100644 keychain/OctagonTrust/OctagonTrust.m create mode 100644 keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h create mode 100644 keychain/OctagonTrust/ot-tests/OctagonTrustTests+Errors.m create mode 100644 keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowRecords.m create mode 100644 keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowTestVectors.h rename keychain/{ckks/tests/CKKSCloudKitTestsInfo.plist => OctagonTrust/ot-tests/OctagonTrustTests-Info.plist} (94%) create mode 100644 keychain/OctagonTrust/ot-tests/OctagonTrustTests.h mode change 100644 => 100755 keychain/ResetCloudKeychainAccount/reset_ick_account delete mode 100644 keychain/SigninMetrics/SFSignInAnalytics.h delete mode 100644 keychain/SigninMetrics/SFSignInAnalytics.m delete mode 100644 keychain/SigninMetrics/tests/SFSignInAnalyticsTests.m create mode 100644 keychain/TrustedPeersHelper/Container_EscrowRecords.swift create mode 100644 keychain/TrustedPeersHelper/Container_Peers.swift create mode 100644 keychain/TrustedPeersHelper/Container_UserSync.swift create mode 100644 keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb delete mode 100644 keychain/behavior/SFBehavior.h delete mode 100644 keychain/behavior/SFBehavior.m create mode 100644 keychain/ckks/CKKSCheckKeyHierarchyOperation.h create mode 100644 keychain/ckks/CKKSCheckKeyHierarchyOperation.m create mode 100644 keychain/ckks/CKKSCreateCKZoneOperation.h create mode 100644 keychain/ckks/CKKSCreateCKZoneOperation.m create mode 100644 keychain/ckks/CKKSDeleteCKZoneOperation.h create mode 100644 keychain/ckks/CKKSDeleteCKZoneOperation.m create mode 100644 keychain/ckks/CKKSLocalResetOperation.h create mode 100644 keychain/ckks/CKKSLocalResetOperation.m create mode 100644 keychain/ckks/CKKSLogging.m create mode 100644 keychain/ckks/CKKSOperationDependencies.h create mode 100644 keychain/ckks/CKKSOperationDependencies.m create mode 100644 keychain/ckks/CKKSStates.h create mode 100644 keychain/ckks/CKKSStates.m delete mode 100644 keychain/ckks/CKKSZone.h delete mode 100644 keychain/ckks/CKKSZone.m delete mode 100644 keychain/ckks/tests/CKKSCloudKitTests.m create mode 100644 keychain/ckks/tests/CKKSTests+ForwardCompatibility.m create mode 100644 keychain/ckks/tests/CKKSTests+ItemSyncChoice.m create mode 100644 keychain/ot/OTClique+Private.h create mode 100644 keychain/ot/OTModifyUserControllableViewStatusOperation.h create mode 100644 keychain/ot/OTModifyUserControllableViewStatusOperation.m create mode 100644 keychain/ot/OTPreloadOctagonKeysOperation.h create mode 100644 keychain/ot/OTPreloadOctagonKeysOperation.m create mode 100644 keychain/ot/proto/OTCDPRecoveryInformation.proto create mode 100644 keychain/ot/proto/OTEscrowRecord.proto create mode 100644 keychain/ot/proto/generated_source/OTCDPRecoveryInformation.h create mode 100644 keychain/ot/proto/generated_source/OTCDPRecoveryInformation.m create mode 100644 keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.h create mode 100644 keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.m create mode 100644 keychain/ot/proto/generated_source/OTEscrowRecord.h create mode 100644 keychain/ot/proto/generated_source/OTEscrowRecord.m create mode 100644 keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h create mode 100644 keychain/ot/proto/generated_source/OTEscrowRecordMetadata.m create mode 100644 keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h create mode 100644 keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.m create mode 100644 keychain/ot/proto/generated_source/OTGlobalEnums.h create mode 100644 keychain/ot/proto/generated_source/OTICDPRecordContext.h create mode 100644 keychain/ot/proto/generated_source/OTICDPRecordContext.m create mode 100644 keychain/ot/proto/generated_source/OTICDPRecordSilentContext.h create mode 100644 keychain/ot/proto/generated_source/OTICDPRecordSilentContext.m create mode 100644 keychain/ot/proto/generated_source/OTSupportOctagonMessage.h create mode 100644 keychain/ot/proto/generated_source/OTSupportOctagonMessage.m create mode 100644 keychain/ot/proto/generated_source/OTSupportSOSMessage.h create mode 100644 keychain/ot/proto/generated_source/OTSupportSOSMessage.m delete mode 100644 keychain/ot/proto/source/OTSOSMessage.h create mode 100644 keychain/ot/tests/octagon/OctagonPolicyTests.swift create mode 100644 keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift create mode 100644 keychain/ot/tests/octagon/OctagonTests+EscrowTestVectors.swift delete mode 100644 keychain/securityd/Regressions/secd-668-ghosts.m create mode 100644 keychain/securityd/Regressions/secd-68-fullPeerInfoIntegrity.m create mode 100644 keychain/securityd/SecDbKeychainV7-protobufs/SecDbKeychainSerializedMetadataKey.proto create mode 100644 keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.h create mode 100644 keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.m create mode 100644 keychain/securityd/SecItemServer+SWC.h create mode 100644 keychain/securityd/SecItemServer+SWC.m delete mode 120000 libsecurity_smime/Security delete mode 120000 libsecurity_smime/security_smime create mode 100644 secdxctests/KeychainAppClipTests.m create mode 100644 secdxctests/KeychainBackupTests.m create mode 100644 secdxctests/secdxctests-entitlements.plist create mode 100644 sectask/SystemEntitlements.h create mode 100644 securityd/src/keychainstasherinterface.h create mode 100644 securityd/src/keychainstasherinterface.m create mode 100644 supd/com.apple.securityuploadd.sb rename tests/SecDbBackupTests/{Entitlements.plist => SecDbBackupTests-Entitlements.plist} (93%) delete mode 100644 tests/SecDbBackupTests/SecDbBackupTests.plist create mode 100644 tests/SecDbBackupTests/SecDbBackupTestsBase.h create mode 100644 tests/SecDbBackupTests/SecDbBackupTestsBase.m create mode 100644 tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.h create mode 100644 tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.m rename {KeychainEntitledTestApp_mac => tests/TestHostBinaries/KeychainEntitledTestApp}/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {KeychainEntitledTestApp_mac => tests/TestHostBinaries/KeychainEntitledTestApp}/Info.plist (89%) create mode 100644 tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.h rename {KeychainEntitledTestApp_mac => tests/TestHostBinaries/KeychainEntitledTestApp}/ViewController.m (50%) rename {KeychainEntitledTestApp_ios => tests/TestHostBinaries/KeychainEntitledTestApp}/main.m (54%) rename keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist => tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements (65%) rename {keychain/ckks/tests/testrunner => tests/TestHostBinaries/KeychainEntitledTestRunner}/KeychainEntitledTestRunner.m (91%) create mode 100644 tests/TrustTests/DaemonTests/PersonalizationTests.m create mode 100644 tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m create mode 100644 tests/TrustTests/EvaluationTests/AllowlistBlocklistTests_data.h create mode 100644 tests/TrustTests/EvaluationTests/CAIssuerTests.m create mode 100644 tests/TrustTests/EvaluationTests/CAIssuerTests_data.h create mode 100644 tests/TrustTests/EvaluationTests/SMIMEPolicyTests.m rename OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.m => tests/TrustTests/EvaluationTests/TrustSettingsTests.m (77%) rename OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.h => tests/TrustTests/EvaluationTests/TrustSettingsTests_data.h (99%) create mode 100644 tests/TrustTests/EvaluationTests/ValidTests.m create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/any_eku.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/common_name.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/data_encipher.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/digital_signature.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/email_field.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/email_protection.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_decipher_only.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_encipher_decipher.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_encipher_only.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/key_encipher.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/no_name.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/non_repudiation.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/root.cer create mode 100644 tests/TrustTests/TestData/SMIMEPolicyTests-data/san_name.cer delete mode 100644 tests/TrustTests/TestRunners/Base.lproj/LaunchScreen.storyboard delete mode 100644 tests/TrustTests/TestRunners/Base.lproj/Main.storyboard create mode 100644 tests/stashtester/main.m create mode 100644 tests/stashtester/stashtester.entitlements delete mode 100644 xcconfig/all_arches.xcconfig delete mode 100644 xcconfig/framework_requiring_modern_objc_runtime.xcconfig diff --git a/.swiftlint.yml b/.swiftlint.yml index 43c689e8..ee93ab06 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,12 +1,16 @@ indentation: 4 disabled_rules: + - cyclomatic_complexity - file_length - function_body_length - function_parameter_count - identifier_name + - implicit_return + - large_tuple - line_length - todo - type_body_length + - type_name opt_in_rules: - anyobject_protocol - array_init @@ -14,18 +18,30 @@ opt_in_rules: #- closure_end_indentation ## commented as --format removes option - closure_spacing - conditional_returns_on_newline + - contains_over_range_nil_comparison - empty_count + - empty_string - explicit_init - - implicit_return + - fatal_error_message + - first_where + - implicitly_unwrapped_optional - joined_default_parameter #- literal_expression_end_indentation ## commented as --format removes option + - legacy_random + - let_var_whitespace + - lower_acl_than_parent + - multiline_function_chains - operator_usage_whitespace + - pattern_matching_keywords - redundant_nil_coalescing - redundant_type_annotation - sorted_imports - trailing_closure - unneeded_parentheses_in_closure_argument - untyped_error_in_catch + - vertical_whitespace_closing_braces + - xct_specific_matcher + - yoda_condition trailing_comma: mandatory_comma: true excluded: diff --git a/Analytics/Clients/LocalKeychainAnalytics.h b/Analytics/Clients/LocalKeychainAnalytics.h index f3344093..7d39c0af 100644 --- a/Analytics/Clients/LocalKeychainAnalytics.h +++ b/Analytics/Clients/LocalKeychainAnalytics.h @@ -44,6 +44,8 @@ typedef NSString* LKAnalyticsFailableEvent NS_STRING_ENUM; typedef NSString* LKAnalyticsMetric NS_STRING_ENUM; extern LKAnalyticsFailableEvent const LKAEventUpgrade; +extern LKAnalyticsFailableEvent const LKAEventStash; +extern LKAnalyticsFailableEvent const LKAEventStashLoad; @interface LocalKeychainAnalytics : SFAnalytics diff --git a/Analytics/Clients/LocalKeychainAnalytics.m b/Analytics/Clients/LocalKeychainAnalytics.m index 8d97a540..9eabc0ac 100644 --- a/Analytics/Clients/LocalKeychainAnalytics.m +++ b/Analytics/Clients/LocalKeychainAnalytics.m @@ -32,6 +32,10 @@ LKAnalyticsFailableEvent const LKAEventUpgrade = (LKAnalyticsFailableEvent)@"LKA LKAnalyticsFailableEvent const LKAEventBackup = (LKAnalyticsFailableEvent)@"LKAEventBackup"; LKAnalyticsMetric const LKAMetricBackupDuration = (LKAnalyticsMetric)@"LKAMetricBackupDuration"; +// SFAnalytics: Collect keychain masterkey stash success/failure rates and failure codes on macOS SUs +LKAnalyticsFailableEvent const LKAEventStash = (LKAnalyticsFailableEvent)@"LKAEventStash"; +LKAnalyticsFailableEvent const LKAEventStashLoad = (LKAnalyticsFailableEvent)@"LKAEventStashLoad"; + // Internal consts NSString* const LKAOldSchemaKey = @"oldschema"; NSString* const LKANewSchemaKey = @"newschema"; diff --git a/Analytics/Clients/SOSAnalytics.h b/Analytics/Clients/SOSAnalytics.h index 53e81312..87287418 100644 --- a/Analytics/Clients/SOSAnalytics.h +++ b/Analytics/Clients/SOSAnalytics.h @@ -26,7 +26,7 @@ #define SOSAnalytics_h #import -#import "Analytics/SFAnalytics.h" +#import extern NSString* const CKDKVSPerformanceCountersSampler; diff --git a/Analytics/SFAnalytics.h b/Analytics/SFAnalytics.h index 55d35ba6..2010156d 100644 --- a/Analytics/SFAnalytics.h +++ b/Analytics/SFAnalytics.h @@ -26,9 +26,9 @@ #define SFAnalytics_h #import -#import "SFAnalyticsSampler.h" -#import "SFAnalyticsMultiSampler.h" -#import "SFAnalyticsActivityTracker.h" +#import +#import +#import NS_ASSUME_NONNULL_BEGIN @@ -70,6 +70,9 @@ typedef NS_ENUM(uint32_t, SFAnalyticsTimestampBucket) { // Help for the subclass to pick a prefered location + (NSString *)defaultAnalyticsDatabasePath:(NSString *)basename; ++ (NSString *)defaultProtectedAnalyticsDatabasePath:(NSString *)basename uuid:(NSUUID * __nullable)userUuid; ++ (NSString *)defaultProtectedAnalyticsDatabasePath:(NSString *)basename; // uses current user UUID for path + - (void)dailyCoreAnalyticsMetrics:(NSString *)eventName; // Log event-based metrics: create an event corresponding to some event in your feature diff --git a/Analytics/SFAnalytics.m b/Analytics/SFAnalytics.m index a51eb5f9..f3014caa 100644 --- a/Analytics/SFAnalytics.m +++ b/Analytics/SFAnalytics.m @@ -42,6 +42,7 @@ #if TARGET_OS_OSX #include +#include #else #import #endif @@ -80,6 +81,7 @@ NSString* const SFAnalyticsTopicCloudServices = @"CloudServicesTopic"; NSString* const SFAnalyticsTopicKeySync = @"KeySyncTopic"; NSString* const SFAnalyticsTopicTrust = @"TrustTopic"; NSString* const SFAnalyticsTopicTransparency = @"TransparencyTopic"; +NSString* const SFAnalyticsTopicNetworking = @"NetworkingTopic"; NSString* const SFAnalyticsTableSchema = @"CREATE TABLE IF NOT EXISTS hard_failures (\n" @"id INTEGER PRIMARY KEY AUTOINCREMENT,\n" @@ -197,6 +199,61 @@ const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport = -1.0; return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory((__bridge CFStringRef)path) path]; } ++ (NSString *)defaultProtectedAnalyticsDatabasePath:(NSString *)basename uuid:(NSUUID * __nullable)userUuid +{ + // Create the top-level directory with full access + NSMutableString *directory = [NSMutableString stringWithString:@"sfanalytics"]; + WithPathInProtectedDirectory((__bridge CFStringRef)directory, ^(const char *path) { + mode_t permissions = 0777; + int ret = mkpath_np(path, permissions); + if (!(ret == 0 || ret == EEXIST)) { + secerror("could not create path: %s (%s)", path, strerror(ret)); + } + chmod(path, permissions); + }); + + // create per-user directory + if (userUuid) { + [directory appendString:@"/"]; + [directory appendString:[userUuid UUIDString]]; + WithPathInProtectedDirectory((__bridge CFStringRef)directory, ^(const char *path) { +#if TARGET_OS_IPHONE + mode_t permissions = 0775; +#else + mode_t permissions = 0700; + if (geteuid() == 0) { + // Root user directory needs to be read/write for group so that user supd can upload root data + permissions = 0775; + } +#endif // TARGET_OS_IPHONE + int ret = mkpath_np(path, permissions); + if (!(ret == 0 || ret == EEXIST)) { + secerror("could not create path: %s (%s)", path, strerror(ret)); + } + chmod(path, permissions); + }); + } + NSString *path = [NSString stringWithFormat:@"%@/%@.db", directory, basename]; + return [(__bridge_transfer NSURL*)SecCopyURLForFileInProtectedDirectory((__bridge CFStringRef)path) path]; +} + ++ (NSString *)defaultProtectedAnalyticsDatabasePath:(NSString *)basename +{ +#if TARGET_OS_OSX + uid_t euid = geteuid(); + uuid_t currentUserUuid; + int ret = mbr_uid_to_uuid(euid, currentUserUuid); + if (ret != 0) { + secerror("failed to get UUID for user(%d) - %d", euid, ret); + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:basename uuid:nil]; + } + NSUUID *userUuid = [[NSUUID alloc] initWithUUIDBytes:currentUserUuid]; + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:basename uuid:userUuid]; +#else + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:basename uuid:nil]; +#endif // TARGET_OS_IPHONE +} + + (NSInteger)fuzzyDaysSinceDate:(NSDate*)date { // Sentinel: it didn't happen at all diff --git a/Analytics/SFAnalytics.plist b/Analytics/SFAnalytics.plist index ec44cc55..0b7cab8d 100644 --- a/Analytics/SFAnalytics.plist +++ b/Analytics/SFAnalytics.plist @@ -50,5 +50,18 @@ splunk_bagURL https://metrics-config.icloud.com/config/TransparencyAnalytics + NetworkingTopic + + uploadSizeLimit + 1000000 + splunk_allowInsecureCertificate + + splunk_topic + xp_sear_trust + splunk_bagURL + https://xp.apple.com/config/1/report/xp_sear_trust + disableClientId + + diff --git a/Analytics/SFAnalyticsDefines.h b/Analytics/SFAnalyticsDefines.h index abf89eec..06bff295 100644 --- a/Analytics/SFAnalyticsDefines.h +++ b/Analytics/SFAnalyticsDefines.h @@ -61,6 +61,7 @@ extern NSString* const SFAnalyticsTopicCloudServices; extern NSString* const SFAnalyticsTopicKeySync; extern NSString* const SFAnalyticsTopicTrust; extern NSString* const SFAnalyticsTopicTransparency; +extern NSString* const SFAnalyticsTopicNetworking; typedef NS_ENUM(NSInteger, SFAnalyticsEventClass) { SFAnalyticsEventClassSuccess, diff --git a/Analytics/SFAnalyticsSQLiteStore.h b/Analytics/SFAnalyticsSQLiteStore.h index 16531fa5..c7bbade4 100644 --- a/Analytics/SFAnalyticsSQLiteStore.h +++ b/Analytics/SFAnalyticsSQLiteStore.h @@ -23,8 +23,8 @@ #if __OBJC2__ -#import "Analytics/SQLite/SFSQLite.h" -#import "SFAnalytics.h" +#import +#import @interface SFAnalyticsSQLiteStore : SFSQLite diff --git a/Analytics/SQLite/SFSQLite.m b/Analytics/SQLite/SFSQLite.m index fcde86f7..e0f1a8dd 100644 --- a/Analytics/SQLite/SFSQLite.m +++ b/Analytics/SQLite/SFSQLite.m @@ -28,6 +28,7 @@ #include #include #import "utilities/debugging.h" +#import "utilities/simulatecrash_assert.h" #include #define kSFSQLiteBusyTimeout (5*60*1000) @@ -911,7 +912,7 @@ done: - (NSString *)_tableNameForClass:(Class)objectClass { NSString *className = [objectClass SFSQLiteClassName]; if (![className hasPrefix:_objectClassPrefix]) { - secerror("sfsqlite: %@", [NSString stringWithFormat:@"Object class \"%@\" does not have prefix \"%@\"", className, _objectClassPrefix]); + secerror("sfsqlite: Object class \"%@\" does not have prefix \"%@\"", className, _objectClassPrefix); return nil; } return [className substringFromIndex:_objectClassPrefix.length]; diff --git a/CMS/CMSDecoder.h b/CMS/CMSDecoder.h index 031ad4a4..30e4f01c 100644 --- a/CMS/CMSDecoder.h +++ b/CMS/CMSDecoder.h @@ -68,7 +68,7 @@ typedef CF_ENUM(uint32_t, CMSSignerStatus) { * Create a CMSDecoder. Result must eventually be freed via CFRelease(). */ OSStatus CMSDecoderCreate(CMSDecoderRef * __nonnull CF_RETURNS_RETAINED cmsDecoderOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Feed raw bytes of the message to be decoded into the decoder. Can be called @@ -80,7 +80,7 @@ OSStatus CMSDecoderUpdateMessage( CMSDecoderRef cmsDecoder, const void *msgBytes, size_t msgBytesLen) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Indicate that no more CMSDecoderUpdateMessage() calls are forthcoming; @@ -89,7 +89,7 @@ OSStatus CMSDecoderUpdateMessage( * message. */ OSStatus CMSDecoderFinalizeMessage(CMSDecoderRef cmsDecoder) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * A signed CMS message optionally includes the data which was signed. If the @@ -105,7 +105,7 @@ OSStatus CMSDecoderFinalizeMessage(CMSDecoderRef cmsDecoder) OSStatus CMSDecoderSetDetachedContent( CMSDecoderRef cmsDecoder, CFDataRef detachedContent) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the detached content specified in CMSDecoderSetDetachedContent(). @@ -115,7 +115,7 @@ OSStatus CMSDecoderSetDetachedContent( OSStatus CMSDecoderCopyDetachedContent( CMSDecoderRef cmsDecoder, CFDataRef * __nonnull CF_RETURNS_RETAINED detachedContentOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); #if SEC_OS_OSX /* @@ -125,7 +125,7 @@ OSStatus CMSDecoderCopyDetachedContent( OSStatus CMSDecoderSetSearchKeychain( CMSDecoderRef cmsDecoder, CFTypeRef keychainOrArray) - API_DEPRECATED_WITH_REPLACEMENT("SecKeychainSetSearchList",macos(10.5, 10.13)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecKeychainSetSearchList",macos(10.5, 10.13)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #endif // SEC_OS_OSX /* @@ -136,7 +136,7 @@ OSStatus CMSDecoderSetSearchKeychain( OSStatus CMSDecoderGetNumSigners( CMSDecoderRef cmsDecoder, size_t *numSignersOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the status of a CMS message's signature. A CMS message can @@ -220,7 +220,7 @@ OSStatus CMSDecoderCopySignerStatus( CMSSignerStatus * __nullable signerStatusOut, /* optional; RETURNED */ SecTrustRef * __nullable CF_RETURNS_RETAINED secTrustOut, /* optional; RETURNED */ OSStatus * __nullable certVerifyResultCodeOut) /* optional; RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the email address of signer 'signerIndex' of a CMS message, if @@ -235,7 +235,7 @@ OSStatus CMSDecoderCopySignerEmailAddress( CMSDecoderRef cmsDecoder, size_t signerIndex, CFStringRef * __nonnull CF_RETURNS_RETAINED signerEmailAddressOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the certificate of signer 'signerIndex' of a CMS message, if @@ -250,7 +250,7 @@ OSStatus CMSDecoderCopySignerCert( CMSDecoderRef cmsDecoder, size_t signerIndex, SecCertificateRef * __nonnull CF_RETURNS_RETAINED signerCertOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Determine whether a CMS message was encrypted. Returns TRUE if so, FALSE if not. @@ -262,7 +262,7 @@ OSStatus CMSDecoderCopySignerCert( OSStatus CMSDecoderIsContentEncrypted( CMSDecoderRef cmsDecoder, Boolean *isEncryptedOut) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if @@ -274,7 +274,7 @@ OSStatus CMSDecoderIsContentEncrypted( OSStatus CMSDecoderCopyEncapsulatedContentType( CMSDecoderRef cmsDecoder, CFDataRef * __nonnull CF_RETURNS_RETAINED eContentTypeOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain an array of all of the certificates in a message. Elements of the @@ -287,7 +287,7 @@ OSStatus CMSDecoderCopyEncapsulatedContentType( OSStatus CMSDecoderCopyAllCerts( CMSDecoderRef cmsDecoder, CFArrayRef * __nonnull CF_RETURNS_RETAINED certsOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the actual message content (payload), if any. If the message was @@ -298,7 +298,7 @@ OSStatus CMSDecoderCopyAllCerts( OSStatus CMSDecoderCopyContent( CMSDecoderRef cmsDecoder, CFDataRef * __nonnull CF_RETURNS_RETAINED contentOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the signing time of signer 'signerIndex' of a CMS message, if @@ -314,7 +314,7 @@ OSStatus CMSDecoderCopySignerSigningTime( CMSDecoderRef cmsDecoder, size_t signerIndex, CFAbsoluteTime *signingTime) /* RETURNED */ - __API_AVAILABLE(macos(10.8)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.8)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the timestamp of signer 'signerIndex' of a CMS message, if @@ -330,7 +330,7 @@ OSStatus CMSDecoderCopySignerTimestamp( CMSDecoderRef cmsDecoder, size_t signerIndex, CFAbsoluteTime *timestamp) /* RETURNED */ - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * Obtain the timestamp of signer 'signerIndex' of a CMS message, if @@ -347,7 +347,7 @@ OSStatus CMSDecoderCopySignerTimestampWithPolicy( CFTypeRef __nullable timeStampPolicy, size_t signerIndex, /* usually 0 */ CFAbsoluteTime *timestamp) /* RETURNED */ - API_AVAILABLE(macos(10.10)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.10)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * Obtain an array of the certificates in a timestamp response. Elements of the @@ -365,7 +365,7 @@ OSStatus CMSDecoderCopySignerTimestampCertificates( CMSDecoderRef cmsDecoder, size_t signerIndex, /* usually 0 */ CFArrayRef * __nonnull CF_RETURNS_RETAINED certificateRefs) /* RETURNED */ - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); CF_ASSUME_NONNULL_END diff --git a/CMS/CMSEncoder.h b/CMS/CMSEncoder.h index 276b72ef..02128b6c 100644 --- a/CMS/CMSEncoder.h +++ b/CMS/CMSEncoder.h @@ -62,13 +62,13 @@ CF_ASSUME_NONNULL_BEGIN typedef struct CF_BRIDGED_TYPE(id) _CMSEncoder *CMSEncoderRef; CFTypeID CMSEncoderGetTypeID(void) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Create a CMSEncoder. Result must eventually be freed via CFRelease(). */ OSStatus CMSEncoderCreate(CMSEncoderRef * __nonnull CF_RETURNS_RETAINED cmsEncoderOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); extern const CFStringRef kCMSEncoderDigestAlgorithmSHA1; extern const CFStringRef kCMSEncoderDigestAlgorithmSHA256; @@ -76,7 +76,7 @@ extern const CFStringRef kCMSEncoderDigestAlgorithmSHA256; OSStatus CMSEncoderSetSignerAlgorithm( CMSEncoderRef cmsEncoder, CFStringRef digestAlgorithm) - __API_AVAILABLE(macos(10.11)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.11)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Specify signers of the CMS message; implies that the message will be signed. @@ -91,7 +91,7 @@ OSStatus CMSEncoderSetSignerAlgorithm( OSStatus CMSEncoderAddSigners( CMSEncoderRef cmsEncoder, CFTypeRef signerOrArray) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain an array of signers as specified in CMSEncoderSetSigners(). @@ -101,7 +101,7 @@ OSStatus CMSEncoderAddSigners( OSStatus CMSEncoderCopySigners( CMSEncoderRef cmsEncoder, CFArrayRef * __nonnull CF_RETURNS_RETAINED signersOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Specify recipients of the message. Implies that the message will @@ -117,7 +117,7 @@ OSStatus CMSEncoderCopySigners( OSStatus CMSEncoderAddRecipients( CMSEncoderRef cmsEncoder, CFTypeRef recipientOrArray) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain an array of recipients as specified in CMSEncoderSetRecipients(). @@ -128,7 +128,7 @@ OSStatus CMSEncoderAddRecipients( OSStatus CMSEncoderCopyRecipients( CMSEncoderRef cmsEncoder, CFArrayRef * __nonnull CF_RETURNS_RETAINED recipientsOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * A signed message optionally includes the data to be signed. If the message @@ -144,7 +144,7 @@ OSStatus CMSEncoderCopyRecipients( OSStatus CMSEncoderSetHasDetachedContent( CMSEncoderRef cmsEncoder, Boolean detachedContent) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain a Boolean indicating whether the current message will have detached @@ -155,7 +155,7 @@ OSStatus CMSEncoderSetHasDetachedContent( OSStatus CMSEncoderGetHasDetachedContent( CMSEncoderRef cmsEncoder, Boolean *detachedContentOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); #if SEC_OS_OSX /* @@ -173,7 +173,7 @@ OSStatus CMSEncoderGetHasDetachedContent( OSStatus CMSEncoderSetEncapsulatedContentType( CMSEncoderRef cmsEncoder, const CSSM_OID *eContentType) - API_DEPRECATED_WITH_REPLACEMENT("CMSEncoderSetEncapsulatedContentTypeOID", macos(10.5, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("CMSEncoderSetEncapsulatedContentTypeOID", macos(10.5, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #endif // SEC_OS_OSX /* @@ -191,7 +191,7 @@ OSStatus CMSEncoderSetEncapsulatedContentType( OSStatus CMSEncoderSetEncapsulatedContentTypeOID( CMSEncoderRef cmsEncoder, CFTypeRef eContentTypeOID) - __API_AVAILABLE(macos(10.7)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.7)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the eContentType OID specified in CMSEncoderSetEncapsulatedContentType(). @@ -204,7 +204,7 @@ OSStatus CMSEncoderSetEncapsulatedContentTypeOID( OSStatus CMSEncoderCopyEncapsulatedContentType( CMSEncoderRef cmsEncoder, CFDataRef * __nonnull CF_RETURNS_RETAINED eContentTypeOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Signed CMS messages can contain arbitrary sets of certificates beyond those @@ -229,7 +229,7 @@ OSStatus CMSEncoderCopyEncapsulatedContentType( OSStatus CMSEncoderAddSupportingCerts( CMSEncoderRef cmsEncoder, CFTypeRef certOrArray) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain the SecCertificates provided in CMSEncoderAddSupportingCerts(). @@ -240,7 +240,7 @@ OSStatus CMSEncoderAddSupportingCerts( OSStatus CMSEncoderCopySupportingCerts( CMSEncoderRef cmsEncoder, CFArrayRef * __nonnull CF_RETURNS_RETAINED certsOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Standard signed attributes, optionally specified in @@ -285,7 +285,7 @@ typedef CF_OPTIONS(uint32_t, CMSSignedAttributes) { OSStatus CMSEncoderAddSignedAttributes( CMSEncoderRef cmsEncoder, CMSSignedAttributes signedAttributes) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Specification of what certificates to include in a signed message. @@ -313,7 +313,7 @@ typedef CF_ENUM(uint32_t, CMSCertificateChainMode) { OSStatus CMSEncoderSetCertificateChainMode( CMSEncoderRef cmsEncoder, CMSCertificateChainMode chainMode) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Obtain indication of which signer certs are to be included @@ -322,7 +322,7 @@ OSStatus CMSEncoderSetCertificateChainMode( OSStatus CMSEncoderGetCertificateChainMode( CMSEncoderRef cmsEncoder, CMSCertificateChainMode *chainModeOut) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Feed content bytes into the encoder. @@ -333,7 +333,7 @@ OSStatus CMSEncoderUpdateContent( CMSEncoderRef cmsEncoder, const void *content, size_t contentLen) - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); /* * Finish encoding the message and obtain the encoded result. @@ -342,7 +342,7 @@ OSStatus CMSEncoderUpdateContent( OSStatus CMSEncoderCopyEncodedContent( CMSEncoderRef cmsEncoder, CFDataRef * __nonnull CF_RETURNS_RETAINED encodedContentOut) /* RETURNED */ - __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); #if TARGET_OS_OSX /* @@ -377,7 +377,7 @@ OSStatus CMSEncode( const void * content, size_t contentLen, CFDataRef * __nonnull CF_RETURNS_RETAINED encodedContentOut) /* RETURNED */ - API_DEPRECATED_WITH_REPLACEMENT("CMSEncodeContent", macos(10.5, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("CMSEncodeContent", macos(10.5, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #endif // TARGET_OS_OSX /* @@ -410,20 +410,20 @@ OSStatus CMSEncodeContent( const void *content, size_t contentLen, CFDataRef * __nullable CF_RETURNS_RETAINED encodedContentOut) /* RETURNED */ - __API_AVAILABLE(macos(10.7)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + __API_AVAILABLE(macos(10.7)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), macCatalyst(11.0)); OSStatus CMSEncoderCopySignerTimestamp( CMSEncoderRef cmsEncoder, size_t signerIndex, /* usually 0 */ CFAbsoluteTime *timestamp) /* RETURNED */ - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); OSStatus CMSEncoderCopySignerTimestampWithPolicy( CMSEncoderRef cmsEncoder, CFTypeRef __nullable timeStampPolicy, size_t signerIndex, /* usually 0 */ CFAbsoluteTime *timestamp) /* RETURNED */ - API_AVAILABLE(macos(10.10)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.10)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); CF_ASSUME_NONNULL_END diff --git a/CMS/CMSPrivate.h b/CMS/CMSPrivate.h index 548a2792..b8a5c137 100644 --- a/CMS/CMSPrivate.h +++ b/CMS/CMSPrivate.h @@ -115,7 +115,7 @@ OSStatus CMSEncoderSetAppleExpirationTime( void CmsMessageSetTSAContext(CMSEncoderRef cmsEncoder, CFTypeRef tsaContext) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, macCatalyst); /*** *** Private CMSDecoder routines diff --git a/CMS/SecCmsBase.h b/CMS/SecCmsBase.h index 44f7eade..77ec4ac5 100644 --- a/CMS/SecCmsBase.h +++ b/CMS/SecCmsBase.h @@ -69,9 +69,9 @@ typedef SecAsn1AlgId SECAlgorithmID; @discussion XXX This should probably move to SecKey.h */ #if TARGET_OS_OSX -typedef SecKeyRef SecSymmetricKeyRef API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +typedef SecKeyRef SecSymmetricKeyRef API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else -typedef void * SecSymmetricKeyRef API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +typedef void * SecSymmetricKeyRef API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif /*! @@ -173,7 +173,7 @@ typedef void (*SecCmsContentCallback)(void *arg, const char *buf, size_t len); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" typedef SecSymmetricKeyRef(*SecCmsGetDecryptKeyCallback)(void *arg, SECAlgorithmID *algid) - API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop /*! diff --git a/CMS/SecCmsContentInfo.h b/CMS/SecCmsContentInfo.h index c799eb43..2a4eafeb 100644 --- a/CMS/SecCmsContentInfo.h +++ b/CMS/SecCmsContentInfo.h @@ -71,7 +71,7 @@ SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo); */ extern CSSM_DATA_PTR SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -80,7 +80,7 @@ SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo) */ extern const SecAsn1Item * SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! @@ -99,7 +99,7 @@ SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo); */ extern CSSM_OID * SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -108,7 +108,7 @@ SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo) */ extern SecAsn1Oid * SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! @@ -143,7 +143,7 @@ SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo) */ extern OSStatus SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -157,7 +157,7 @@ SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinf */ extern OSStatus SecCmsContentInfoSetContentData(SecCmsContentInfoRef cinfo, CFDataRef data, Boolean detached) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX @@ -173,7 +173,7 @@ SecCmsContentInfoSetContentData(SecCmsContentInfoRef cinfo, CFDataRef data, Bool */ extern OSStatus SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -186,7 +186,7 @@ SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRe */ extern OSStatus SecCmsContentInfoSetContentSignedData(SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // TARGET_OS_OSX #if TARGET_OS_OSX @@ -202,7 +202,7 @@ SecCmsContentInfoSetContentSignedData(SecCmsContentInfoRef cinfo, SecCmsSignedDa */ extern OSStatus SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -215,7 +215,7 @@ SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInf */ extern OSStatus SecCmsContentInfoSetContentEnvelopedData(SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX @@ -231,7 +231,7 @@ SecCmsContentInfoSetContentEnvelopedData(SecCmsContentInfoRef cinfo, SecCmsEnvel */ extern OSStatus SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -244,7 +244,7 @@ SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfo */ extern OSStatus SecCmsContentInfoSetContentDigestedData(SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX @@ -260,7 +260,7 @@ SecCmsContentInfoSetContentDigestedData(SecCmsContentInfoRef cinfo, SecCmsDigest */ extern OSStatus SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -273,41 +273,41 @@ SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInf */ extern OSStatus SecCmsContentInfoSetContentEncryptedData(SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX OSStatus SecCmsContentInfoSetContentOther(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached, const CSSM_OID *eContentType) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX OSStatus SecCmsContentInfoSetContentOther(SecCmsContentInfoRef cinfo, SecAsn1Item *data, Boolean detached, const SecAsn1Oid *eContentType) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX extern OSStatus SecCmsContentInfoSetContentEncAlg(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, SECOidTag bulkalgtag, CSSM_DATA_PTR parameters, int keysize) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX extern OSStatus SecCmsContentInfoSetContentEncAlg(SecCmsContentInfoRef cinfo, SECOidTag bulkalgtag, const SecAsn1Item *parameters, int keysize) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX extern OSStatus SecCmsContentInfoSetContentEncAlgID(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, SECAlgorithmID *algid, int keysize) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX extern OSStatus SecCmsContentInfoSetContentEncAlgID(SecCmsContentInfoRef cinfo, SECAlgorithmID *algid, int keysize) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !!TARGET_OS_OSX /*! @@ -315,14 +315,14 @@ SecCmsContentInfoSetContentEncAlgID(SecCmsContentInfoRef cinfo, */ extern void SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey) - API_AVAILABLE(macos(10.4),ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4),ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); /*! @function */ extern SecSymmetricKeyRef SecCmsContentInfoGetBulkKey(SecCmsContentInfoRef cinfo) - API_AVAILABLE(macos(10.4),ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4),ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); /*! @function diff --git a/CMS/SecCmsDecoder.h b/CMS/SecCmsDecoder.h index b1eb50ec..1098f80d 100644 --- a/CMS/SecCmsDecoder.h +++ b/CMS/SecCmsDecoder.h @@ -68,7 +68,7 @@ SecCmsDecoderCreate(SecArenaPoolRef arena, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, SecCmsDecoderRef *outDecoder) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX /*! @function @@ -94,7 +94,7 @@ SecCmsDecoderCreate(SecCmsContentCallback cb, void *cb_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, SecCmsDecoderRef *outDecoder) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! @@ -161,7 +161,7 @@ SecCmsMessageDecode(const CSSM_DATA *encodedMessage, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, SecCmsMessageRef *outMessage) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX /*! @@ -190,7 +190,7 @@ SecCmsMessageDecode(const SecAsn1Item *encodedMessage, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, SecCmsMessageRef *outMessage) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX diff --git a/CMS/SecCmsDigestContext.h b/CMS/SecCmsDigestContext.h index 159a2827..0a6e0194 100644 --- a/CMS/SecCmsDigestContext.h +++ b/CMS/SecCmsDigestContext.h @@ -44,7 +44,7 @@ __BEGIN_DECLS #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern SecCmsDigestContextRef SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) - API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop /*! @@ -70,7 +70,7 @@ SecCmsDigestContextCancel(SecCmsDigestContextRef cmsdigcx); */ extern void SecCmsDigestContextDestroy(SecCmsDigestContextRef cmsdigcx) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // TARGET_OS_IPHONE #if TARGET_OS_OSX @@ -83,7 +83,7 @@ SecCmsDigestContextDestroy(SecCmsDigestContextRef cmsdigcx) extern OSStatus SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef arena, CSSM_DATA_PTR **digestsp) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #endif // TARGET_OS_OSX diff --git a/CMS/SecCmsDigestedData.h b/CMS/SecCmsDigestedData.h index 6fc48c99..466b3139 100644 --- a/CMS/SecCmsDigestedData.h +++ b/CMS/SecCmsDigestedData.h @@ -51,7 +51,7 @@ __BEGIN_DECLS #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern SecCmsDigestedDataRef SecCmsDigestedDataCreate(SecCmsMessageRef cmsg, SECAlgorithmID *digestalg) - API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4), ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop /*! diff --git a/CMS/SecCmsEncoder.h b/CMS/SecCmsEncoder.h index 102c39af..f43037ac 100644 --- a/CMS/SecCmsEncoder.h +++ b/CMS/SecCmsEncoder.h @@ -77,7 +77,7 @@ SecCmsEncoderCreate(SecCmsMessageRef cmsg, SecCmsGetDecryptKeyCallback encrypt_key_cb, void *encrypt_key_cb_arg, SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests, SecCmsEncoderRef *outEncoder) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX /*! @@ -107,7 +107,7 @@ SecCmsEncoderCreate(SecCmsMessageRef cmsg, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback encrypt_key_cb, void *encrypt_key_cb_arg, SecCmsEncoderRef *outEncoder) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! @@ -157,7 +157,7 @@ SecCmsEncoderFinish(SecCmsEncoderRef encoder); extern OSStatus SecCmsMessageEncode(SecCmsMessageRef cmsg, const CSSM_DATA *input, SecArenaPoolRef arena, CSSM_DATA_PTR outBer) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX /*! @@ -172,7 +172,7 @@ SecCmsMessageEncode(SecCmsMessageRef cmsg, const CSSM_DATA *input, SecArenaPoolR extern OSStatus SecCmsMessageEncode(SecCmsMessageRef cmsg, const SecAsn1Item *input, CFMutableDataRef outBer) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX __END_DECLS diff --git a/CMS/SecCmsMessage.h b/CMS/SecCmsMessage.h index 497c4677..7cbb8277 100644 --- a/CMS/SecCmsMessage.h +++ b/CMS/SecCmsMessage.h @@ -55,7 +55,7 @@ __BEGIN_DECLS */ extern SecCmsMessageRef SecCmsMessageCreate(SecArenaPoolRef poolp) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX @@ -69,7 +69,7 @@ SecCmsMessageCreate(SecArenaPoolRef poolp) */ extern SecCmsMessageRef SecCmsMessageCreate(void) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX @@ -119,7 +119,7 @@ SecCmsMessageGetContentInfo(SecCmsMessageRef cmsg); #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern CSSM_DATA_PTR SecCmsMessageGetContent(SecCmsMessageRef cmsg) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX /*! @@ -130,7 +130,7 @@ SecCmsMessageGetContent(SecCmsMessageRef cmsg) */ extern const SecAsn1Item * SecCmsMessageGetContent(SecCmsMessageRef cmsg) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! diff --git a/CMS/SecCmsRecipientInfo.h b/CMS/SecCmsRecipientInfo.h index f57481fd..66db12de 100644 --- a/CMS/SecCmsRecipientInfo.h +++ b/CMS/SecCmsRecipientInfo.h @@ -47,7 +47,7 @@ __BEGIN_DECLS */ extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreate(SecCmsMessageRef cmsg, SecCertificateRef cert) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX @@ -59,7 +59,7 @@ SecCmsRecipientInfoCreate(SecCmsMessageRef cmsg, SecCertificateRef cert) */ extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreate(SecCmsEnvelopedDataRef envd, SecCertificateRef cert) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX @@ -70,14 +70,14 @@ extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsEnvelopedDataRef envd, const SecAsn1Item *subjKeyID, SecPublicKeyRef pubKey) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX @@ -85,12 +85,12 @@ SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsEnvelopedDataRef envd, extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsMessageRef cmsg, SecCertificateRef cert) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OS_OSX extern SecCmsRecipientInfoRef SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsEnvelopedDataRef envd, SecCertificateRef cert) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX diff --git a/CMS/SecCmsSignedData.h b/CMS/SecCmsSignedData.h index f74f89b2..a6e3c2a2 100644 --- a/CMS/SecCmsSignedData.h +++ b/CMS/SecCmsSignedData.h @@ -165,7 +165,7 @@ SecCmsSignedDataContainsCertsOrCrls(SecCmsSignedDataRef sigd); #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern CSSM_DATA_PTR * SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX /*! @@ -174,7 +174,7 @@ SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd) */ extern SecAsn1Item * * SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX /*! @@ -200,7 +200,7 @@ SecCmsSignedDataCreateCertsOnly(SecCmsMessageRef cmsg, SecCertificateRef cert, B */ extern OSStatus SecCmsSignedDataSetDigestContext(SecCmsSignedDataRef sigd, SecCmsDigestContextRef digestContext) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macos, iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macos, macCatalyst); #endif #if TARGET_OS_OSX @@ -214,7 +214,7 @@ extern OSStatus SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, SECAlgorithmID **digestalgs, CSSM_DATA_PTR *digests) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #endif diff --git a/CMS/SecCmsSignerInfo.h b/CMS/SecCmsSignerInfo.h index f3f80d6e..095950c4 100644 --- a/CMS/SecCmsSignerInfo.h +++ b/CMS/SecCmsSignerInfo.h @@ -44,13 +44,13 @@ __BEGIN_DECLS #if TARGET_OS_OSX extern SecCmsSignerInfoRef SecCmsSignerInfoCreate(SecCmsMessageRef cmsg, SecIdentityRef identity, SECOidTag digestalgtag) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #else // !TARGET_OSX extern SecCmsSignerInfoRef SecCmsSignerInfoCreate(SecCmsSignedDataRef sigd, SecIdentityRef identity, SECOidTag digestalgtag) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX @@ -58,12 +58,12 @@ SecCmsSignerInfoCreate(SecCmsSignedDataRef sigd, SecIdentityRef identity, SECOid #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern SecCmsSignerInfoRef SecCmsSignerInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(macCatalyst); #pragma clang diagnostic pop #else // !TARGET_OS_OSX extern SecCmsSignerInfoRef SecCmsSignerInfoCreateWithSubjKeyID(SecCmsSignedDataRef sigd, const SecAsn1Item *subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) - API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macCatalyst); #endif // !TARGET_OS_OSX #if TARGET_OS_OSX @@ -73,7 +73,7 @@ SecCmsSignerInfoCreateWithSubjKeyID(SecCmsSignedDataRef sigd, const SecAsn1Item */ extern void SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si) - API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #endif /*! @@ -291,26 +291,26 @@ SecCertificateRef SecCmsSignerInfoCopyCertFromEncryptionKeyPreference(SecCmsSign extern OSStatus SecCmsSignerInfoVerifyUnAuthAttrs(SecCmsSignerInfoRef signerinfo) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); extern OSStatus SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeStampPolicy) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" extern CSSM_DATA * SecCmsSignerInfoGetEncDigest(SecCmsSignerInfoRef signerinfo) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma clang diagnostic pop extern CFArrayRef SecCmsSignerInfoGetTimestampCertList(SecCmsSignerInfoRef signerinfo) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); extern SecCertificateRef SecCmsSignerInfoGetTimestampSigningCert(SecCmsSignerInfoRef signerinfo) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function @@ -321,7 +321,7 @@ SecCmsSignerInfoGetTimestampSigningCert(SecCmsSignerInfoRef signerinfo) */ OSStatus SecCmsSignerInfoGetTimestampTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function @@ -332,7 +332,7 @@ SecCmsSignerInfoGetTimestampTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stim */ OSStatus SecCmsSignerInfoGetTimestampTimeWithPolicy(SecCmsSignerInfoRef sinfo, CFTypeRef timeStampPolicy, CFAbsoluteTime *stime) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function @@ -342,7 +342,7 @@ SecCmsSignerInfoGetTimestampTimeWithPolicy(SecCmsSignerInfoRef sinfo, CFTypeRef #pragma clang diagnostic ignored "-Wdeprecated-declarations" OSStatus SecCmsSignerInfoAddTimeStamp(SecCmsSignerInfoRef signerinfo, CSSM_DATA *tstoken) - API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma clang diagnostic pop #endif // TARGET_OS_OSX diff --git a/CircleJoinRequested/Applicant.m b/CircleJoinRequested/Applicant.m index 5cce5177..58692652 100644 --- a/CircleJoinRequested/Applicant.m +++ b/CircleJoinRequested/Applicant.m @@ -13,14 +13,10 @@ -(id)initWithPeerInfo:(SOSPeerInfoRef)peerInfo { - self = [super init]; - if (!self) { - return self; - } - - self.rawPeerInfo = CFRetainSafe(peerInfo); - self.applicantUIState = ApplicantWaiting; - + if ((self = [super init])) { + self.rawPeerInfo = CFRetainSafe(peerInfo); + self.applicantUIState = ApplicantWaiting; + } return self; } diff --git a/CircleJoinRequested/CircleJoinRequested.m b/CircleJoinRequested/CircleJoinRequested.m index 2d9caabd..88d42276 100644 --- a/CircleJoinRequested/CircleJoinRequested.m +++ b/CircleJoinRequested/CircleJoinRequested.m @@ -31,8 +31,7 @@ #import #import #import -#import -#import +#import #import #import #import diff --git a/KVSKeychainSyncingProxy/CKDAKSLockMonitor.m b/KVSKeychainSyncingProxy/CKDAKSLockMonitor.m index 8686852b..f971c794 100644 --- a/KVSKeychainSyncingProxy/CKDAKSLockMonitor.m +++ b/KVSKeychainSyncingProxy/CKDAKSLockMonitor.m @@ -31,9 +31,7 @@ } - (instancetype)init { - self = [super init]; - - if (self) { + if ((self = [super init])) { XPCNotificationDispatcher* dispatcher = [XPCNotificationDispatcher dispatcher]; _queue = dispatch_queue_create("CKDAKSLockMonitor", NULL); @@ -86,6 +84,7 @@ } - (void) _onqueueRecheck { + dispatch_assert_queue(_queue); CFErrorRef aksError = NULL; bool locked = true; // Assume locked if we get an error diff --git a/KVSKeychainSyncingProxy/CKDKVSProxy.m b/KVSKeychainSyncingProxy/CKDKVSProxy.m index d586951c..84b79828 100644 --- a/KVSKeychainSyncingProxy/CKDKVSProxy.m +++ b/KVSKeychainSyncingProxy/CKDKVSProxy.m @@ -40,12 +40,10 @@ #include "keychain/SecureObjectSync/SOSARCDefines.h" #include "keychain/SecureObjectSync/SOSKVSKeys.h" #include -#include #include "SOSCloudKeychainConstants.h" #include -#include #include #import "XPCNotificationDispatcher.h" @@ -202,7 +200,7 @@ static NSString *kMonitorWroteInTimeSlice = @"TimeSlice"; } - (void)synchronizeStore { - [self.store pushWrites]; + [self.store pushWrites:[NSArray array] requiresForceSync:YES]; } - (id) objectForKey: (NSString*) key { @@ -336,9 +334,9 @@ static NSString *kMonitorWroteInTimeSlice = @"TimeSlice"; [[self store] addOneToOutGoing]; [self.store setObject:obj forKey:key]; } - }]; - - [self.store pushWrites]; + }]; + + [self.store pushWrites:[mutableValues allKeys] requiresForceSync:NO]; } - (void)setObjectsFromDictionary:(NSDictionary *)values diff --git a/KVSKeychainSyncingProxy/CKDKVSStore.h b/KVSKeychainSyncingProxy/CKDKVSStore.h index 4e4b87dd..f20f0bf0 100644 --- a/KVSKeychainSyncingProxy/CKDKVSStore.h +++ b/KVSKeychainSyncingProxy/CKDKVSStore.h @@ -25,7 +25,7 @@ - (NSDictionary*) copyAsDictionary; -- (void)pushWrites; +- (void)pushWrites:(NSArray*)keys requiresForceSync:(BOOL)requiresForceSync; - (BOOL)pullUpdates:(NSError**) failure; - (void)kvsStoreChanged: (NSNotification*) notification; diff --git a/KVSKeychainSyncingProxy/CKDKVSStore.m b/KVSKeychainSyncingProxy/CKDKVSStore.m index 03386203..c46a6a41 100644 --- a/KVSKeychainSyncingProxy/CKDKVSStore.m +++ b/KVSKeychainSyncingProxy/CKDKVSStore.m @@ -19,6 +19,9 @@ #import "Analytics/Clients/SOSAnalytics.h" +#include "keychain/SecureObjectSync/SOSKVSKeys.h" +#include + struct CKDKVSCounters { uint64_t synchronize; uint64_t synchronizeWithCompletionHandler; @@ -29,8 +32,6 @@ struct CKDKVSCounters { uint64_t synchronizeFailures; }; - - @interface CKDKVSStore () @property (readwrite, weak) UbiqitousKVSProxy* proxy; @property (readwrite) NSUbiquitousKeyValueStore* cloudStore; @@ -45,20 +46,20 @@ struct CKDKVSCounters { } - (instancetype)init { - self = [super init]; + if ((self = [super init])) { - self->_cloudStore = [NSUbiquitousKeyValueStore defaultStore]; - self->_proxy = nil; + self->_cloudStore = [NSUbiquitousKeyValueStore defaultStore]; + self->_proxy = nil; - if (!self.cloudStore) { - secerror("NO NSUbiquitousKeyValueStore defaultStore!!!"); - return nil; - } - self.perfQueue = dispatch_queue_create("CKDKVSStorePerfQueue", NULL); - self.perfCounters = calloc(1, sizeof(struct CKDKVSCounters)); + if (!self.cloudStore) { + secerror("NO NSUbiquitousKeyValueStore defaultStore!!!"); + return nil; + } + self.perfQueue = dispatch_queue_create("CKDKVSStorePerfQueue", NULL); + self.perfCounters = calloc(1, sizeof(struct CKDKVSCounters)); - [self setupSamplers]; - + [self setupSamplers]; + } return self; } @@ -106,13 +107,70 @@ struct CKDKVSCounters { }]; } -- (void)pushWrites { - [[self cloudStore] synchronize]; + +- (void)forceSynchronizeWithKVS +{ + secnoticeq("pushWrites", "requesting force synchronization with KVS on CloudKit"); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSError *error = nil; + bool success = [self pullUpdates:&error]; + if(!success || error != nil) { + secerror("pushWrites: failed to synchronize with KVS: %@", error); + } else { + secnoticeq("pushWrites", "successfully synced with KVS!"); + } + }); dispatch_async(self.perfQueue, ^{ self.perfCounters->synchronize++; }); } +- (void)pushWrites:(NSArray*)keys requiresForceSync:(BOOL)requiresForceSync +{ + secnoticeq("pushWrites", "Push writes"); + + if (SecKVSOnCloudKitIsEnabled() == NO) { + secnoticeq("pushWrites", "KVS on CloudKit not enabled"); + + [[self cloudStore] synchronize]; + dispatch_async(self.perfQueue, ^{ + self.perfCounters->synchronize++; + }); + return; + } + + if(requiresForceSync == YES) { + secnoticeq("pushWrites", "requested to force synchronize"); + [self forceSynchronizeWithKVS]; + return; + } + + //if KVS on CK is enabled we should only force sync rings, circles, and key parameters + secnoticeq("pushWrites", "KVS on CloudKit enabled. Evaluating changed keys"); + + if (keys == nil || [keys count] == 0){ + secnoticeq("pushWrites", "key set is empty, returning"); + return; + } + + __block BOOL proceedWithSync = NO; + [keys enumerateObjectsUsingBlock:^(NSString *kvsKey, NSUInteger idx, BOOL *stop) { + if ([kvsKey containsString:(__bridge_transfer NSString*)sRingPrefix] || + [kvsKey containsString:(__bridge_transfer NSString*)sCirclePrefix] || + [kvsKey containsString:(__bridge_transfer NSString*)kSOSKVSKeyParametersKey]) { + proceedWithSync = YES; + } + }]; + + if (proceedWithSync == NO) { + secnoticeq("pushWrites", "no keys to force push, returning"); + return; + } + + [self forceSynchronizeWithKVS]; +} + // Runs on the same thread that posted the notification, and that thread _may_ be the // kdkvsproxy_queue (see 30470419). Avoid deadlock by bouncing through global queue. - (void)kvsStoreChangedAsync:(NSNotification *)notification @@ -217,8 +275,10 @@ struct CKDKVSCounters { self.perfCounters->synchronize++; }); secnotice("fresh", "%s RETURNING FROM syncdefaultsd SWCH: %@", kWAIT2MINID, self); - [[self cloudStore] synchronize]; // Per olivier in , sync before getting values - secnotice("fresh", "%s RETURNING FROM syncdefaultsd SYNC: %@", kWAIT2MINID, self); + if(SecKVSOnCloudKitIsEnabled() == NO) { + [[self cloudStore] synchronize]; // Per olivier in , sync before getting values + secnotice("fresh", "%s RETURNING FROM syncdefaultsd SYNC: %@", kWAIT2MINID, self); + } } dispatch_semaphore_signal(freshSemaphore); }]; diff --git a/KVSKeychainSyncingProxy/CKDStore.h b/KVSKeychainSyncingProxy/CKDStore.h index ec68f709..3fec1119 100644 --- a/KVSKeychainSyncingProxy/CKDStore.h +++ b/KVSKeychainSyncingProxy/CKDStore.h @@ -22,7 +22,7 @@ - (NSDictionary*) copyAsDictionary; -- (void)pushWrites; +- (void)pushWrites:(NSArray*)keys requiresForceSync:(BOOL)requiresForceSync; - (BOOL)pullUpdates:(NSError**) failure; - (void)perfCounters:(void(^)(NSDictionary *counters))callback; diff --git a/KVSKeychainSyncingProxy/XPCNotificationDispatcher.m b/KVSKeychainSyncingProxy/XPCNotificationDispatcher.m index 3b6d7dca..0c010d13 100644 --- a/KVSKeychainSyncingProxy/XPCNotificationDispatcher.m +++ b/KVSKeychainSyncingProxy/XPCNotificationDispatcher.m @@ -61,9 +61,7 @@ static const char *kXPCNotificationNameKey = "Notification"; } - (instancetype) init { - self = [super init]; - - if (self) { + if ((self = [super init])) { self.queue = dispatch_queue_create("XPC Notification Dispatch", DISPATCH_QUEUE_SERIAL); self.listeners = [NSPointerArray weakObjectsPointerArray]; __weak typeof(self) weakSelf = self; diff --git a/KVSKeychainSyncingProxy/cloudkeychainproxy.m b/KVSKeychainSyncingProxy/cloudkeychainproxy.m index b0f39a4c..b3a56ba8 100644 --- a/KVSKeychainSyncingProxy/cloudkeychainproxy.m +++ b/KVSKeychainSyncingProxy/cloudkeychainproxy.m @@ -70,52 +70,129 @@ #import "CKDSecuritydAccount.h" #import "CKDKVSStore.h" #import "CKDAKSLockMonitor.h" +#import "SOSCloudKeychainConstants.h" +#include -void finalize_connection(void *not_used); -void handle_connection_event(const xpc_connection_t peer); -static void cloudkeychainproxy_peer_dictionary_handler(const xpc_connection_t peer, xpc_object_t event); -static bool operation_put_dictionary(xpc_object_t event); -static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event); +#define PROXYXPCSCOPE "xpcproxy" -int ckdproxymain(int argc, const char *argv[]); +@interface CloudKeychainProxy : NSObject +-(id _Nullable) init; -#define PROXYXPCSCOPE "xpcproxy" +@property (nonatomic, retain) UbiqitousKVSProxy *proxyID; +@property (nonatomic, retain) xpc_connection_t listener; +@property (nonatomic, retain) dispatch_source_t sigterm_source; +@property (nonatomic, retain) NSURL *registrationFileName; + ++ (CloudKeychainProxy *) sharedObject; +- (void) cloudkeychainproxy_peer_dictionary_handler: (const xpc_connection_t) peer forEvent: (xpc_object_t) event; -static void describeXPCObject(char *prefix, xpc_object_t object) +@end + +static void cloudkeychainproxy_event_handler(xpc_connection_t peer) { -//#ifndef NDEBUG - // This is useful for debugging. - if (object) + if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) { + secinfo(PROXYXPCSCOPE, "expected XPC_TYPE_CONNECTION"); + return; + } + + xpc_object_t ent = xpc_connection_copy_entitlement_value(peer, "com.apple.CloudKeychainProxy.client"); + if (ent == NULL || xpc_get_type(ent) != XPC_TYPE_BOOL || xpc_bool_get_value(ent) != true) { + secnotice(PROXYXPCSCOPE, "cloudkeychainproxy_event_handler: rejected client %d", xpc_connection_get_pid(peer)); + xpc_connection_cancel(peer); + return; + } + + xpc_connection_set_target_queue(peer, [[CloudKeychainProxy sharedObject].proxyID ckdkvsproxy_queue]); + xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { + // We could handle other peer events (e.g.) disconnects, + // but we don't keep per-client state so there is no need. + if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) { + [[CloudKeychainProxy sharedObject] cloudkeychainproxy_peer_dictionary_handler: peer forEvent: event]; + } + }); + + // This will tell the connection to begin listening for events. If you + // have some other initialization that must be done asynchronously, then + // you can defer this call until after that initialization is done. + xpc_connection_resume(peer); +} + +static void finalize_connection(void *not_used) { + secinfo(PROXYXPCSCOPE, "finalize_connection"); + [[CloudKeychainProxy sharedObject].proxyID synchronizeStore]; + xpc_transaction_end(); +} + +@implementation CloudKeychainProxy + +static CFStringRef kRegistrationFileName = CFSTR("com.apple.security.cloudkeychainproxy3.keysToRegister.plist"); + ++ (CloudKeychainProxy *) sharedObject { + static CloudKeychainProxy *sharedCKP = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedCKP = [CloudKeychainProxy new]; + }); + + return sharedCKP; +} + +-(id _Nullable) init { + if ((self = [super init])) { + _registrationFileName = (NSURL *)CFBridgingRelease(SecCopyURLForFileInPreferencesDirectory(kRegistrationFileName)); + _proxyID = [UbiqitousKVSProxy withAccount: [CKDSecuritydAccount securitydAccount] + store: [CKDKVSStore kvsInterface] + lockMonitor: [CKDAKSLockMonitor monitor] + persistence: _registrationFileName]; + + _listener = xpc_connection_create_mach_service(kCKPServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); + xpc_connection_set_finalizer_f(_listener, finalize_connection); + xpc_connection_set_event_handler(_listener, ^(xpc_object_t object){ cloudkeychainproxy_event_handler(object); }); + + // It looks to me like there is insufficient locking to allow a request to come in on the XPC connection while doing the initial all items. + // Therefore I'm leaving the XPC connection suspended until that has time to process. + xpc_connection_resume(_listener); + + (void)signal(SIGTERM, SIG_IGN); + _sigterm_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, _proxyID.ckdkvsproxy_queue); + dispatch_source_set_event_handler(_sigterm_source, ^{ + secnotice(PROXYXPCSCOPE, "exiting due to SIGTERM"); + xpc_transaction_exit_clean(); + }); + dispatch_activate(_sigterm_source); + } + return self; +} + + +- (void) describeXPCObject: (char *) prefix withObject: (xpc_object_t) object { + if(object) { char *desc = xpc_copy_description(object); - secdebug(PROXYXPCSCOPE, "%s%s\n", prefix, desc); + secinfo(PROXYXPCSCOPE, "%s%s", prefix, desc); free(desc); + } else { + secinfo(PROXYXPCSCOPE, "%s", prefix); } - else - secdebug(PROXYXPCSCOPE, "%s\n", prefix); - -//#endif } -static NSObject *CreateNSObjectForCFXPCObjectFromKey(xpc_object_t xdict, const char * _Nonnull key) -{ +- (NSObject *) CreateNSObjectForCFXPCObjectFromKey: (xpc_object_t) xdict withKey: (const char * _Nonnull) key { xpc_object_t xObj = xpc_dictionary_get_value(xdict, key); - if (!xObj) { return nil; } - return (__bridge_transfer NSObject *)(_CFXPCCreateCFObjectFromXPCObject(xObj)); } -static NSArray *CreateArrayOfStringsForCFXPCObjectFromKey(xpc_object_t xdict, const char * _Nonnull key) { - NSObject * possibleArray = CreateNSObjectForCFXPCObjectFromKey(xdict, key); +- (NSArray *) CreateArrayOfStringsForCFXPCObjectFromKey: (xpc_object_t) xdict withKey: (const char * _Nonnull) key { + NSObject * possibleArray = [self CreateNSObjectForCFXPCObjectFromKey: xdict withKey: key]; - if (![possibleArray isNSArray__]) + if (![possibleArray isNSArray__]) { return nil; - + } + __block bool onlyStrings = true; [(NSArray*) possibleArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (![obj isNSString__]) { @@ -127,208 +204,187 @@ static NSArray *CreateArrayOfStringsForCFXPCObjectFromKey(xpc_object_ return onlyStrings ? (NSArray*) possibleArray : nil; } -static CFStringRef kRegistrationFileName = CFSTR("com.apple.security.cloudkeychainproxy3.keysToRegister.plist"); - -static UbiqitousKVSProxy *SharedProxy(void) { - static UbiqitousKVSProxy *sProxy = NULL; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sProxy = [UbiqitousKVSProxy withAccount: [CKDSecuritydAccount securitydAccount] - store: [CKDKVSStore kvsInterface] - lockMonitor: [CKDAKSLockMonitor monitor] - persistence: (NSURL *)CFBridgingRelease(SecCopyURLForFileInPreferencesDirectory(kRegistrationFileName))]; - }); - - return sProxy; -} - -static void sendAckResponse(const xpc_connection_t peer, xpc_object_t event) { +- (void) sendAckResponse: (const xpc_connection_t) peer forEvent: (xpc_object_t) event { xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) // Caller wanted an ACK, so give one - { + if (replyMessage) { // Caller wanted an ACK, so give one xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); xpc_connection_send_message(peer, replyMessage); } } -static void cloudkeychainproxy_peer_dictionary_handler(const xpc_connection_t peer, xpc_object_t event) -{ +- (void) cloudkeychainproxy_peer_dictionary_handler: (const xpc_connection_t) peer forEvent: (xpc_object_t) event { bool result = false; int err = 0; - require_action_string(xpc_get_type(event) == XPC_TYPE_DICTIONARY, xit, err = -51, "expected XPC_TYPE_DICTIONARY"); + @autoreleasepool { - const char *operation = xpc_dictionary_get_string(event, kMessageKeyOperation); - require_action(operation, xit, result = false); + require_action_string(xpc_get_type(event) == XPC_TYPE_DICTIONARY, xit, err = -51, "expected XPC_TYPE_DICTIONARY"); - // Check protocol version - uint64_t version = xpc_dictionary_get_uint64(event, kMessageKeyVersion); - secdebug(PROXYXPCSCOPE, "Reply version: %lld\n", version); - require_action(version == kCKDXPCVersion, xit, result = false); + const char *operation = xpc_dictionary_get_string(event, kMessageKeyOperation); + require_action(operation, xit, result = false); - // Operations - secdebug(PROXYXPCSCOPE, "Handling %s operation", operation); + // Check protocol version + uint64_t version = xpc_dictionary_get_uint64(event, kMessageKeyVersion); + secinfo(PROXYXPCSCOPE, "Reply version: %lld", version); + require_action(version == kCKDXPCVersion, xit, result = false); + // Operations + secinfo(PROXYXPCSCOPE, "Handling %s operation", operation); - if (!strcmp(operation, kOperationPUTDictionary)) - { - operation_put_dictionary(event); - sendAckResponse(peer, event); - } - else if (!strcmp(operation, kOperationGETv2)) - { - operation_get_v2(peer, event); - // operationg_get_v2 sends the response - } - else if (!strcmp(operation, kOperationClearStore)) - { - [SharedProxy() clearStore]; - sendAckResponse(peer, event); - } - else if (!strcmp(operation, kOperationSynchronize)) - { - [SharedProxy() synchronizeStore]; - sendAckResponse(peer, event); - } - else if (!strcmp(operation, kOperationSynchronizeAndWait)) - { - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - secnotice(XPROXYSCOPE, "%s XPC request: %s", kWAIT2MINID, kOperationSynchronizeAndWait); - - [SharedProxy() waitForSynchronization:^(__unused NSDictionary *values, NSError *error) - { - secnotice(PROXYXPCSCOPE, "%s Result from [Proxy waitForSynchronization:]: %@", kWAIT2MINID, error); - if (replyMessage) // Caller wanted an ACK, so give one + if (!strcmp(operation, kOperationPUTDictionary)) + { + [self operation_put_dictionary: event]; + [self sendAckResponse: peer forEvent: event]; + } + else if (!strcmp(operation, kOperationGETv2)) + { + [self operation_get_v2: peer forEvent: event]; + // operationg_get_v2 sends the response + } + else if (!strcmp(operation, kOperationClearStore)) + { + [_proxyID clearStore]; + [self sendAckResponse: peer forEvent: event]; + } + else if (!strcmp(operation, kOperationSynchronize)) + { + [_proxyID synchronizeStore]; + [self sendAckResponse: peer forEvent: event]; + } + else if (!strcmp(operation, kOperationSynchronizeAndWait)) + { + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + secnotice(XPROXYSCOPE, "%s XPC request: %s", kWAIT2MINID, kOperationSynchronizeAndWait); + + [_proxyID waitForSynchronization:^(__unused NSDictionary *values, NSError *error) { - if (error) + secnotice(PROXYXPCSCOPE, "%s Result from [Proxy waitForSynchronization:]: %@", kWAIT2MINID, error); + + if (replyMessage) // Caller wanted an ACK, so give one { - xpc_object_t xerrobj = SecCreateXPCObjectWithCFError((__bridge CFErrorRef)(error)); - xpc_dictionary_set_value(replyMessage, kMessageKeyError, xerrobj); - } else { - xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + if (error) + { + xpc_object_t xerrobj = SecCreateXPCObjectWithCFError((__bridge CFErrorRef)(error)); + xpc_dictionary_set_value(replyMessage, kMessageKeyError, xerrobj); + } else { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + } + xpc_connection_send_message(peer, replyMessage); } - xpc_connection_send_message(peer, replyMessage); - } - }]; - } - else if (!strcmp(operation, kOperationRegisterKeys)) - { - xpc_object_t xkeysToRegisterDict = xpc_dictionary_get_value(event, kMessageKeyValue); + }]; + } + else if (!strcmp(operation, kOperationRegisterKeys)) + { + xpc_object_t xkeysToRegisterDict = xpc_dictionary_get_value(event, kMessageKeyValue); - xpc_object_t xKTRallkeys = xpc_dictionary_get_value(xkeysToRegisterDict, kMessageAllKeys); + xpc_object_t xKTRallkeys = xpc_dictionary_get_value(xkeysToRegisterDict, kMessageAllKeys); - NSString* accountUUID = (NSString*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyAccountUUID); + NSString* accountUUID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey:event withKey: kMessageKeyAccountUUID]; - if (![accountUUID isKindOfClass:[NSString class]]) { - accountUUID = nil; - } + if (![accountUUID isKindOfClass:[NSString class]]) { + accountUUID = nil; + } - NSDictionary *KTRallkeys = (__bridge_transfer NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xKTRallkeys)); + NSDictionary *KTRallkeys = (__bridge_transfer NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xKTRallkeys)); - [SharedProxy() registerKeys: KTRallkeys forAccount: accountUUID]; - sendAckResponse(peer, event); + [_proxyID registerKeys: KTRallkeys forAccount: accountUUID]; + [self sendAckResponse: peer forEvent: event]; - secdebug(PROXYXPCSCOPE, "RegisterKeys message sent"); - } - else if (!strcmp(operation, kOperationRemoveKeys)) - { - xpc_object_t xkeysToRemoveDict = xpc_dictionary_get_value(event, kMessageKeyValue); - - NSString* accountUUID = (NSString*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyAccountUUID); - - if (![accountUUID isKindOfClass:[NSString class]]) { - accountUUID = nil; + secinfo(PROXYXPCSCOPE, "RegisterKeys message sent"); } - - NSArray *KTRallkeys = (__bridge_transfer NSArray *)(_CFXPCCreateCFObjectFromXPCObject(xkeysToRemoveDict)); - - [SharedProxy() removeKeys:KTRallkeys forAccount:accountUUID]; - sendAckResponse(peer, event); - - secdebug(PROXYXPCSCOPE, "RemoveKeys message sent"); - } - else if (!strcmp(operation, kOperationRequestSyncWithPeers)) - { + else if (!strcmp(operation, kOperationRemoveKeys)) + { + xpc_object_t xkeysToRemoveDict = xpc_dictionary_get_value(event, kMessageKeyValue); + + NSString* accountUUID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey: event withKey: kMessageKeyAccountUUID]; + + if (![accountUUID isKindOfClass:[NSString class]]) { + accountUUID = nil; + } + + NSArray *KTRallkeys = (__bridge_transfer NSArray *)(_CFXPCCreateCFObjectFromXPCObject(xkeysToRemoveDict)); + + [_proxyID removeKeys:KTRallkeys forAccount:accountUUID]; + [self sendAckResponse: peer forEvent: event]; + + secinfo(PROXYXPCSCOPE, "RemoveKeys message sent"); + } + else if (!strcmp(operation, kOperationRequestSyncWithPeers)) + { - NSArray * peerIDs = CreateArrayOfStringsForCFXPCObjectFromKey(event, kMessageKeyPeerIDList); - NSArray * backupPeerIDs = CreateArrayOfStringsForCFXPCObjectFromKey(event, kMesssgeKeyBackupPeerIDList); + NSArray * peerIDs = [self CreateArrayOfStringsForCFXPCObjectFromKey: event withKey: kMessageKeyPeerIDList]; + NSArray * backupPeerIDs = [self CreateArrayOfStringsForCFXPCObjectFromKey: event withKey: kMesssgeKeyBackupPeerIDList]; - require_action(peerIDs && backupPeerIDs, xit, (secnotice(XPROXYSCOPE, "Bad call to sync with peers"), result = false)); + require_action(peerIDs && backupPeerIDs, xit, (secnotice(XPROXYSCOPE, "Bad call to sync with peers"), result = false)); - [SharedProxy() requestSyncWithPeerIDs: peerIDs backupPeerIDs: backupPeerIDs]; - sendAckResponse(peer, event); + [_proxyID requestSyncWithPeerIDs: peerIDs backupPeerIDs: backupPeerIDs]; + [self sendAckResponse: peer forEvent: event]; - secdebug(PROXYXPCSCOPE, "RequestSyncWithAllPeers reply sent"); - } - else if (!strcmp(operation, kOperationHasPendingSyncWithPeer)) { - NSString *peerID = (NSString*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyPeerID); + secinfo(PROXYXPCSCOPE, "RequestSyncWithAllPeers reply sent"); + } + else if (!strcmp(operation, kOperationHasPendingSyncWithPeer)) { + NSString *peerID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey: event withKey: kMessageKeyPeerID]; - BOOL hasPending = [SharedProxy() hasSyncPendingFor: peerID]; + BOOL hasPending = [_proxyID hasSyncPendingFor: peerID]; - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) - { - xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, hasPending); - xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "HasPendingSyncWithPeer reply sent"); + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) + { + xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, hasPending); + xpc_connection_send_message(peer, replyMessage); + secinfo(PROXYXPCSCOPE, "HasPendingSyncWithPeer reply sent"); + } } - } - else if (!strcmp(operation, kOperationHasPendingKey)) { - NSString *peerID = (NSString*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyPeerID); + else if (!strcmp(operation, kOperationHasPendingKey)) { + NSString *peerID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey: event withKey: kMessageKeyPeerID]; - BOOL hasPending = [SharedProxy() hasPendingKey: peerID]; + BOOL hasPending = [_proxyID hasPendingKey: peerID]; - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) + { + xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, hasPending); + xpc_connection_send_message(peer, replyMessage); + secinfo(PROXYXPCSCOPE, "HasIncomingMessageFromPeer reply sent"); + } + } + else if (!strcmp(operation, kOperationRequestEnsurePeerRegistration)) { - xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, hasPending); - xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "HasIncomingMessageFromPeer reply sent"); + [_proxyID requestEnsurePeerRegistration]; + [self sendAckResponse: peer forEvent: event]; + secinfo(PROXYXPCSCOPE, "RequestEnsurePeerRegistration reply sent"); } - } - else if (!strcmp(operation, kOperationRequestEnsurePeerRegistration)) - { - [SharedProxy() requestEnsurePeerRegistration]; - sendAckResponse(peer, event); - secdebug(PROXYXPCSCOPE, "RequestEnsurePeerRegistration reply sent"); - } - else if (!strcmp(operation, kOperationFlush)) - { - [SharedProxy() doAfterFlush:^{ - sendAckResponse(peer, event); - secdebug(PROXYXPCSCOPE, "flush reply sent"); - }]; - } - else if (!strcmp(operation, kOperationPerfCounters)) { - [SharedProxy() perfCounters:^(NSDictionary *counters){ - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_object_t object = _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)counters); - xpc_dictionary_set_value(replyMessage, kMessageKeyValue, object); - xpc_connection_send_message(peer, replyMessage); - }]; - } - else - { - char *description = xpc_copy_description(event); - secdebug(PROXYXPCSCOPE, "Unknown op=%s request from pid %d: %s", operation, xpc_connection_get_pid(peer), description); - free(description); - } - result = true; + else if (!strcmp(operation, kOperationFlush)) + { + [_proxyID doAfterFlush:^{ + [self sendAckResponse: peer forEvent: event]; + secinfo(PROXYXPCSCOPE, "flush reply sent"); + }]; + } + else if (!strcmp(operation, kOperationPerfCounters)) { + [_proxyID perfCounters:^(NSDictionary *counters){ + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + xpc_object_t object = _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)counters); + xpc_dictionary_set_value(replyMessage, kMessageKeyValue, object); + xpc_connection_send_message(peer, replyMessage); + }]; + } + else + { + char *description = xpc_copy_description(event); + secinfo(PROXYXPCSCOPE, "Unknown op=%s request from pid %d: %s", operation, xpc_connection_get_pid(peer), description); + free(description); + } + result = true; xit: - if (!result) - describeXPCObject("handle_operation fail: ", event); -} - -void finalize_connection(void *not_used) -{ - secdebug(PROXYXPCSCOPE, "finalize_connection"); - [SharedProxy() synchronizeStore]; - xpc_transaction_end(); + if (!result) { + [self describeXPCObject: "handle_operation fail: " withObject: event]; + } + } } -static bool operation_put_dictionary(xpc_object_t event) -{ +- (bool) operation_put_dictionary: (xpc_object_t) event { // PUT a set of objects into the KVS store. Return false if error xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); if (!xvalue) { @@ -337,29 +393,28 @@ static bool operation_put_dictionary(xpc_object_t event) NSObject* object = (__bridge_transfer NSObject*) _CFXPCCreateCFObjectFromXPCObject(xvalue); if (![object isKindOfClass:[NSDictionary class]]) { - describeXPCObject("operation_put_dictionary unable to convert to CF: ", xvalue); + [self describeXPCObject: "operation_put_dictionary unable to convert to CF: " withObject: xvalue]; return false; } - [SharedProxy() setObjectsFromDictionary: (NSDictionary *)object]; + [_proxyID setObjectsFromDictionary: (NSDictionary *)object]; return true; } -static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) -{ +- (bool) operation_get_v2: (xpc_connection_t) peer forEvent: (xpc_object_t) event { // GET a set of objects from the KVS store. Return false if error xpc_object_t replyMessage = xpc_dictionary_create_reply(event); if (!replyMessage) { - secdebug(PROXYXPCSCOPE, "can't create replyMessage"); + secinfo(PROXYXPCSCOPE, "can't create replyMessage"); assert(false); //must have a reply handler return false; } xpc_object_t returnedValues = xpc_dictionary_create(NULL, NULL, 0); if (!returnedValues) { - secdebug(PROXYXPCSCOPE, "can't create returnedValues"); + secinfo(PROXYXPCSCOPE, "can't create returnedValues"); assert(false); // must have a spot for the returned values return false; } @@ -367,18 +422,18 @@ static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); if (!xvalue) { - secdebug(PROXYXPCSCOPE, "missing \"value\" key"); + secinfo(PROXYXPCSCOPE, "missing \"value\" key"); return false; } xpc_object_t xkeystoget = xpc_dictionary_get_value(xvalue, kMessageKeyKeysToGet); if (xkeystoget) { - secdebug(PROXYXPCSCOPE, "got xkeystoget"); + secinfo(PROXYXPCSCOPE, "got xkeystoget"); CFTypeRef keystoget = _CFXPCCreateCFObjectFromXPCObject(xkeystoget); if (!keystoget || (CFGetTypeID(keystoget)!=CFArrayGetTypeID())) // not "getAll", this is an error of some kind { - secdebug(PROXYXPCSCOPE, "can't convert keystoget or is not an array"); + secinfo(PROXYXPCSCOPE, "can't convert keystoget or is not an array"); CFReleaseSafe(keystoget); return false; } @@ -386,16 +441,16 @@ static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) [(__bridge NSArray *)keystoget enumerateObjectsUsingBlock: ^ (id obj, NSUInteger idx, BOOL *stop) { NSString *key = (NSString *)obj; - id object = [SharedProxy() objectForKey:key]; - secdebug(PROXYXPCSCOPE, "get: key: %@, object: %@", key, object); + id object = [_proxyID objectForKey:key]; + secinfo(PROXYXPCSCOPE, "get: key: %@, object: %@", key, object); xpc_object_t xobject = object ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)object) : xpc_null_create(); xpc_dictionary_set_value(returnedValues, [key UTF8String], xobject); }]; } else // get all values from kvs { - secdebug(PROXYXPCSCOPE, "get all values from kvs"); - NSDictionary *all = [SharedProxy() copyAsDictionary]; + secinfo(PROXYXPCSCOPE, "get all values from kvs"); + NSDictionary *all = [_proxyID copyAsDictionary]; [all enumerateKeysAndObjectsUsingBlock: ^ (id key, id obj, BOOL *stop) { xpc_object_t xobject = obj ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)obj) : xpc_null_create(); @@ -410,53 +465,23 @@ static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) return true; } -static void cloudkeychainproxy_event_handler(xpc_connection_t peer) -{ - if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) - { - secdebug(PROXYXPCSCOPE, "expected XPC_TYPE_CONNECTION"); - return; - } - - xpc_object_t ent = xpc_connection_copy_entitlement_value(peer, "com.apple.CloudKeychainProxy.client"); - if (ent == NULL || xpc_get_type(ent) != XPC_TYPE_BOOL || xpc_bool_get_value(ent) != true) { - secnotice(PROXYXPCSCOPE, "cloudkeychainproxy_event_handler: rejected client %d", xpc_connection_get_pid(peer)); - xpc_connection_cancel(peer); - return; - } - xpc_connection_set_target_queue(peer, [SharedProxy() ckdkvsproxy_queue]); - xpc_connection_set_event_handler(peer, ^(xpc_object_t event) - { - // We could handle other peer events (e.g.) disconnects, - // but we don't keep per-client state so there is no need. - if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) { - cloudkeychainproxy_peer_dictionary_handler(peer, event); - } - }); - - // This will tell the connection to begin listening for events. If you - // have some other initialization that must be done asynchronously, then - // you can defer this call until after that initialization is done. - xpc_connection_resume(peer); -} +@end -static void diagnostics(int argc, const char *argv[]) -{ - @autoreleasepool - { - NSDictionary *all = [SharedProxy() copyAsDictionary]; +static void diagnostics(int argc, const char *argv[]) { + @autoreleasepool { + NSDictionary *all = [[CloudKeychainProxy sharedObject].proxyID copyAsDictionary]; NSLog(@"All: %@",all); } } -int ckdproxymain(int argc, const char *argv[]) -{ - secdebug(PROXYXPCSCOPE, "Starting CloudKeychainProxy"); + + +int main(int argc, const char *argv[]) { + secinfo(PROXYXPCSCOPE, "Starting CloudKeychainProxy"); char *wait4debugger = getenv("WAIT4DEBUGGER"); - if (wait4debugger && !strcasecmp("YES", wait4debugger)) - { + if (wait4debugger && !strcasecmp("YES", wait4debugger)) { syslog(LOG_ERR, "Waiting for debugger"); kill(getpid(), SIGTSTP); } @@ -465,31 +490,18 @@ int ckdproxymain(int argc, const char *argv[]) diagnostics(argc, argv); return 0; } - - UbiqitousKVSProxy* proxyID = SharedProxy(); - - if (proxyID) { // nothing bad happened when initializing - xpc_connection_t listener = xpc_connection_create_mach_service(kCKPServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); - xpc_connection_set_event_handler(listener, ^(xpc_object_t object){ cloudkeychainproxy_event_handler(object); }); - - // It looks to me like there is insufficient locking to allow a request to come in on the XPC connection while doing the initial all items. - // Therefore I'm leaving the XPC connection suspended until that has time to process. - xpc_connection_resume(listener); - - @autoreleasepool - { - secdebug(PROXYXPCSCOPE, "Starting mainRunLoop"); - NSRunLoop *runLoop = [NSRunLoop mainRunLoop]; - [runLoop run]; - } + + CloudKeychainProxy *ckp = nil; + @autoreleasepool { + ckp = [CloudKeychainProxy sharedObject]; } - - secdebug(PROXYXPCSCOPE, "Exiting CloudKeychainProxy"); + + if (ckp) { // nothing bad happened when initializing + secinfo(PROXYXPCSCOPE, "Starting mainRunLoop"); + NSRunLoop *runLoop = [NSRunLoop mainRunLoop]; + [runLoop run]; + } + secinfo(PROXYXPCSCOPE, "Exiting CloudKeychainProxy"); return EXIT_FAILURE; } - -int main(int argc, const char *argv[]) -{ - return ckdproxymain(argc, argv); -} diff --git a/KeychainCircle/KCAESGCMDuplexSession.m b/KeychainCircle/KCAESGCMDuplexSession.m index 3bc684cd..bd17f5a6 100644 --- a/KeychainCircle/KCAESGCMDuplexSession.m +++ b/KeychainCircle/KCAESGCMDuplexSession.m @@ -162,29 +162,28 @@ static NSString* KCDSEpoch= @"epoch"; freeWhenDone: false]; }); - self = [super init]; - - self.asSender = sender; - self.secret = sharedSecret; - self.send = malloc(ccgcm_context_size(ccaes_gcm_encrypt_mode())); - self.receive = malloc(ccgcm_context_size(ccaes_gcm_decrypt_mode())); - self.context = context; - - _pairingUUID = pairingUUID; - _piggybackingVersion = piggybackingVersion; - _epoch = epoch; - - if (self.send == nil || self.receive == nil) { - return nil; + if ((self = [super init])) { + self.asSender = sender; + self.secret = sharedSecret; + self.send = malloc(ccgcm_context_size(ccaes_gcm_encrypt_mode())); + self.receive = malloc(ccgcm_context_size(ccaes_gcm_decrypt_mode())); + self.context = context; + + _pairingUUID = pairingUUID; + _piggybackingVersion = piggybackingVersion; + _epoch = epoch; + + if (self.send == nil || self.receive == nil) { + return nil; + } + + derive_and_init(ccaes_gcm_encrypt_mode(), + self.send, self.secret, + sender ? kdfInfoSendToReceive : kdfInfoReceiveToSend); + derive_and_init(ccaes_gcm_decrypt_mode(), + self.receive, self.secret, + !sender ? kdfInfoSendToReceive : kdfInfoReceiveToSend); } - - derive_and_init(ccaes_gcm_encrypt_mode(), - self.send, self.secret, - sender ? kdfInfoSendToReceive : kdfInfoReceiveToSend); - derive_and_init(ccaes_gcm_decrypt_mode(), - self.receive, self.secret, - !sender ? kdfInfoSendToReceive : kdfInfoReceiveToSend); - return self; } diff --git a/KeychainCircle/KCError.h b/KeychainCircle/KCError.h index 1f9d1874..9b140fe5 100644 --- a/KeychainCircle/KCError.h +++ b/KeychainCircle/KCError.h @@ -18,6 +18,8 @@ typedef enum { kUnexpectedMessage, kInternalError, kDERUnknownVersion, + kProcessApplicationFailure, + kUnsupportedTrustPlatform, } KCJoiningError; @interface NSError(KCJoiningError) diff --git a/KeychainCircle/KCJoiningAcceptSession.m b/KeychainCircle/KCJoiningAcceptSession.m index 931144a8..8e865fdf 100644 --- a/KeychainCircle/KCJoiningAcceptSession.m +++ b/KeychainCircle/KCJoiningAcceptSession.m @@ -20,7 +20,6 @@ #include #include #include -#include #include #if OCTAGON @@ -30,6 +29,9 @@ #import "keychain/ot/proto/generated_source/OTApplicantToSponsorRound2M1.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.h" +#import "keychain/ot/proto/generated_source/OTGlobalEnums.h" +#import "keychain/ot/proto/generated_source/OTSupportSOSMessage.h" +#import "keychain/ot/proto/generated_source/OTSupportOctagonMessage.h" #import "keychain/ot/proto/generated_source/OTPairingMessage.h" #endif @@ -103,39 +105,39 @@ typedef enum { dsid: (uint64_t) dsid rng: (struct ccrng_state *)rng error: (NSError**) error { - self = [super init]; + if ((self = [super init])) { - secnotice("accepting", "initWithSecretDelegate"); + secnotice("accepting", "initWithSecretDelegate"); - NSString* name = [NSString stringWithFormat: @"%llu", dsid]; + NSString* name = [NSString stringWithFormat: @"%llu", dsid]; - self->_context = [[KCSRPServerContext alloc] initWithUser: name - password: [secretDelegate secret] - digestInfo: ccsha256_di() - group: ccsrp_gp_rfc5054_3072() - randomSource: rng]; - self.secretDelegate = secretDelegate; - self.circleDelegate = circleDelegate; - self->_state = kExpectingA; - self->_dsid = dsid; - self->_piggy_uuid = nil; - self->_defaults = [NSMutableDictionary dictionary]; + self->_context = [[KCSRPServerContext alloc] initWithUser: name + password: [secretDelegate secret] + digestInfo: ccsha256_di() + group: ccsrp_gp_rfc5054_3072() + randomSource: rng]; + self.secretDelegate = secretDelegate; + self.circleDelegate = circleDelegate; + self->_state = kExpectingA; + self->_dsid = dsid; + self->_piggy_uuid = nil; + self->_defaults = [NSMutableDictionary dictionary]; #if OCTAGON - self->_otControl = [OTControl controlObject:true error:error]; - self->_piggy_version = KCJoiningOctagonPiggybackingEnabled()? kPiggyV2 : kPiggyV1; - self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:@"OctagonPiggybacking" - uniqueDeviceID:@"acceptor-deviceid" - uniqueClientID:@"requester-deviceid" - pairingUUID:[[NSUUID UUID] UUIDString] - containerName:nil - contextID:OTDefaultContext - epoch:0 - isInitiator:false]; + self->_otControl = [OTControl controlObject:true error:error]; + self->_piggy_version = KCJoiningOctagonPiggybackingEnabled()? kPiggyV2 : kPiggyV1; + self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:@"OctagonPiggybacking" + uniqueDeviceID:@"acceptor-deviceid" + uniqueClientID:@"requester-deviceid" + pairingUUID:[[NSUUID UUID] UUIDString] + containerName:nil + contextID:OTDefaultContext + epoch:0 + isInitiator:false]; #else - self->_piggy_version = kPiggyV1; + self->_piggy_version = kPiggyV1; #endif - + } return self; } @@ -243,8 +245,14 @@ typedef enum { captureError = epochError; }else{ OTPairingMessage* responseMessage = [[OTPairingMessage alloc] init]; + responseMessage.supportsSOS = [[OTSupportSOSMessage alloc] init]; + responseMessage.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; + responseMessage.epoch = [[OTSponsorToApplicantRound1M2 alloc] init]; responseMessage.epoch.epoch = epoch; + + responseMessage.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + responseMessage.supportsOctagon.supported = OTSupportType_supported; next = responseMessage.data; } dispatch_semaphore_signal(sema); @@ -405,7 +413,7 @@ typedef enum { - (NSData*) createTLKRequestResponse: (NSError**) error { NSError* localError = NULL; - NSData* initialSync = [self.circleDelegate circleGetInitialSyncViews:kSOSInitialSyncFlagTLKs error:&localError]; + NSData* initialSync = [self.circleDelegate circleGetInitialSyncViews:kSOSInitialSyncFlagTLKsRequestOnly error:&localError]; if (!initialSync) { secnotice("joining", "Failed to get initial sync view: %@", localError); if ( error!=NULL && localError != NULL ) @@ -429,6 +437,26 @@ typedef enum { error:error] der]; } + +- (BOOL)shouldProcessSOSApplication:(KCJoiningMessage*)message pairingMessage:(OTPairingMessage*)pairingMessage +{ + BOOL shouldProcess = YES; + + if (OctagonPlatformSupportsSOS() == NO) { + secnotice("joining", "platform does not support SOS"); + shouldProcess = NO; + } else if (message.secondData == nil) { + secnotice("joining", "message does not contain SOS data"); + shouldProcess = NO; + } else if (pairingMessage.hasSupportsSOS && pairingMessage.supportsSOS.supported == OTSupportType_not_supported) { + secnotice("joining", "requester explicitly does not support SOS"); + shouldProcess = NO; + } + + return shouldProcess; +} + + - (NSData*) processApplication: (KCJoiningMessage*) message error:(NSError**) error { if ([message type] == kTLKRequest) { @@ -473,9 +501,14 @@ typedef enum { localError = err; }else{ OTPairingMessage *pairingResponse = [[OTPairingMessage alloc] init]; + pairingResponse.supportsSOS = [[OTSupportSOSMessage alloc] init]; + pairingResponse.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; pairingResponse.voucher = [[OTSponsorToApplicantRound2M2 alloc] init]; pairingResponse.voucher.voucher = voucher; pairingResponse.voucher.voucherSignature = voucherSig; + + pairingMessage.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + pairingMessage.supportsOctagon.supported = OTSupportType_supported; next = pairingResponse.data; } dispatch_semaphore_signal(sema); @@ -493,17 +526,19 @@ typedef enum { } NSData* encryptedOutgoing = nil; - if (OctagonPlatformSupportsSOS() && message.secondData) { + if ([self shouldProcessSOSApplication:message pairingMessage:pairingMessage]) { secnotice("joining", "doing SOS processSOSApplication"); - //note we are stuffing SOS into the payload "secondData" encryptedOutgoing = [self processSOSApplication: message.secondData error:error]; - } else { - secnotice("joining", "no platform support processSOSApplication, peer sent data: %s", - message.secondData ? "yes" : "no"); + if (encryptedOutgoing == nil) { + secerror("joining: failed to process SOS application: %@", error && *error ? *error : nil); + KCJoiningErrorCreate(kProcessApplicationFailure, error, @"message failed to process application"); + return nil; + } } self->_state = kAcceptDone; + //note we are stuffing SOS into the payload return [[KCJoiningMessage messageWithType:kCircleBlob data:next payload:encryptedOutgoing diff --git a/KeychainCircle/KCJoiningMessages.h b/KeychainCircle/KCJoiningMessages.h index 5dc66c70..97f57d80 100644 --- a/KeychainCircle/KCJoiningMessages.h +++ b/KeychainCircle/KCJoiningMessages.h @@ -111,7 +111,7 @@ typedef enum { + (nullable instancetype) messageWithType: (KCJoiningMessageType) type data: (NSData*) firstData - payload: (NSData*) secondData + payload: (nullable NSData*) secondData error: (NSError**) error; diff --git a/KeychainCircle/KCJoiningMessages.m b/KeychainCircle/KCJoiningMessages.m index 2eb0c94b..2fff03ee 100644 --- a/KeychainCircle/KCJoiningMessages.m +++ b/KeychainCircle/KCJoiningMessages.m @@ -32,14 +32,14 @@ + (nullable instancetype) messageWithType: (KCJoiningMessageType) type data: (NSData*) firstData - secondData: (NSData*) secondData + secondData: (nullable NSData*) secondData error: (NSError**) error { return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:secondData error:error]; } + (nullable instancetype) messageWithType: (KCJoiningMessageType) type data: (NSData*) firstData - payload: (NSData*) secondData + payload: (nullable NSData*) secondData error: (NSError**) error { return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:secondData error:error]; @@ -140,10 +140,9 @@ - (nullable instancetype) initWithDER: (NSData*) message error: (NSError**) error { - self = [super init]; - - self->_der = [NSData dataWithData: message]; - + if ((self = [super init])) { + self->_der = [NSData dataWithData: message]; + } return [self inflatePartsOfEncoding: error] ? self : nil; } @@ -151,14 +150,13 @@ data: (NSData*) firstData payload: (nullable NSData*) secondData error: (NSError**) error { - self = [super init]; - - self->_der = [KCJoiningMessage encodeToDERType:type - data:firstData - payload:secondData - error:error]; - if (self->_der == nil) return nil; - + if ((self = [super init])) { + self->_der = [KCJoiningMessage encodeToDERType:type + data:firstData + payload:secondData + error:error]; + if (self->_der == nil) return nil; + } return [self inflatePartsOfEncoding: error] ? self : nil; } diff --git a/KeychainCircle/KCJoiningRequestCircleSession.m b/KeychainCircle/KCJoiningRequestCircleSession.m index a8778b29..e0fffb47 100644 --- a/KeychainCircle/KCJoiningRequestCircleSession.m +++ b/KeychainCircle/KCJoiningRequestCircleSession.m @@ -26,6 +26,9 @@ #import "keychain/ot/proto/generated_source/OTApplicantToSponsorRound2M1.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.h" +#import "keychain/ot/proto/generated_source/OTGlobalEnums.h" +#import "keychain/ot/proto/generated_source/OTSupportSOSMessage.h" +#import "keychain/ot/proto/generated_source/OTSupportOctagonMessage.h" #import "keychain/ot/proto/generated_source/OTPairingMessage.h" #endif #import @@ -102,6 +105,7 @@ typedef enum { return [self->_session encrypt:initialMessage.data error:error]; } + - (nullable NSData*) initialMessage: (NSError**) error { secnotice("joining", "joining: KCJoiningRequestCircleSession initialMessage called"); @@ -129,6 +133,8 @@ typedef enum { localError = err; } else{ OTPairingMessage *pairingMessage = [[OTPairingMessage alloc]init]; + pairingMessage.supportsSOS = [[OTSupportSOSMessage alloc] init]; + pairingMessage.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; OTApplicantToSponsorRound2M1 *prepareMessage = [[OTApplicantToSponsorRound2M1 alloc]init]; prepareMessage.peerID = peerID; prepareMessage.permanentInfo = permanentInfo; @@ -137,6 +143,10 @@ typedef enum { prepareMessage.stableInfoSig = stableInfoSig; pairingMessage.prepare = prepareMessage; + + pairingMessage.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + pairingMessage.supportsOctagon.supported = OTSupportType_supported; + next = pairingMessage.data; } dispatch_semaphore_signal(sema); @@ -162,7 +172,7 @@ typedef enum { self->_state = kExpectingCircleBlob; NSData *encryptedInitialMessage = [self encryptedInitialMessage:next error:error]; - return [[KCJoiningMessage messageWithType: kPeerInfo + return [[KCJoiningMessage messageWithType:kPeerInfo data:encryptedInitialMessage payload:encryptedPi error:error] der]; @@ -180,13 +190,34 @@ typedef enum { } -- (void) attemptSosUpgrade +- (void) waitForOctagonUpgrade { - [self.otControl attemptSosUpgrade:self.joiningConfiguration.containerName context:self.joiningConfiguration.contextID reply:^(NSError *error) { +#if OCTAGON + [self.otControl waitForOctagonUpgrade:self.joiningConfiguration.containerName context:self.joiningConfiguration.contextID reply:^(NSError *error) { if(error){ secerror("pairing: failed to upgrade initiator into Octagon: %@", error); } }]; +#endif +} + +- (BOOL)shouldJoinSOS:(KCJoiningMessage*)message pairingMessage:(OTPairingMessage*)pairingMessage +{ + + BOOL shouldJoin = YES; + + if (OctagonPlatformSupportsSOS() == NO) { + secnotice("joining", "platform does not support SOS"); + shouldJoin = NO; + } else if (message.secondData == nil) { + secnotice("joining", "message does not contain SOS data"); + shouldJoin = NO; + } else if (pairingMessage.hasSupportsSOS && pairingMessage.supportsSOS.supported == OTSupportType_not_supported) { + secnotice("joining", "acceptor explicitly does not support SOS"); + shouldJoin = NO; + } + + return shouldJoin; } - (NSData*) handleCircleBlob: (KCJoiningMessage*) message error: (NSError**) error { @@ -206,6 +237,7 @@ typedef enum { secerror("octagon: expected voucher! returning from piggybacking."); return nil; } + OTSponsorToApplicantRound2M2 *voucher = pairingMessage.voucher; //handle voucher message then join octagon @@ -228,16 +260,18 @@ typedef enum { return nil; } - if (OctagonPlatformSupportsSOS()) { + if ([self shouldJoinSOS:message pairingMessage:pairingMessage]) { secnotice("joining", "doing SOS processCircleJoinData"); //note we are stuffing SOS into the payload "secondData" NSData* circleBlob = [self.session decryptAndVerify:message.secondData error:error]; - if (circleBlob == nil) return nil; - - if (![self.circleDelegate processCircleJoinData: circleBlob version:kPiggyV1 error:error]) + if (circleBlob == nil) { + secnotice("joining", "decryptAndVerify failed: %@", error && *error ? *error : nil); return nil; - } else { - secnotice("joining", "platform doesn't support SOS"); + } + if (![self.circleDelegate processCircleJoinData: circleBlob version:kPiggyV1 error:error]){ + secerror("joining: processCircleJoinData failed %@", error && *error ? *error : nil); + return nil; + } } self->_state = kRequestCircleDone; @@ -257,10 +291,12 @@ typedef enum { return nil; } else { secnotice("joining", "joined the SOS circle!"); +#if OCTAGON if(OctagonIsEnabled()) { secnotice("joining", "kicking off SOS Upgrade into Octagon!"); - [self attemptSosUpgrade]; + [self waitForOctagonUpgrade]; } +#endif } self->_state = kRequestCircleDone; @@ -311,27 +347,26 @@ typedef enum { error:(NSError**) error { secnotice("joining", "joining: KCJoiningRequestCircleSession initWithCircleDelegate called, uuid=%@", session.pairingUUID); - self = [super init]; - - self->_circleDelegate = circleDelegate; - self->_session = session; - self.state = kExpectingCircleBlob; + if ((self = [super init])) { + self->_circleDelegate = circleDelegate; + self->_session = session; + self.state = kExpectingCircleBlob; #if OCTAGON - self->_otControl = otcontrol; - self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:@"OctagonPiggybacking" - uniqueDeviceID:@"requester-id" - uniqueClientID:@"requester-id" - pairingUUID:session.pairingUUID - containerName:nil - contextID:OTDefaultContext - epoch:session.epoch - isInitiator:true]; - - self->_piggy_version = session.piggybackingVersion; + self->_otControl = otcontrol; + self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:@"OctagonPiggybacking" + uniqueDeviceID:@"requester-id" + uniqueClientID:@"requester-id" + pairingUUID:session.pairingUUID + containerName:nil + contextID:OTDefaultContext + epoch:session.epoch + isInitiator:true]; + + self->_piggy_version = session.piggybackingVersion; #else - self->_piggy_version = kPiggyV1; + self->_piggy_version = kPiggyV1; #endif - + } return self; } diff --git a/KeychainCircle/KCJoiningRequestSecretSession.m b/KeychainCircle/KCJoiningRequestSecretSession.m index 81b9aac8..db52d630 100644 --- a/KeychainCircle/KCJoiningRequestSecretSession.m +++ b/KeychainCircle/KCJoiningRequestSecretSession.m @@ -18,7 +18,6 @@ #include #include #include -#include #import #include @@ -33,6 +32,9 @@ #import "keychain/ot/proto/generated_source/OTApplicantToSponsorRound2M1.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.h" +#import "keychain/ot/proto/generated_source/OTGlobalEnums.h" +#import "keychain/ot/proto/generated_source/OTSupportSOSMessage.h" +#import "keychain/ot/proto/generated_source/OTSupportOctagonMessage.h" #import "keychain/ot/proto/generated_source/OTPairingMessage.h" #endif #import @@ -70,9 +72,9 @@ bool KCJoiningOctagonPiggybackingEnabled() { @property (readwrite) uint64_t epoch; @property (readwrite) NSData* challenge; @property (readwrite) NSData* salt; -#if OCTAGON @property (readwrite) NSString* sessionUUID; +#if OCTAGON @property (nonatomic, strong) OTControl *otControl; #endif @property (nonatomic, strong) NSMutableDictionary *defaults; @@ -212,15 +214,15 @@ bool KCJoiningOctagonPiggybackingEnabled() { } #if OCTAGON //handle octagon data if it exists - if(KCJoiningOctagonPiggybackingEnabled()){ + if (KCJoiningOctagonPiggybackingEnabled()){ self.piggy_version = [message secondData] ? kPiggyV2 : kPiggyV1; // The session may or may not exist at this point. If it doesn't, the version will be set at object creation time. self.session.piggybackingVersion = self.piggy_version; - if(self.piggy_version == kPiggyV2){ + if (self.piggy_version == kPiggyV2){ OTPairingMessage* pairingMessage = [[OTPairingMessage alloc]initWithData: [message secondData]]; - if(pairingMessage.hasEpoch) { + if (pairingMessage.hasEpoch) { secnotice("octagon", "received epoch message: %@", [pairingMessage.epoch dictionaryRepresentation]); self.epoch = pairingMessage.epoch.epoch; } @@ -340,31 +342,30 @@ bool KCJoiningOctagonPiggybackingEnabled() { rng: (struct ccrng_state *)rng error: (NSError**)error { secnotice("joining", "joining: initWithSecretDelegate called"); - self = [super init]; - - self->_secretDelegate = secretDelegate; - self->_state = kExpectingB; - self->_dsid = dsid; - self->_defaults = [NSMutableDictionary dictionary]; + if ((self = [super init])) { + self->_secretDelegate = secretDelegate; + self->_state = kExpectingB; + self->_dsid = dsid; + self->_defaults = [NSMutableDictionary dictionary]; #if OCTAGON - self->_piggy_version = KCJoiningOctagonPiggybackingEnabled() ? kPiggyV2 : kPiggyV1; - self->_otControl = [OTControl controlObject:true error:error]; + self->_piggy_version = KCJoiningOctagonPiggybackingEnabled() ? kPiggyV2 : kPiggyV1; + self->_otControl = [OTControl controlObject:true error:error]; - _sessionUUID = [[NSUUID UUID] UUIDString]; + _sessionUUID = [[NSUUID UUID] UUIDString]; #else - self->_piggy_version = kPiggyV1; + self->_piggy_version = kPiggyV1; #endif - secnotice("joining", "joining: initWithSecretDelegate called, uuid=%@", self.sessionUUID); + secnotice("joining", "joining: initWithSecretDelegate called, uuid=%@", self.sessionUUID); - NSString* name = [NSString stringWithFormat: @"%llu", dsid]; + NSString* name = [NSString stringWithFormat: @"%llu", dsid]; - self->_context = [[KCSRPClientContext alloc] initWithUser: name - digestInfo: ccsha256_di() - group: ccsrp_gp_rfc5054_3072() - randomSource: rng]; - + self->_context = [[KCSRPClientContext alloc] initWithUser: name + digestInfo: ccsha256_di() + group: ccsrp_gp_rfc5054_3072() + randomSource: rng]; + } return self; } diff --git a/KeychainCircle/KCSRPContext.m b/KeychainCircle/KCSRPContext.m index 3d9d8a8e..15bdf412 100644 --- a/KeychainCircle/KCSRPContext.m +++ b/KeychainCircle/KCSRPContext.m @@ -50,14 +50,13 @@ static const NSStringEncoding srpStringEncoding = NSUTF8StringEncoding; group: (ccsrp_const_gp_t) gp randomSource: (struct ccrng_state *) rng { - self = [super init]; - - self.context = malloc(ccsrp_sizeof_srp(di, gp)); - ccsrp_ctx_init(self.context, di, gp); - - self.user = user; - self.rng = rng; + if ((self = [super init])) { + self.context = malloc(ccsrp_sizeof_srp(di, gp)); + ccsrp_ctx_init(self.context, di, gp); + self.user = user; + self.rng = rng; + } return self; } @@ -179,15 +178,14 @@ static bool ExactDataSizeRequirement(NSData* data, NSUInteger expectedLength, NS digestInfo: (const struct ccdigest_info *) di group: (ccsrp_const_gp_t) gp randomSource: (struct ccrng_state *) rng { - self = [super initWithUser: user - digestInfo: di - group: gp - randomSource: rng]; - - if (![self resetWithPassword:password error:nil]) { - return nil; + if ((self = [super initWithUser: user + digestInfo: di + group: gp + randomSource: rng])) { + if (![self resetWithPassword:password error:nil]) { + return nil; + } } - return self; } @@ -197,14 +195,13 @@ static bool ExactDataSizeRequirement(NSData* data, NSUInteger expectedLength, NS digestInfo: (const struct ccdigest_info *) di group: (ccsrp_const_gp_t) gp randomSource: (struct ccrng_state *) rng { - self = [super initWithUser: user - digestInfo: di - group: gp - randomSource: rng]; - - self.verifier = verifier; - self->_salt = salt; - + if ((self = [super initWithUser: user + digestInfo: di + group: gp + randomSource: rng])) { + self.verifier = verifier; + self->_salt = salt; + } return self; } diff --git a/KeychainCircle/PairingChannel.m b/KeychainCircle/PairingChannel.m index 3627feae..60b5cf5e 100644 --- a/KeychainCircle/PairingChannel.m +++ b/KeychainCircle/PairingChannel.m @@ -11,16 +11,19 @@ #import #import #import +#import "utilities/SecCoreAnalytics.h" #import #import "keychain/ot/OTManager.h" #import "keychain/ot/OctagonControlServer.h" #import "keychain/ot/OTControl.h" #import "keychain/ot/OctagonControlServer.h" #import "keychain/ot/OTJoiningConfiguration.h" -#import "keychain/ot/proto/generated_source/OTPairingMessage.h" #import "keychain/ot/proto/generated_source/OTApplicantToSponsorRound2M1.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h" #import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.h" +#import "keychain/ot/proto/generated_source/OTGlobalEnums.h" +#import "keychain/ot/proto/generated_source/OTSupportSOSMessage.h" +#import "keychain/ot/proto/generated_source/OTSupportOctagonMessage.h" #import "keychain/ot/proto/generated_source/OTPairingMessage.h" #include @@ -29,7 +32,6 @@ #import #endif -#import "utilities/SecADWrapper.h" KCPairingIntent_Type KCPairingIntent_Type_None = @"none"; KCPairingIntent_Type KCPairingIntent_Type_SilentRepair = @"repair"; @@ -78,8 +80,7 @@ typedef void(^OTNextState)(NSData *inData, OTPairingInternalCompletion complete) - (nullable instancetype)initWithCoder:(NSCoder *)decoder { - self = [super init]; - if (self) { + if ((self = [super init])) { _model = [decoder decodeObjectOfClass:[NSString class] forKey:@"model"]; _modelVersion = [decoder decodeObjectOfClass:[NSString class] forKey:@"modelVersion"]; _modelClass = [decoder decodeObjectOfClass:[NSString class] forKey:@"modelClass"]; @@ -256,9 +257,9 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; //MARK: - Initiator -- (void) attemptSosUpgrade +- (void) waitForOctagonUpgrade { - [self.otControl attemptSosUpgrade:nil context:self.contextID reply:^(NSError *error) { + [self.otControl waitForOctagonUpgrade:nil context:self.contextID reply:^(NSError *error) { if(error){ secerror("pairing: failed to upgrade initiator into Octagon: %@", error); } @@ -407,12 +408,17 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; return; } else { OTPairingMessage *octagonMessage = [[OTPairingMessage alloc]init]; + octagonMessage.supportsSOS = [[OTSupportSOSMessage alloc] init]; + octagonMessage.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; OTApplicantToSponsorRound2M1 *prepare = [[OTApplicantToSponsorRound2M1 alloc] init]; prepare.peerID = peerID; prepare.permanentInfo = permanentInfo; prepare.permanentInfoSig = permanentInfoSig; prepare.stableInfo = stableInfo; prepare.stableInfoSig = stableInfoSig; + + octagonMessage.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + octagonMessage.supportsOctagon.supported = OTSupportType_supported; octagonMessage.prepare = prepare; if(application){ secnotice(pairingScope, "initiatorCompleteSecondPacketOctagon returning octagon and sos data"); @@ -465,7 +471,7 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; } else { //kick off SOS ugprade if(OctagonIsEnabled() && !self.sessionSupportsOctagon) { - [self attemptSosUpgrade]; + [self waitForOctagonUpgrade]; } typeof(self) strongSelf = weakSelf; secnotice("pairing", "initiator circle join complete, more data: %s: %@", @@ -656,10 +662,13 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; [weakSelf acceptorSecondPacket:nsdata complete:kscomplete]; }; OTPairingMessage *response = [[OTPairingMessage alloc] init]; + response.supportsSOS = [[OTSupportSOSMessage alloc] init]; + response.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; response.epoch = [[OTSponsorToApplicantRound1M2 alloc] init]; response.epoch.epoch = epoch; + response.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + response.supportsOctagon.supported = OTSupportType_supported; reply[@"o"] = response.data; - secnotice("pairing", "acceptor reply to packet 1"); complete(false, reply, error); } @@ -755,9 +764,13 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; finished = false; } OTPairingMessage *response = [[OTPairingMessage alloc] init]; + response.supportsSOS = [[OTSupportSOSMessage alloc] init]; + response.supportsOctagon = [[OTSupportOctagonMessage alloc] init]; response.voucher = [[OTSponsorToApplicantRound2M2 alloc] init]; response.voucher.voucher = voucher; response.voucher.voucherSignature = voucherSig; + response.supportsSOS.supported = OctagonPlatformSupportsSOS() ? OTSupportType_supported : OTSupportType_not_supported; + response.supportsOctagon.supported = OTSupportType_supported; if (self.acceptorWillSendInitialSyncCredentials) { // no need to share TLKs over the pairing channel, that's provided by octagon @@ -866,7 +879,7 @@ const compression_algorithm pairingCompression = COMPRESSION_LZFSE; if (compressedData) { NSString *key = [NSString stringWithFormat:@"com.apple.ckks.pairing.packet-size.%s.%u", self->_initiator ? "initiator" : "acceptor", self->_counter]; - SecADClientPushValueForDistributionKey((__bridge CFStringRef)key, [compressedData length]); + [SecCoreAnalytics sendEvent:key event:@{SecCoreAnalyticsValue: [NSNumber numberWithUnsignedInteger:[compressedData length]]}]; secnotice("pairing", "pairing packet size %lu", (unsigned long)[compressedData length]); } } diff --git a/KeychainCircle/Tests/FakeSOSControl.m b/KeychainCircle/Tests/FakeSOSControl.m index eafb80c6..9feadd4d 100644 --- a/KeychainCircle/Tests/FakeSOSControl.m +++ b/KeychainCircle/Tests/FakeSOSControl.m @@ -4,8 +4,7 @@ @implementation FakeNSXPCConnection - (instancetype) initWithControl:(id)control { - self = [super init]; - if (self) { + if ((self = [super init])) { _control = control; } return self; @@ -156,7 +155,7 @@ complete(true, nil); } -- (void)triggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete +- (void)rpcTriggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete { complete(true, NULL); } @@ -345,7 +344,19 @@ complete(nil, nil); } -- (void)triggerBackup:(NSArray *)backupPeers complete:(void (^)(NSError *))complete { +- (void)iCloudIdentityStatus_internal: (void(^)(NSDictionary *tableSpid, NSError *error))complete { + complete(nil, nil); +} + +- (void) iCloudIdentityStatus: (void(^)(NSData *json, NSError *error))complete { + complete(nil, nil); +} + +- (void)rpcTriggerBackup:(NSArray *)backupPeers complete:(void (^)(NSError *))complete { + complete(nil); +} + +- (void)rpcTriggerRingUpdate:(void (^)(NSError *))complete { complete(nil); } diff --git a/KeychainCircle/Tests/KCJoiningSessionTest.m b/KeychainCircle/Tests/KCJoiningSessionTest.m index 2cd57264..f34ee649 100644 --- a/KeychainCircle/Tests/KCJoiningSessionTest.m +++ b/KeychainCircle/Tests/KCJoiningSessionTest.m @@ -17,8 +17,6 @@ #include "keychain/SecureObjectSync/SOSFullPeerInfo.h" #include "keychain/SecureObjectSync/SOSPeerInfoInternal.h" -#include - static SecKeyRef GenerateFullECKey_internal(int keySize, NSError** error) { @@ -88,25 +86,26 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { - (id) initWithSecret: (NSString*) secret incorrectSecret: (NSString*) incorrectSecret incorrectTries: (int) retries { - self = [super init]; + if ((self = [super init])) { - SecKeyRef signingKey = GenerateFullECKey(256, NULL); - SecKeyRef octagonSigningKey = GenerateFullECKey(384, NULL); - SecKeyRef octagonEncryptionKey = GenerateFullECKey(384, NULL); + SecKeyRef signingKey = GenerateFullECKey(256, NULL); + SecKeyRef octagonSigningKey = GenerateFullECKey(384, NULL); + SecKeyRef octagonEncryptionKey = GenerateFullECKey(384, NULL); - SOSPeerInfoRef newPeerInfo = SOSPeerInfoCreate(NULL, (__bridge CFDictionaryRef) @{(__bridge NSString*)kPIUserDefinedDeviceNameKey:@"Fakey"}, NULL, signingKey, octagonSigningKey, octagonEncryptionKey, NULL); + SOSPeerInfoRef newPeerInfo = SOSPeerInfoCreate(NULL, (__bridge CFDictionaryRef) @{(__bridge NSString*)kPIUserDefinedDeviceNameKey:@"Fakey"}, NULL, signingKey, octagonSigningKey, octagonEncryptionKey, NULL); - if (newPeerInfo == NULL) { - return nil; - } - self.peerInfo = newPeerInfo; - CFRelease(newPeerInfo); - newPeerInfo = NULL; + if (newPeerInfo == NULL) { + return nil; + } + self.peerInfo = newPeerInfo; + CFRelease(newPeerInfo); + newPeerInfo = NULL; - self.sharedSecret = secret; - self.incorrectSecret = incorrectSecret; - self.incorrectTries = retries; + self.sharedSecret = secret; + self.incorrectSecret = incorrectSecret; + self.incorrectTries = retries; + } return self; } @@ -188,18 +187,17 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { } - (id) initWithSecrets: (NSArray*) secrets retries: (int) retries code: (NSString*) code { - self = [super init]; + if ((self = [super init])) { + self->_secrets = secrets; + self.currentSecret = 0; + self->_retriesPerSecret = retries; + self->_retriesLeft = self.retriesPerSecret; - self->_secrets = secrets; - self.currentSecret = 0; - self->_retriesPerSecret = retries; - self->_retriesLeft = self.retriesPerSecret; - - self->_codeToUse = code; - - uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; - self->_circleJoinData = [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ]; + self->_codeToUse = code; + uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + self->_circleJoinData = [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ]; + } return self; } @@ -270,7 +268,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret]; KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; NSData* initialMessage = [requestSession initialMessage: &error]; @@ -282,7 +280,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate circleDelegate:acceptDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; error = nil; @@ -365,7 +363,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret incorrectSecret:@"777888" incorrectTries:3]; KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; NSData* initialMessage = [requestSession initialMessage: &error]; @@ -377,7 +375,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate circleDelegate:acceptDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; error = nil; @@ -471,7 +469,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret]; KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; NSData* initialMessage = [requestSession initialMessage: &error]; @@ -483,7 +481,7 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate circleDelegate:acceptDelegate dsid:dsid - rng:ccDRBGGetRngState() + rng:ccrng(NULL) error:&error]; error = nil; diff --git a/KeychainCircle/Tests/KCParing.plist b/KeychainCircle/Tests/KCParing.plist index 137bf077..112ebe33 100644 --- a/KeychainCircle/Tests/KCParing.plist +++ b/KeychainCircle/Tests/KCParing.plist @@ -24,7 +24,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testSecPairBasicTest KCPairing.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testSecPairBasicTest + KCPairing.xctest diff --git a/KeychainCircle/Tests/KCSRPTests.m b/KeychainCircle/Tests/KCSRPTests.m index e518a261..6a516cd4 100644 --- a/KeychainCircle/Tests/KCSRPTests.m +++ b/KeychainCircle/Tests/KCSRPTests.m @@ -10,7 +10,6 @@ #include #include #include -#include @interface KCSRPTests : XCTestCase @@ -102,7 +101,7 @@ [self negotiateWithUser: @"TestUser" digestInfo: ccsha256_di() group: ccsrp_gp_rfc5054_3072() - randomSource: ccDRBGGetRngState()]; + randomSource: ccrng(NULL)]; } @end diff --git a/KeychainCircle/Tests/KCTLKRequestTest.m b/KeychainCircle/Tests/KCTLKRequestTest.m index 325f198c..8ab9c015 100644 --- a/KeychainCircle/Tests/KCTLKRequestTest.m +++ b/KeychainCircle/Tests/KCTLKRequestTest.m @@ -15,24 +15,6 @@ #include - -static SecKeyRef GenerateFullECKey_internal(int keySize, NSError** error) -{ - SecKeyRef full_key = NULL; - - NSDictionary* keygen_parameters = @{ (__bridge NSString*)kSecAttrKeyType:(__bridge NSString*) kSecAttrKeyTypeEC, - (__bridge NSString*)kSecAttrKeySizeInBits: [NSNumber numberWithInt: keySize] }; - - - (void) OSStatusError(SecKeyGeneratePair((__bridge CFDictionaryRef)keygen_parameters, NULL, &full_key), error, @"Generate Key failed"); - - return full_key; -} - -static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { - return GenerateFullECKey_internal(keySize, error); -} - static NSData* createTlkRequestMessage (KCAESGCMDuplexSession* aesSession) { char someData[] = {1,2,3,4,5,6}; NSError* error = NULL; @@ -165,18 +147,17 @@ static NSData* createTlkRequestMessage (KCAESGCMDuplexSession* aesSession) { } - (id) initWithSecrets: (NSArray*) secrets retries: (int) retries code: (NSString*) code { - self = [super init]; - - self->_secrets = secrets; - self.currentSecret = 0; - self->_retriesPerSecret = retries; - self->_retriesLeft = self.retriesPerSecret; + if ((self = [super init])) { + self->_secrets = secrets; + self.currentSecret = 0; + self->_retriesPerSecret = retries; + self->_retriesLeft = self.retriesPerSecret; - self->_codeToUse = code; - - uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; - self->_circleJoinData = [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ]; + self->_codeToUse = code; + uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + self->_circleJoinData = [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ]; + } return self; } diff --git a/KeychainCircle/Tests/KeychainCircle.plist b/KeychainCircle/Tests/KeychainCircle.plist index daf13f84..d34989d6 100644 --- a/KeychainCircle/Tests/KeychainCircle.plist +++ b/KeychainCircle/Tests/KeychainCircle.plist @@ -24,7 +24,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest KCDerTest KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + KCDerTest + KeychainCircleTests.xctest @@ -38,7 +45,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testAESGCMDuplex KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testAESGCMDuplex + KeychainCircleTests.xctest @@ -52,7 +66,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testAESGCMDuplexCoding KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testAESGCMDuplexCoding + KeychainCircleTests.xctest @@ -66,7 +87,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSession KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testJoiningSession + KeychainCircleTests.xctest @@ -80,7 +108,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSessionRetry KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testJoiningSessionRetry + KeychainCircleTests.xctest @@ -94,7 +129,14 @@ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSessionCodeChange KeychainCircleTests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + testJoiningSessionCodeChange + KeychainCircleTests.xctest diff --git a/KeychainEntitledTestApp_ios/AppDelegate.h b/KeychainEntitledTestApp_ios/AppDelegate.h deleted file mode 100644 index 998155c0..00000000 --- a/KeychainEntitledTestApp_ios/AppDelegate.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// AppDelegate.h -// KeychainEntitledTestApp_ios -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/KeychainEntitledTestApp_ios/AppDelegate.m b/KeychainEntitledTestApp_ios/AppDelegate.m deleted file mode 100644 index 7905ddac..00000000 --- a/KeychainEntitledTestApp_ios/AppDelegate.m +++ /dev/null @@ -1,51 +0,0 @@ -// -// AppDelegate.m -// KeychainEntitledTestApp_ios -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. -} - - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. -} - - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - - -@end diff --git a/KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json b/KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d8db8d65..00000000 --- a/KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - }, - { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/KeychainEntitledTestApp_ios/Info.plist b/KeychainEntitledTestApp_ios/Info.plist deleted file mode 100644 index d0524738..00000000 --- a/KeychainEntitledTestApp_ios/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/KeychainEntitledTestApp_ios/ViewController.h b/KeychainEntitledTestApp_ios/ViewController.h deleted file mode 100644 index 2300ca20..00000000 --- a/KeychainEntitledTestApp_ios/ViewController.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// ViewController.h -// KeychainEntitledTestApp_ios -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import - -@interface ViewController : UIViewController - - -@end - diff --git a/KeychainEntitledTestApp_ios/ViewController.m b/KeychainEntitledTestApp_ios/ViewController.m deleted file mode 100644 index 30c0bb6d..00000000 --- a/KeychainEntitledTestApp_ios/ViewController.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// ViewController.m -// KeychainEntitledTestApp_ios -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import "ViewController.h" - -@interface ViewController () - -@end - -@implementation ViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view, typically from a nib. -} - - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - - -@end diff --git a/KeychainEntitledTestApp_mac/AppDelegate.h b/KeychainEntitledTestApp_mac/AppDelegate.h deleted file mode 100644 index 5452eb93..00000000 --- a/KeychainEntitledTestApp_mac/AppDelegate.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// AppDelegate.h -// KeychainEntitledTestApp_mac -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import - -@interface AppDelegate : NSObject - - -@end - diff --git a/KeychainEntitledTestApp_mac/AppDelegate.m b/KeychainEntitledTestApp_mac/AppDelegate.m deleted file mode 100644 index e1e6dc39..00000000 --- a/KeychainEntitledTestApp_mac/AppDelegate.m +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.m -// KeychainEntitledTestApp_mac -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - // Insert code here to initialize your application -} - - -- (void)applicationWillTerminate:(NSNotification *)aNotification { - // Insert code here to tear down your application -} - - -@end diff --git a/KeychainEntitledTestApp_mac/ViewController.h b/KeychainEntitledTestApp_mac/ViewController.h deleted file mode 100644 index 3a40d4b2..00000000 --- a/KeychainEntitledTestApp_mac/ViewController.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// ViewController.h -// KeychainEntitledTestApp_mac -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import - -@interface ViewController : NSViewController - - -@end - diff --git a/KeychainEntitledTestApp_mac/main.m b/KeychainEntitledTestApp_mac/main.m deleted file mode 100644 index bc0cd59e..00000000 --- a/KeychainEntitledTestApp_mac/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// KeychainEntitledTestApp_mac -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - -#import - -int main(int argc, const char * argv[]) { - return NSApplicationMain(argc, argv); -} diff --git a/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m index 030606c4..cc31d676 100644 --- a/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m +++ b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m @@ -30,10 +30,12 @@ // was asked to file this radar for accounts: Invoke DataclassOwner when enabling or signing into an account - (void)account:(ACAccount *)account didChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount { - if((changeType == kACAccountChangeTypeAdded || changeType == kACAccountChangeTypeModified) && + if((changeType == kACAccountChangeTypeAdded || changeType == kACAccountChangeTypeModified || changeType == kACAccountChangeTypeWarmingUp) && [account.accountType.identifier isEqualToString: ACAccountTypeIdentifierAppleAccount] && [self accountIsPrimary:account]) { + SOSCCLoggedIntoAccount(NULL); + #if OCTAGON if(OctagonIsEnabled()){ NSString* altDSID = [account aa_altDSID]; diff --git a/Modules/OctagonTrust.modulemap b/Modules/OctagonTrust.modulemap new file mode 100644 index 00000000..be8cef68 --- /dev/null +++ b/Modules/OctagonTrust.modulemap @@ -0,0 +1,6 @@ +framework module OctagonTrust [system] { + umbrella header "OctagonTrust.h" + + export * + module * { export * } +} diff --git a/Modules/Security.iOS.modulemap b/Modules/Security.iOS.modulemap index 19cd51d0..7672ee88 100644 --- a/Modules/Security.iOS.modulemap +++ b/Modules/Security.iOS.modulemap @@ -1,4 +1,4 @@ -framework module Security [extern_c] { +framework module Security [extern_c][system] { umbrella header "Security.h" export * diff --git a/Modules/Security.macOS.modulemap b/Modules/Security.macOS.modulemap index e183b646..935d8655 100644 --- a/Modules/Security.macOS.modulemap +++ b/Modules/Security.macOS.modulemap @@ -1,4 +1,4 @@ -framework module Security [extern_c] { +framework module Security [extern_c][system] { umbrella header "Security.h" export * diff --git a/Modules/Security.macOS.private.modulemap b/Modules/Security.macOS.private.modulemap index 9645c117..83865039 100644 --- a/Modules/Security.macOS.private.modulemap +++ b/Modules/Security.macOS.private.modulemap @@ -1,4 +1,4 @@ -module Security.SecTask [extern_c] { +module Security.SecTask [extern_c][system] { header "SecTask.h" export * } diff --git a/OSX/Breadcrumb/README b/OSX/Breadcrumb/README deleted file mode 100644 index 894c607d..00000000 --- a/OSX/Breadcrumb/README +++ /dev/null @@ -1,99 +0,0 @@ -Breadcrumbs -=========== - -simple defintions: - - old password - new password - K = random 16 byte key - EK = Encrypted K - EKold = ECB(PBKDF2(password_old), K) - EKnew = ECB(PBKDF2(password_new), K) - Breadcrumb = AES-GCM(K, old password) - - -Breadcrumbs are to make life easier when using AppleID password as -local password by allowing upgrade of keychains from old password to new -password. - -When changing the password on one machine, the keychains for the user are -still encrypted (AES-GCM, key derived using PBKDF2) with the old password on -all machines. - -This happens for one machine when changing password on the AppleID.apple.com webpage. - -An EK is stored on the apple server. Each machine have its own EK stored on the web server. - -When user change the password on the AppleID.apple.com website, the -web server will unwrap the key K with the old password and then rewrap -it with the new password. - - unwrap(EKold, old password) -> K - wrap(K, new password) -> EKnew - -This means that if the user changes password more then ones, the computer can still upgrade the keychain to the current password since K will be the same until a new EK is uploaded the the computer. - -PKDF2 is used to avoid prebuilt lists of string2key tables attacks on -the breadcrumb + encryptedKey if the attacker possesses both. - -Breadcrumb contain current password that encrypts the keychain. The breadcrumb itself is encrypted with a machine-specific key K. - -The breadcrumb is stored on the local machine and never leaves the -local machine. - -When the computer have upgrade keychain to the current password and new K, EK, and breadcrumb is generated. - -Format -====== - -K = Random 16 byte -EK = ECB(PBKDF2(pw), key K) (16byte) | pbkdf-salt (20byte) | 4byte int network order of pbdf-iter -Breadcrumb = version (1) 1byte | AES-GCM-ENC(key K, password length (4byte, network order) | password | pad ) | tag - -The encrypted key (EK) is a PKDF2 salt + iteration count + random AES-128 key (K) -encrypted with ECB of the PKDF2(salt, iteration, password). - -There is no integrity on this encryption on purpose since that would make the -EK an verifier. - -The format of the EncryptedKey is - - ECB(PBKDF2(pw), key K) (16byte) | pbkdf-salt (20byte) | 4byte int network order of pbdf-iter - -The random key (K) is used to encrypt a breadcrumb that is stored -locally on the machine. The breadcrumb allows you to recover the old -password if you know the new password and have the encrypted key. - -The client machine encrypts the password with AES-GCM using key K. The data -is padded to 256 bytes to no tell password length. - -The format of the breadcrumb - - version (1) 1byte | AES-GCM-ENC(key K, password length (4byte, network order) | password | pad ) | tag - -tag is the 16 byte GCM tag -key is the key (K) from the EncryptedKey (EK) -assoc data i AES-GCM covers version byte - -Password length including up to pad is encrypted with AES-GCM - -Password is padded to paddingSize (256) to avoid exposing length of password. - -The PBKDF2 function is PBKDF2-HMAC-SHA256. - - -Updating the Encrypted Key (EK) on server -========================================= - -When a user update the password on the apple id server the server -updates the breadcrumb for each machine that the user have associsated -with the account. - -1. The server takes the old password generates a the key using PBKDF2 - using the salt and interation count. - -2. The server takes the new password generates a the key using PBKDF2 - using the same salt and interation count. - -3. Decrypts the first block with the key of old password and - re-encrypt with the key of new password. diff --git a/OSX/Breadcrumb/SecBreadcrumb.c b/OSX/Breadcrumb/SecBreadcrumb.c deleted file mode 100644 index 067c93c5..00000000 --- a/OSX/Breadcrumb/SecBreadcrumb.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (c) 2014 - 2016 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@ - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#import "SecCFAllocator.h" - -#define CFReleaseNull(CF) ({ __typeof__(CF) *const _pcf = &(CF), _cf = *_pcf; (_cf ? (*_pcf) = ((__typeof__(CF))0), (CFRelease(_cf), ((__typeof__(CF))0)) : _cf); }) - -#define kBCKeySize CCAES_KEY_SIZE_128 -#define kBCSaltSize 20 -#define kBCIterations 5000 -#define BCTagLen 16 -#define BCIVLen 16 -#define BCversion1 1 -#define BCversion2 2 -#define BCPaddingSize 256 -#define BCMaxSize 1024 - -Boolean -SecBreadcrumbCreateFromPassword(CFStringRef inPassword, - CFDataRef *outBreadcrumb, - CFDataRef *outEncryptedKey, - CFErrorRef *outError) -{ - const struct ccmode_ecb *ecb = ccaes_ecb_encrypt_mode(); - const struct ccmode_gcm *gcm = ccaes_gcm_encrypt_mode(); - uint8_t iv[BCIVLen]; - CFMutableDataRef key, npw; - CFDataRef pw; - - *outBreadcrumb = NULL; - *outEncryptedKey = NULL; - if (outError) - *outError = NULL; - - key = CFDataCreateMutable(SecCFAllocatorZeroize(), 0); - if (key == NULL) - return false; - - CFDataSetLength(key, kBCKeySize + kBCSaltSize + 4); - if (SecRandomCopyBytes(kSecRandomDefault, CFDataGetLength(key) - 4, CFDataGetMutableBytePtr(key)) != 0) { - CFReleaseNull(key); - return false; - } - if (SecRandomCopyBytes(kSecRandomDefault, BCIVLen, iv) != 0) { - CFReleaseNull(key); - return false; - } - - uint32_t size = htonl(kBCIterations); - memcpy(CFDataGetMutableBytePtr(key) + kBCKeySize + kBCSaltSize, &size, sizeof(size)); - - /* - * Create data for password - */ - - pw = CFStringCreateExternalRepresentation(SecCFAllocatorZeroize(), inPassword, kCFStringEncodingUTF8, 0); - if (pw == NULL) { - CFReleaseNull(key); - return false; - } - - const CFIndex passwordLength = CFDataGetLength(pw); - - if (passwordLength > BCMaxSize) { - CFReleaseNull(pw); - CFReleaseNull(key); - return false; - } - - CFIndex paddedSize = passwordLength + BCPaddingSize - (passwordLength % BCPaddingSize); - const CFIndex outLength = 1 + BCIVLen + 4 + paddedSize + BCTagLen; - - npw = CFDataCreateMutable(NULL, outLength); - if (npw == NULL) { - CFReleaseNull(pw); - CFReleaseNull(key); - return false; - } - CFDataSetLength(npw, outLength); - - cc_clear(outLength, CFDataGetMutableBytePtr(npw)); - CFDataGetMutableBytePtr(npw)[0] = BCversion2; - memcpy(CFDataGetMutableBytePtr(npw) + 1, iv, BCIVLen); - size = htonl(passwordLength); - memcpy(CFDataGetMutableBytePtr(npw) + 1 + BCIVLen, &size, sizeof(size)); - memcpy(CFDataGetMutableBytePtr(npw) + 1 + BCIVLen + 4, CFDataGetBytePtr(pw), passwordLength); - - /* - * Now create a GCM encrypted password using the random key - */ - - ccgcm_ctx_decl(gcm->size, ctx); - ccgcm_init(gcm, ctx, kBCKeySize, CFDataGetMutableBytePtr(key)); - ccgcm_set_iv(gcm, ctx, BCIVLen, iv); - ccgcm_gmac(gcm, ctx, 1, CFDataGetMutableBytePtr(npw)); - ccgcm_update(gcm, ctx, outLength - BCTagLen - BCIVLen - 1, CFDataGetMutableBytePtr(npw) + 1 + BCIVLen, CFDataGetMutableBytePtr(npw) + 1 + BCIVLen); - ccgcm_finalize(gcm, ctx, BCTagLen, CFDataGetMutableBytePtr(npw) + outLength - BCTagLen); - ccgcm_ctx_clear(gcm->size, ctx); - - /* - * Wrapping key is PBKDF2(sha256) over password - */ - - const struct ccdigest_info *di = ccsha256_di(); - uint8_t rawkey[CCSHA256_OUTPUT_SIZE]; - _Static_assert(sizeof(rawkey) >= kBCKeySize, "keysize changed w/o updating digest"); - if (sizeof(rawkey) != di->output_size) abort(); - - if (ccpbkdf2_hmac(di, CFDataGetLength(pw), CFDataGetBytePtr(pw), - kBCSaltSize, CFDataGetMutableBytePtr(key) + kBCKeySize, - kBCIterations, - sizeof(rawkey), rawkey) != 0) - abort(); - - /* - * Wrap the random key with one round of ECB cryto - */ - - ccecb_ctx_decl(ccecb_context_size(ecb), ecbkey); - ccecb_init(ecb, ecbkey, kBCKeySize, rawkey); - ccecb_update(ecb, ecbkey, 1, CFDataGetMutableBytePtr(key), CFDataGetMutableBytePtr(key)); - ccecb_ctx_clear(ccecb_context_size(ecb), ecbkey); - - /* - * - */ - - cc_clear(sizeof(rawkey), rawkey); - CFReleaseNull(pw); - - *outBreadcrumb = npw; - *outEncryptedKey = key; - - return true; -} - - -Boolean -SecBreadcrumbCopyPassword(CFStringRef inPassword, - CFDataRef inBreadcrumb, - CFDataRef inEncryptedKey, - CFStringRef *outPassword, - CFErrorRef *outError) -{ - const struct ccmode_ecb *ecb = ccaes_ecb_decrypt_mode(); - CFMutableDataRef gcmkey, oldpw; - CFIndex outLength; - CFDataRef pw; - uint32_t size; - - *outPassword = NULL; - if (outError) - *outError = NULL; - - if (CFDataGetLength(inEncryptedKey) < kBCKeySize + kBCSaltSize + 4) { - return false; - } - - if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion1) { - if (CFDataGetLength(inBreadcrumb) < 1 + 4 + BCPaddingSize + BCTagLen) - return false; - - outLength = CFDataGetLength(inBreadcrumb) - 1 - BCTagLen; - } else if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion2) { - if (CFDataGetLength(inBreadcrumb) < 1 + BCIVLen + 4 + BCPaddingSize + BCTagLen) - return false; - outLength = CFDataGetLength(inBreadcrumb) - 1 - BCIVLen - BCTagLen; - } else { - return false; - } - - gcmkey = CFDataCreateMutableCopy(SecCFAllocatorZeroize(), 0, inEncryptedKey); - if (gcmkey == NULL) { - return false; - } - - if ((outLength % 16) != 0 && outLength < 4) { - CFReleaseNull(gcmkey); - return false; - } - - oldpw = CFDataCreateMutable(SecCFAllocatorZeroize(), outLength); - if (oldpw == NULL) { - CFReleaseNull(gcmkey); - return false; - } - CFDataSetLength(oldpw, outLength); - - /* - * Create data for password - */ - - pw = CFStringCreateExternalRepresentation(SecCFAllocatorZeroize(), inPassword, kCFStringEncodingUTF8, 0); - if (pw == NULL) { - CFReleaseNull(oldpw); - CFReleaseNull(gcmkey); - return false; - } - - /* - * Wrapping key is HMAC(sha256) over password - */ - - const struct ccdigest_info *di = ccsha256_di(); - uint8_t rawkey[CCSHA256_OUTPUT_SIZE]; - _Static_assert(sizeof(rawkey) >= kBCKeySize, "keysize changed w/o updating digest"); - if (sizeof(rawkey) != di->output_size) abort(); - - memcpy(&size, CFDataGetMutableBytePtr(gcmkey) + kBCKeySize + kBCSaltSize, sizeof(size)); - size = ntohl(size); - - if (ccpbkdf2_hmac(di, CFDataGetLength(pw), CFDataGetBytePtr(pw), - kBCSaltSize, CFDataGetMutableBytePtr(gcmkey) + kBCKeySize, - size, - sizeof(rawkey), rawkey) != 0) - abort(); - - CFReleaseNull(pw); - - /* - * Unwrap the random key with one round of ECB cryto - */ - - ccecb_ctx_decl(ccecb_context_size(ecb), ecbkey); - ccecb_init(ecb, ecbkey, kBCKeySize, rawkey); - ccecb_update(ecb, ecbkey, 1, CFDataGetMutableBytePtr(gcmkey), CFDataGetMutableBytePtr(gcmkey)); - ccecb_ctx_clear(ccecb_context_size(ecb), ecbkey); - /* - * GCM unwrap - */ - - uint8_t tag[BCTagLen]; - - if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion1) { - memcpy(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, BCTagLen); - - ccgcm_one_shot_legacy(ccaes_gcm_decrypt_mode(), kBCKeySize, CFDataGetMutableBytePtr(gcmkey), 0, NULL, 1, CFDataGetBytePtr(inBreadcrumb), - outLength, CFDataGetBytePtr(inBreadcrumb) + 1, CFDataGetMutableBytePtr(oldpw), BCTagLen, tag); - if (memcmp(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, BCTagLen) != 0) { - CFReleaseNull(oldpw); - CFReleaseNull(gcmkey); - return false; - } - - } else { - const uint8_t *iv = CFDataGetBytePtr(inBreadcrumb) + 1; - int res; - memcpy(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + BCIVLen + outLength, BCTagLen); - - res = ccgcm_one_shot(ccaes_gcm_decrypt_mode(), kBCKeySize, CFDataGetMutableBytePtr(gcmkey), - BCIVLen, iv, - 1, CFDataGetBytePtr(inBreadcrumb), - outLength, CFDataGetBytePtr(inBreadcrumb) + 1 + BCIVLen, CFDataGetMutableBytePtr(oldpw), - BCTagLen, tag); - if (res) { - CFReleaseNull(gcmkey); - CFReleaseNull(oldpw); - CFReleaseNull(gcmkey); - return false; - } - } - - CFReleaseNull(gcmkey); - - - memcpy(&size, CFDataGetMutableBytePtr(oldpw), sizeof(size)); - size = ntohl(size); - if ((ssize_t) size > outLength - 4) { - CFReleaseNull(oldpw); - return false; - } - memmove(CFDataGetMutableBytePtr(oldpw), CFDataGetMutableBytePtr(oldpw) + 4, size); - CFDataSetLength(oldpw, size); - - *outPassword = CFStringCreateFromExternalRepresentation(SecCFAllocatorZeroize(), oldpw, kCFStringEncodingUTF8); - CFReleaseNull(oldpw); - - return true; -} - -CFDataRef -SecBreadcrumbCreateNewEncryptedKey(CFStringRef oldPassword, - CFStringRef newPassword, - CFDataRef encryptedKey, - CFErrorRef *outError) -{ - const struct ccmode_ecb *enc = ccaes_ecb_encrypt_mode(); - const struct ccmode_ecb *dec = ccaes_ecb_decrypt_mode(); - const struct ccdigest_info *di = ccsha256_di(); - uint8_t rawkey[CCSHA256_OUTPUT_SIZE]; - CFDataRef newpw = NULL, oldpw = NULL; - CFMutableDataRef newEncryptedKey; - - _Static_assert(sizeof(rawkey) >= kBCKeySize, "keysize changed w/o updating digest"); - if (sizeof(rawkey) != di->output_size) abort(); - - if (CFDataGetLength(encryptedKey) < kBCKeySize + kBCSaltSize + 4) { - return NULL; - } - - newEncryptedKey = CFDataCreateMutableCopy(SecCFAllocatorZeroize(), 0, encryptedKey); - if (newEncryptedKey == NULL) { - return NULL; - } - - oldpw = CFStringCreateExternalRepresentation(SecCFAllocatorZeroize(), oldPassword, kCFStringEncodingUTF8, 0); - if (oldpw == NULL) { - CFReleaseNull(newEncryptedKey); - return false; - } - - newpw = CFStringCreateExternalRepresentation(SecCFAllocatorZeroize(), newPassword, kCFStringEncodingUTF8, 0); - if (newpw == NULL) { - CFReleaseNull(newEncryptedKey); - CFReleaseNull(oldpw); - return false; - } - - /* - * Unwrap with new key - */ - - uint32_t iter; - - memcpy(&iter, CFDataGetMutableBytePtr(newEncryptedKey) + kBCKeySize + kBCSaltSize, sizeof(iter)); - iter = ntohl(iter); - - if (ccpbkdf2_hmac(di, CFDataGetLength(oldpw), CFDataGetBytePtr(oldpw), - kBCSaltSize, CFDataGetMutableBytePtr(newEncryptedKey) + kBCKeySize, - iter, - sizeof(rawkey), rawkey) != 0) - abort(); - - CFReleaseNull(oldpw); - - - ccecb_ctx_decl(dec->size, deckey); - ccecb_init(dec, deckey, kBCKeySize, rawkey); - ccecb_update(dec, deckey, 1, CFDataGetMutableBytePtr(newEncryptedKey), CFDataGetMutableBytePtr(newEncryptedKey)); - ccecb_ctx_clear(ccecb_context_size(dec), deckey); - - cc_clear(sizeof(rawkey), rawkey); - - /* - * Re-wrap with new key - */ - - if (ccpbkdf2_hmac(di, CFDataGetLength(newpw), CFDataGetBytePtr(newpw), - kBCSaltSize, CFDataGetMutableBytePtr(newEncryptedKey) + kBCKeySize, - iter, - sizeof(rawkey), rawkey) != 0) - abort(); - - CFReleaseNull(newpw); - - - ccecb_ctx_decl(enc->size, enckey); - ccecb_init(enc, enckey, kBCKeySize, rawkey); - ccecb_update(enc, enckey, 1, CFDataGetMutableBytePtr(newEncryptedKey), CFDataGetMutableBytePtr(newEncryptedKey)); - ccecb_ctx_clear(ccecb_context_size(enc), enckey); - - cc_clear(sizeof(rawkey), rawkey); - - return newEncryptedKey; -} diff --git a/OSX/Breadcrumb/SecBreadcrumb.h b/OSX/Breadcrumb/SecBreadcrumb.h deleted file mode 100644 index e7cc4088..00000000 --- a/OSX/Breadcrumb/SecBreadcrumb.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2014 - 2016 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@ - */ - -/*! - @function SecBreadcrumbCreateFromPassword - @abstract Encryptes the password using a random key and then returns - the encrypted password (breadcrumb) and the password encrypted random key. - - @param inPassword is the password to encrypt and use to encrypt the random key. - @param outBreadcrumb is the password encrypted using a random key. - @param outEncryptedKey is the random key encrypted using inPassword. - @param outError An optional pointer to a CFErrorRef. This value is set - if an error occurred. If not NULL, the caller is responsible for - releasing the CFErrorRef. - @result On return a Boolean indicating success or failure. - - @discussion This function generates the breadcrumb that will be used to - update the user's keychain password when their Apple ID Login password - is changed on appleid.apple.com. -*/ - -Boolean -SecBreadcrumbCreateFromPassword(CFStringRef inPassword, - CFDataRef *outBreadcrumb, - CFDataRef *outEncryptedKey, - CFErrorRef *outError); - - -/*! - @function SecBreadcrumbCopyPassword - @abstract Decryptes the encrypted key using the password and uses the key to - decrypt the breadcrumb and returns the password stored in the breadcrumb. - - @param inPassword is the password to decrypt the encrypted random key. - @param inBreadcrumb is the breadcrumb encrypted by the key. It contains - and encrypted version of the users old password. - @param inEncryptedKey is an encrypted version of the key used to encrypt the - breadcrumb. - @param outPassword is the cleartext password that was stored in the breadcrumb. - @param outError An optional pointer to a CFErrorRef. This value is set - if an error occurred. If not NULL, the caller is responsible for - releasing the CFErrorRef. - @result On return a Boolean indicating success or failure. - - @discussion This function uses the password to decrypt the encrypted key and then - uses that key to decrypt the breadcrumb. -*/ - -Boolean -SecBreadcrumbCopyPassword(CFStringRef inPassword, - CFDataRef inBreadcrumb, - CFDataRef inEncryptedKey, - CFStringRef *outPassword, - CFErrorRef *outError); - -/* - * Change password used to encrypt the key from old password to new password - */ - -CFDataRef -SecBreadcrumbCreateNewEncryptedKey(CFStringRef oldPassword, - CFStringRef newPassword, - CFDataRef encryptedKey, - CFErrorRef *outError); diff --git a/OSX/Breadcrumb/bc-10-knife-on-bread.m b/OSX/Breadcrumb/bc-10-knife-on-bread.m deleted file mode 100644 index a3f80db3..00000000 --- a/OSX/Breadcrumb/bc-10-knife-on-bread.m +++ /dev/null @@ -1,105 +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@ - */ - - -#include -#include -#include -#include - -#include "breadcrumb_regressions.h" - -static NSString *after1 = @"XAKyA0TbLKpDOBl+Ur1CQpjGDtn3wp8bYiM07iJSGVIhaaG4AAATiA=="; -static NSString *bc1 = @"AdSXILtQrtsD+eT/UjMxxu4QTjlIJjvFDhpMXfk2eZ1CCJVhCuAhNcoL4DsU85DgSBCAswzVcSEU+bLMt+DT1jJfjJKVBus1Hd5lCA+N4wVtC66w3GK/WDQdGvLZ+BL86GkeRM2/+wH4/t5qOtxIJPS5SYZhnM5EP8xFYg30MLqXZqpwZhqYBJmVPMqEbLuihYAcAJreiZm4NN09CxvD36mvU3NyQOdHzAiQ+ADMiVI84qjU0qFH1KaZEoMHn3AqjAdviHUTOaNQXNepidedBZhSl4QBeuT2CaCYHjCXny9BYT+hCEU1yXn3RYeWyjcmFKmIz8gRvWf3ckF3XaSVL7MwqfsWw1tdI9OPi7zhauqphRGELw=="; - -static NSString *after2 = @"l/y+EOCUEeQHudNLQd5SoCJ2s/+rfH/kdbxbwZ7YGGb/U2FMAAATiA=="; -static NSString *bc2 = @"AuuaJCuKmffY3XAqTYNygSFQ4QnlkSqTHGYUMaxDRA1lQhbxJh58zAOvcsahYH9lSb4+YoMR6G7hDmqlKae8h3jrn0vhT4FlIySFS3MUPvmGOuhUecb+Gi2AYwc9x1uz7f0FSRxxL+v04r2AkmH1Cv6cL7pvued7vxUjzX4VrexFj+uF7i/HSGStg2+D3L+CRs2+dKZZ9BqiKjavsX9XPkvJAD0r8rKHncOBrRxL7A3+ysBTZi2VCi/8QTDSGp6DmpXEJ4NTo/IrZ+trOXe0MuocLMg+Jf6V8jy5ZfaQoGTuM3fJiD6EFGT68QtLrjqU9KdtHhQdCmFVi60zbWqEBRNN7IyRNyPJX48NqFPZuAUW7BL0YbuhdUX2Oj7+hFz99vch1T0="; - -#define kTestCount 10 -int bc_10_password(int argc, char *const *argv) -{ - CFDataRef breadcrumb = NULL, encryptedKey = NULL; - CFStringRef oldPassword = NULL; - CFStringRef password = CFSTR("password"); - CFStringRef newpassword = CFSTR("newpassword"); - CFErrorRef error = NULL; - - plan_tests(kTestCount); - - ok(SecBreadcrumbCreateFromPassword(password, &breadcrumb, &encryptedKey, &error), "wrap failed"); - - ok(SecBreadcrumbCopyPassword(password, breadcrumb, encryptedKey, &oldPassword, NULL), "unwrap failed"); - - ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); - CFReleaseSafe(oldPassword); - - CFDataRef newEncryptedKey; - - printf("changing password from \"password\" to \"newpassword\"\n"); - - newEncryptedKey = SecBreadcrumbCreateNewEncryptedKey(password, - newpassword, - encryptedKey, - &error); - ok(newEncryptedKey, "no new encrypted key"); - - ok(SecBreadcrumbCopyPassword(newpassword, breadcrumb, newEncryptedKey, &oldPassword, NULL), "unwrap failed"); - - ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); - - CFReleaseSafe(breadcrumb); - CFReleaseSafe(oldPassword); - CFReleaseSafe(newEncryptedKey); - - /* - * Check KAT for IV less operation (version1) - */ - - breadcrumb = CFBridgingRetain([[NSData alloc] initWithBase64EncodedString:bc1 options:0]); - newEncryptedKey = CFBridgingRetain([[NSData alloc] initWithBase64EncodedString:after1 options:0]); - - ok(SecBreadcrumbCopyPassword(newpassword, breadcrumb, newEncryptedKey, &oldPassword, NULL), "unwrap failed"); - - ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); - - CFReleaseSafe(breadcrumb); - CFReleaseSafe(oldPassword); - CFReleaseSafe(newEncryptedKey); - - /* - * Check KAT for IV less operation (version2) - */ - - breadcrumb = CFBridgingRetain([[NSData alloc] initWithBase64EncodedString:bc2 options:0]); - newEncryptedKey = CFBridgingRetain([[NSData alloc] initWithBase64EncodedString:after2 options:0]); - - ok(SecBreadcrumbCopyPassword(newpassword, breadcrumb, newEncryptedKey, &oldPassword, NULL), "unwrap failed"); - - ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); - - CFReleaseSafe(breadcrumb); - CFReleaseSafe(oldPassword); - CFReleaseSafe(newEncryptedKey); - - return 0; -} diff --git a/OSX/Breadcrumb/breadcrumb_regressions.h b/OSX/Breadcrumb/breadcrumb_regressions.h deleted file mode 100644 index 29894bf2..00000000 --- a/OSX/Breadcrumb/breadcrumb_regressions.h +++ /dev/null @@ -1,7 +0,0 @@ -/* To add a test: - 1) add it here - 2) Add it as command line argument for SecurityTest.app in the Release and Debug schemes - */ -#include - -ONE_TEST(bc_10_password) diff --git a/OSX/Keychain Circle Notification/Keychain Circle Notification.8 b/OSX/Keychain Circle Notification/Keychain Circle Notification.8 index d4bdc363..686d1654 100644 --- a/OSX/Keychain Circle Notification/Keychain Circle Notification.8 +++ b/OSX/Keychain Circle Notification/Keychain Circle Notification.8 @@ -1,9 +1,9 @@ .Dd November 02, 2016 -.Dt Keychain Circle Notification 8 +.Dt Keychain\ Circle\ Notification 8 .Os .Sh NAME .Nm Keychain Circle Notification -.Nd part of iCloud Keychain syncing. +.Nd Part of iCloud Keychain syncing. .Sh DESCRIPTION .Nm -part of iCloud Keychain syncing. +Part of iCloud Keychain syncing. diff --git a/OSX/Keychain/KDCirclePeer.m b/OSX/Keychain/KDCirclePeer.m index 91f8864e..563467dc 100644 --- a/OSX/Keychain/KDCirclePeer.m +++ b/OSX/Keychain/KDCirclePeer.m @@ -38,16 +38,12 @@ -(id)initWithPeerObject:(id)peerObject { - self = [super init]; - if (!self) { - return self; - } - - self.peerObject = peerObject; - self.name = (__bridge NSString *)(SOSPeerInfoGetPeerName((__bridge SOSPeerInfoRef)peerObject)); - self.idString = (__bridge NSString *)(SOSPeerInfoGetPeerID((__bridge SOSPeerInfoRef)peerObject)); - - return self; + if ((self = [super init])) { + self.peerObject = peerObject; + self.name = (__bridge NSString *)(SOSPeerInfoGetPeerName((__bridge SOSPeerInfoRef)peerObject)); + self.idString = (__bridge NSString *)(SOSPeerInfoGetPeerID((__bridge SOSPeerInfoRef)peerObject)); + } + return self; } -(NSString*)description diff --git a/OSX/Keychain/KDSecCircle.m b/OSX/Keychain/KDSecCircle.m index 66e36e7c..114784bf 100644 --- a/OSX/Keychain/KDSecCircle.m +++ b/OSX/Keychain/KDSecCircle.m @@ -160,14 +160,15 @@ typedef void (^applicantBlock)(id applicant); -(id)init { - self = [super init]; - int token; + if ((self = [super init])) { + int token; - self->_queue_ = dispatch_queue_create([[NSString stringWithFormat:@"KDSecCircle@%p", self] UTF8String], NULL); - self->_callbacks = [NSMutableArray new]; - notify_register_dispatch(kSOSCCCircleChangedNotification, &token, self.queue_, ^(int token1){ - [self updateCheck]; - }); + self->_queue_ = dispatch_queue_create([[NSString stringWithFormat:@"KDSecCircle@%p", self] UTF8String], NULL); + self->_callbacks = [NSMutableArray new]; + notify_register_dispatch(kSOSCCCircleChangedNotification, &token, self.queue_, ^(int token1) { + [self updateCheck]; + }); + } return self; } diff --git a/OSX/Modules b/OSX/Modules deleted file mode 120000 index 287aeb42..00000000 --- a/OSX/Modules +++ /dev/null @@ -1 +0,0 @@ -./Modules \ No newline at end of file diff --git a/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist b/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist index c1dd8e6c..899819c1 100644 --- a/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist +++ b/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist @@ -44,5 +44,11 @@ 123456.test.group2 com.apple.bluetooth + com.apple.private.AuthorizationServices + + com.apple.trust-settings.admin + + com.apple.private.security.storage.Keychains + diff --git a/OSX/SecurityTestsOSX/testlist.h b/OSX/SecurityTestsOSX/testlist.h index 5c3ef633..6bee84a9 100644 --- a/OSX/SecurityTestsOSX/testlist.h +++ b/OSX/SecurityTestsOSX/testlist.h @@ -1,7 +1,6 @@ /* Don't prevent multiple inclusion of this file. */ #include #include -#include #include #include #include diff --git a/OSX/authd/PreloginUserDb.h b/OSX/authd/PreloginUserDb.h new file mode 100644 index 00000000..f2a707f4 --- /dev/null +++ b/OSX/authd/PreloginUserDb.h @@ -0,0 +1,6 @@ +// +// PreloginUserDb.h +// authd +// + +OSStatus preloginudb_copy_userdb(const char * _Nullable uuid, UInt32 flags, CFArrayRef _Nonnull * _Nonnull output); diff --git a/OSX/authd/PreloginUserDb.m b/OSX/authd/PreloginUserDb.m new file mode 100644 index 00000000..dff49829 --- /dev/null +++ b/OSX/authd/PreloginUserDb.m @@ -0,0 +1,548 @@ +// +// PreloginUserDb.m +// authd +// +// Copyright © 2019 Apple. All rights reserved. +// + +#import +#import +#import +#import +#import "PreloginUserDb.h" +#import +#import +#import "debugging.h" +#import +#import +#import + +AUTHD_DEFINE_LOG + +SOFT_LINK_FRAMEWORK(Frameworks, LocalAuthentication) +SOFT_LINK_FRAMEWORK(PrivateFrameworks, DiskManagement) +SOFT_LINK_FRAMEWORK(Frameworks, DiskArbitration) +SOFT_LINK_FRAMEWORK(PrivateFrameworks, APFS) + +SOFT_LINK_CLASS(LocalAuthentication, LAContext) +SOFT_LINK_CLASS(DiskManagement, DMManager) +SOFT_LINK_CLASS(DiskManagement, DMAPFS) +SOFT_LINK_FUNCTION(APFS, APFSVolumeGetUnlockRecord, soft_APFSVolumeGetUnlockRecord, errno_t, (const char *disk, uuid_t wrecUUID, CFDataRef *data), (disk, wrecUUID, data)) +SOFT_LINK_FUNCTION(DiskArbitration, DADiskMount, soft_DADiskMount, void, ( DADiskRef disk, CFURLRef __nullable path, DADiskMountOptions options, DADiskMountCallback __nullable callback, void * __nullable context), (disk, path, options, callback, context )) +SOFT_LINK_FUNCTION(DiskArbitration, DADiskUnmount, soft_DADiskUnmount, void, ( DADiskRef disk, DADiskUnmountOptions options, DADiskUnmountCallback __nullable callback, void * __nullable context), (disk, options, callback, context )) +SOFT_LINK_FUNCTION(DiskArbitration, DADissenterGetStatusString, soft_DADissenterGetStatusString, CFStringRef __nullable, ( DADissenterRef dissenter ), ( dissenter )) +SOFT_LINK_FUNCTION(DiskManagement, DMUnlocalizedTechnicalErrorString, soft_DMUnlocalizedTechnicalErrorString, NSString *, ( DMDiskErrorType inError ), ( inError )) +SOFT_LINK_FUNCTION(DiskArbitration, DASessionCreate, soft_DASessionCreate, DASessionRef __nullable, ( CFAllocatorRef __nullable allocator ), ( allocator )) +SOFT_LINK_FUNCTION(DiskArbitration, DADissenterGetStatus, soft_DADissenterGetStatus, DAReturn, ( DADissenterRef dissenter ), ( dissenter )) +SOFT_LINK_FUNCTION(DiskArbitration, DASessionSetDispatchQueue, soft_DASessionSetDispatchQueue, void, ( DASessionRef session, dispatch_queue_t __nullable queue ), ( session, queue )) + +static NSString *kVekItemName = @"SecureAccessToken"; +static NSString *kGUIDItemName = @"GeneratedUID"; +static NSString *kAuthenticationAuthority = @"AuthenticationAuthority"; +static NSString *kIsAdmintemName = @"Admin"; +static NSString *kSCUnlockDataItemName = @"FVTokenSecret"; +static NSString *kSCEnforcementItemName = @"SmartCardEnforcement"; +static NSString *kSCUacItemName = @"userAccountControl"; + +static NSString *kLongNameItemName = @"RealName"; +static NSString *kUidItemName = @"UID"; +static NSString *kVekFile = @"%@/%@/var/db/secureaccesstoken.plist"; +static NSString *kUsersFile = @"%@/%@/var/db/AllUsersInfo.plist"; + +static NSString *kUsersGUID = @"UserIdent"; +static NSString *kUsersNameSection = @"UserNamesData"; +static NSString *kUsersSection = @"CryptoUsers"; + + +@interface PreloginUserDb : NSObject + +- (instancetype)init; + +- (BOOL) loadWithError:(NSError **)error; + +- (NSArray *) users; +- (NSArray *) users:(NSString *)volumeUuid; + +@end + +typedef void (^AIRDBDACommonCompletionHandler)(DADissenterRef dissenter); +static void _commonDACompletionCallback(DADiskRef disk, DADissenterRef dissenter, void *context) +{ + AIRDBDACommonCompletionHandler handler = (__bridge AIRDBDACommonCompletionHandler)context; + handler(dissenter); +} + +@implementation PreloginUserDb { + DMManager *_diskMgr; + id _daSession; + NSMutableDictionary *_dbDataDict; // NSDictionary indexed by volume UUID (NSString*) + NSMutableDictionary *_dbVolumeGroupMap; + dispatch_queue_t _queue; +} + +- (instancetype)init +{ + if ((self = [super init])) { + _queue = dispatch_queue_create("com.apple.PLUDB", DISPATCH_QUEUE_SERIAL); + if (!_queue) { + os_log_error(AUTHD_LOG, "Failed to create queue"); + return nil; + } + + _diskMgr = [[getDMManagerClass() alloc] init]; + if (!_diskMgr) { + os_log_error(AUTHD_LOG, "Failed to get DM"); + return nil; + } + + _daSession = (__bridge_transfer id)soft_DASessionCreate(kCFAllocatorDefault); + if (!_daSession) { + os_log_error(AUTHD_LOG, "Failed to get DA"); + return nil; + } + + soft_DASessionSetDispatchQueue((__bridge DASessionRef _Nullable)_daSession, _queue); + [_diskMgr setDefaultDASession:(__bridge DASessionRef _Nullable)(_daSession)]; + } + return self; +} + +- (BOOL)loadWithError:(NSError **)err +{ + // get all preboot volumes + NSArray* prebootVolumes = [self allPrebootVolumes]; + if (prebootVolumes.count == 0) { + os_log_error(AUTHD_LOG, "Failed to get preboot volumes for Prelogin userDB"); + if (err) { + *err = [NSError errorWithDomain:@"com.apple.authorization" code:-1000 userInfo:@{ NSLocalizedDescriptionKey : @"Failed to get preboot volumes for Prelogin userDB"}]; + } + return NO; + } + + NSUUID *uuid = [self currentRecoveryVolumeUUID]; + os_log_info(AUTHD_LOG, "Current Recovery Volume UUID: %{public}@", uuid); + + _dbDataDict = [NSMutableDictionary new]; + _dbVolumeGroupMap = [NSMutableDictionary new]; + [self processPrebootVolumes:prebootVolumes currentRecoveryVolumeUUID:uuid]; + + if (_dbDataDict.count == 0 && uuid != nil) { + os_log(AUTHD_LOG, "No admins found. Try to load all preboot partitions"); + _dbDataDict = [NSMutableDictionary new]; + [self processPrebootVolumes:prebootVolumes currentRecoveryVolumeUUID:nil]; // load admins from ALL preboot partitions + } + + if (err) { + *err = nil; + } + return YES; +} + +- (NSArray *)users +{ + return [self users:nil]; +} + +- (NSArray *) users:(NSString *)requestedUuid +{ + if (!_dbDataDict.allValues) { + return nil; + } + if (requestedUuid && !_dbDataDict[requestedUuid]) { + NSString *realUuid = _dbVolumeGroupMap[requestedUuid]; + if (!realUuid) { + os_log_info(AUTHD_LOG, "Requested volume %{public}@ was not found and is not volumeGroup", requestedUuid); + NSArray *keys = [_dbVolumeGroupMap allKeysForObject:requestedUuid]; + for(NSString *uuid in keys) { + if (_dbDataDict[uuid]) { + realUuid = uuid; + break; + } + } + if (!realUuid) { + os_log_info(AUTHD_LOG, "Requested volumeGroup %{public}@ was not found", requestedUuid); + return nil; // no users for requested partition and no mapping for VolumeGroup or vice versa + } + } + os_log_info(AUTHD_LOG, "Requested volume %{public}@ has no users, trying volume %{public}@", requestedUuid, realUuid); + requestedUuid = realUuid; + } + + NSMutableArray *allUsers = [NSMutableArray new]; + for (NSString *uuid in _dbDataDict) { + if (requestedUuid && ![requestedUuid isEqualToString:uuid]) { + os_log_info(AUTHD_LOG, "Requested volume %{public}@ so ignoring volume %{public}@", requestedUuid, uuid); + continue; + } + [allUsers addObjectsFromArray:_dbDataDict[uuid]]; + } + return allUsers; +} +#pragma mark - Private Methods + +- (void)processPrebootVolumes:(NSArray*)prebootVolumes currentRecoveryVolumeUUID:(NSUUID *)currentRecoveryVolumeUUID +{ + // process each preboot volume + for (id prebootVolume in prebootVolumes) { + + // mount the preboot volume. If it fails it could be already mounted. Try to get mountPoint anyway. + Boolean mounted = [self mountPrebootVolume:prebootVolume]; + + // get a mount point of the preboot volume + NSString* mountPoint = [self mountPointForPrebootVolume:prebootVolume]; + if (!mountPoint) { + continue; + } + + // process the preboot volume + NSDirectoryEnumerator *dirEnumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:mountPoint isDirectory:YES] includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:nil]; + for (NSURL *url in dirEnumerator) { + BOOL isDir = NO; + [[NSFileManager defaultManager] fileExistsAtPath:url.path isDirectory:&isDir]; + if (!isDir) { + os_log_info(AUTHD_LOG, "Skipping file %{public}@ (not a directory)", url.path); + continue; + } + + NSUUID* volumeUUID = [[NSUUID alloc] initWithUUIDString:url.lastPathComponent]; // the dir has the name as UUID + if (!volumeUUID) { + os_log_info(AUTHD_LOG, "Ignoring folder %{public}@ (not UUID)", url); + continue; + } + + if (currentRecoveryVolumeUUID && ![currentRecoveryVolumeUUID isEqualTo:volumeUUID]) { + os_log_info(AUTHD_LOG, "The preboot volume skipped: %{public}@ (not the currentRecoveryVolumeUUID %{public}@)", url, currentRecoveryVolumeUUID); + continue; + } + + [self processVolumeData:volumeUUID mountPoint:mountPoint]; + } + + // unmount the preboot volume + if (mounted) { + [self unmountPrebootVolume:prebootVolume]; + } + } +} + +#define kEFISystemVolumeUUIDVariableName "SystemVolumeUUID" +- (NSUUID *)currentRecoveryVolumeUUID +{ + NSData *data; + NSString * const LANVRAMNamespaceStartupManager = @"5EEB160F-45FB-4CE9-B4E3-610359ABF6F8"; + + NSString *key = [NSString stringWithFormat:@"%@:%@", LANVRAMNamespaceStartupManager, @kEFISystemVolumeUUIDVariableName]; + + io_registry_entry_t match = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options"); + if (match) { + CFTypeRef entry = IORegistryEntryCreateCFProperty(match, (__bridge CFStringRef)key, kCFAllocatorDefault, 0); + IOObjectRelease(match); + + if (entry) + { + if (CFGetTypeID(entry) == CFDataGetTypeID()) + data = CFBridgingRelease(entry); + else + CFRelease(entry); + } + } + os_log_info(AUTHD_LOG, "Current boot volume: %{public}@", data); + + if (data) { + return [[NSUUID alloc] initWithUUIDBytes:data.bytes]; + } else { + return nil; + } +} + +- (NSArray *)allPrebootVolumes +{ + NSMutableArray* result = [NSMutableArray new]; + + DMAPFS* dmAPFS = [[getDMAPFSClass() alloc] initWithManager:_diskMgr]; + + for (id tmp in _diskMgr.disks) { + DADiskRef diskRef = (__bridge DADiskRef)(tmp); + os_log_info(AUTHD_LOG, "Found disk %{public}@", diskRef); + + BOOL preboot; + DMDiskErrorType diskErr = [dmAPFS isPrebootVolume:diskRef prebootRole:&preboot]; + if (diskErr) { + os_log(AUTHD_LOG, "Failed to determine preboot state for %{public}@: %{public}@", diskRef, soft_DMUnlocalizedTechnicalErrorString(diskErr)); + continue; + } + if (!preboot) { + os_log_info(AUTHD_LOG, "Not a preboot volume: %{public}@", diskRef); + continue; + } + + id prebootVolume = CFBridgingRelease([_diskMgr copyBooterDiskForDisk:diskRef error:&diskErr]); + if (prebootVolume) { + os_log_info(AUTHD_LOG, "Found APFS preboot %{public}@", prebootVolume); + [result addObject:prebootVolume]; + } else { + os_log_error(AUTHD_LOG, "Failed to copy preboot for disk %{public}@, err: %{public}@", diskRef, soft_DMUnlocalizedTechnicalErrorString(diskErr)); + } + } + + return result; +} + +- (BOOL)mountPrebootVolume:(id)preboot +{ + __block BOOL success = NO; + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + AIRDBDACommonCompletionHandler completionHandler = ^(DADissenterRef dissenter) { + success = (dissenter == NULL); + if (dissenter != NULL) { + os_log(AUTHD_LOG, "Failed to mount preboot volume %{public}@ (status: 0x%x, reason: \"%{public}@\").", preboot, soft_DADissenterGetStatus(dissenter), soft_DADissenterGetStatusString(dissenter)); + } + dispatch_semaphore_signal(sem); + }; + soft_DADiskMount((__bridge DADiskRef _Nonnull)(preboot), NULL, kDADiskMountOptionDefault, _commonDACompletionCallback, (__bridge void * _Nullable)(completionHandler)); + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + return success; +} + +- (NSString *)mountPointForPrebootVolume:(id)preboot +{ + DMDiskErrorType diskErr; + NSString* result = [_diskMgr mountPointForDisk:(__bridge DADiskRef _Nonnull)(preboot) error:&diskErr]; + if (result) { + os_log_info(AUTHD_LOG, "Mounted preboot partition %{public}@ at %{public}@", preboot, result); + } else { + os_log_error(AUTHD_LOG, "Failed to get preboot mount point: %{public}@", soft_DMUnlocalizedTechnicalErrorString(diskErr)); + } + return result; +} + +- (void)unmountPrebootVolume:(id)preboot +{ + soft_DADiskUnmount((__bridge DADiskRef _Nonnull)(preboot), kDADiskUnmountOptionDefault, nil, nil); + os_log_info(AUTHD_LOG, "Preboot partition unmounted: %{public}@", preboot); +} + +- (NSString *)deviceNodeForVolumeWithUUID:(NSUUID *)volumeUuid diskRef:(DADiskRef *)diskRef +{ + DMDiskErrorType diskErr; + DADiskRef localDiskRef = [_diskMgr copyDiskForVolumeUUID:volumeUuid.UUIDString error:&diskErr]; + if (!localDiskRef) { + os_log_error(AUTHD_LOG, "Failed to find disk with volume %{public}@: %{public}@", volumeUuid, soft_DMUnlocalizedTechnicalErrorString(diskErr)); + return nil; + } + if (diskRef) { + *diskRef = localDiskRef; + CFRetain(*diskRef); + } + os_log_info(AUTHD_LOG, "Found disk %{public}@ with volume UUID %{public}@", localDiskRef, volumeUuid); + NSString* deviceNode = [self deviceNodeForDisk:localDiskRef]; + CFRelease(localDiskRef); + return deviceNode; +} + +- (NSString *)deviceNodeForDisk:(DADiskRef)diskRef +{ + DMDiskErrorType diskErr; + NSString *deviceNode = [_diskMgr deviceNodeForDisk:diskRef error:&diskErr]; + if (!deviceNode) { + os_log_error(AUTHD_LOG, "Failed to find device node for disk %{public}@: %{public}@", diskRef, soft_DMUnlocalizedTechnicalErrorString(diskErr)); + return nil; + } + os_log_info(AUTHD_LOG, "Device node found: %{public}@", deviceNode); + return deviceNode; +} + +- (NSData *)loadVEKforVolumeWithUUID:(NSUUID *)volumeUuid mountPoint:(NSString *)mountPoint +{ + NSString *vekPath = [NSString stringWithFormat:kVekFile, mountPoint, volumeUuid.UUIDString]; + NSDictionary *vekDict = [NSDictionary dictionaryWithContentsOfFile:vekPath]; + NSData *vek = vekDict[kVekItemName]; + if (!vek) { + os_log_error(AUTHD_LOG, "Failed to load DiskToken from %{public}@", vekPath); + return nil; + } + os_log_info(AUTHD_LOG, "Loaded DiskToken from %{public}@", vekPath); + + return vek; +} + +- (NSData *)loadKEKforUuid:(NSString *)userUuid deviceNode:(NSString *)deviceNode +{ + NSUUID *nsUuid = [[NSUUID alloc] initWithUUIDString:userUuid]; + uuid_t uuid; + [nsUuid getUUIDBytes:uuid]; + CFDataRef dataCF; + errno_t err = soft_APFSVolumeGetUnlockRecord(deviceNode.UTF8String, uuid, &dataCF); + if(err != 0) { + os_log_error(AUTHD_LOG, "Failed to find SecureToken on device node %{public}@ and UUID %{public}@ (%d)", deviceNode, userUuid, err); + return nil; + } + os_log_info(AUTHD_LOG, "Loaded SecureToken from device node %{public}@", deviceNode); + + NSData *kek = CFBridgingRelease(dataCF); + return kek; +} + +- (NSDictionary *)loadUserDatabaseForVolumeUUID:(NSUUID *)volumeUuid mountPoint:(NSString *)mountPoint +{ + NSString *usersPath = [NSString stringWithFormat:kUsersFile, mountPoint, volumeUuid.UUIDString]; + NSDictionary *users = [NSDictionary dictionaryWithContentsOfFile:usersPath]; + if (users.count == 0) { + os_log_error(AUTHD_LOG, "Failed to find user records in file %{public}@", usersPath); + return nil; + } + os_log_debug(AUTHD_LOG, "Loaded %lu user records from file %{public}@", (unsigned long)users.count, usersPath); + return users; +} + +- (void)processVolumeData:(NSUUID *)volumeUuid mountPoint:(NSString *)mountPoint +{ + os_log_info(AUTHD_LOG, "Processing volume data: %{public}@", volumeUuid); + NSData *vek = [self loadVEKforVolumeWithUUID:volumeUuid mountPoint:mountPoint]; + if (!vek) { + return; + } + + DADiskRef cfDiskRef = NULL; + NSString* deviceNode = [self deviceNodeForVolumeWithUUID:volumeUuid diskRef:&cfDiskRef]; + id diskRef = CFBridgingRelease(cfDiskRef); + if (!deviceNode) { + return; + } + NSString *volumeGroupUuid; + DMAPFS* dmAPFS = [[getDMAPFSClass() alloc] initWithManager:_diskMgr]; + DMDiskErrorType diskErr = [dmAPFS volumeGroupForVolume:(__bridge DADiskRef _Nonnull)(diskRef) id:&volumeGroupUuid]; + if (diskErr != kDiskErrorNoError || volumeGroupUuid == nil) { + os_log_error(AUTHD_LOG, "Error %d while trying to get volume group for %{public}@", diskErr, volumeUuid); + } else { + if ([volumeUuid.UUIDString isEqualTo:volumeGroupUuid]) { + NSArray *systemVolumeDisks = nil; + diskErr = [dmAPFS disksForVolumeGroup:volumeGroupUuid volumeDisks:nil systemVolumeDisks:&systemVolumeDisks dataVolumeDisks:nil userVolumeDisks:nil container:nil]; + if (diskErr != kDiskErrorNoError || systemVolumeDisks == nil) { + os_log_error(AUTHD_LOG, "Error %d while trying to get volume group disks for %{public}@", diskErr, volumeGroupUuid); + } else { + // There should be only one systemVolume, but the API returns an array so we'll process as many as it wants to give us + for (id tmp in systemVolumeDisks) { + DADiskRef systemVolumeDiskRef = (__bridge DADiskRef)(tmp); + NSString *systemVolumeUuid = nil; + diskErr = [dmAPFS volumeUUIDForVolume:systemVolumeDiskRef UUID:&systemVolumeUuid]; + if (diskErr != kDiskErrorNoError || systemVolumeUuid == nil) { + os_log_error(AUTHD_LOG, "Error %d while trying to get volume uuid disks for some system volumes of group %{public}@", diskErr, volumeGroupUuid); + } else { + os_log(AUTHD_LOG, "Volume %{public}@ belongs to the group %{public}@", systemVolumeUuid, volumeGroupUuid); + _dbVolumeGroupMap[systemVolumeUuid] = volumeGroupUuid; + } + } + } + } + } + + NSDictionary *users = [self loadUserDatabaseForVolumeUUID:volumeUuid mountPoint:mountPoint]; + for (NSString *userName in users) { + NSDictionary *userData = users[userName]; + os_log_debug(AUTHD_LOG, "Processing user: %{public}@", userData); + NSString *userGuid = userData[kGUIDItemName]; + if (userGuid == nil) { + os_log_error(AUTHD_LOG, "Failed to find GUID for user %{public}@", userName); + continue; + } + NSData* kek = [self loadKEKforUuid:userGuid deviceNode:deviceNode]; + if (!kek) { + os_log_error(AUTHD_LOG, "Failed to find SecureToken for user %{public}@", userName); + continue; + } + + NSArray *aauthority = userData[kAuthenticationAuthority]; + NSMutableDictionary *dict = @{}.mutableCopy; + if (aauthority) { + dict[@PLUDB_SCPAIR] = aauthority; + os_log_debug(AUTHD_LOG, "Using authority: %{public}@", aauthority); + } + + Boolean owner; + struct aks_fv_param_s params = {}; + aks_fv_blob_state_s verifier_state = {}; + struct aks_fv_data_s kekData = { .data = (void *)kek.bytes, .len = kek.length }; + + int res = aks_fv_get_blob_state(¶ms, &kekData, &verifier_state); + if (res) { + os_log_error(AUTHD_LOG, "Blob state failed: %x", res); + owner = NO; + } else { + owner = ((verifier_state.flags & aks_fv_state_is_owner) == aks_fv_state_is_owner); + } + + dict[@PLUDB_USERNAME] = userName; + dict[@PLUDB_GUID] = userGuid; + dict[@PLUDB_ADMIN] = userData[kIsAdmintemName]; + dict[@PLUDB_KEK] = kek; + dict[@PLUDB_VEK] = vek; + dict[@PLUDB_DNODE] = deviceNode; + dict[@PLUDB_OWNER] = @(owner); + + if ([userData.allKeys containsObject:kSCUnlockDataItemName]) { + dict[@PLUDB_SCUNLOCK_DATA] = userData[kSCUnlockDataItemName]; + } + if ([userData.allKeys containsObject:kSCEnforcementItemName]) { + dict[@PLUDB_SCUNLOCK_DATA] = userData[kSCEnforcementItemName]; + } + if ([userData.allKeys containsObject:kSCUnlockDataItemName]) { + dict[@PLUDB_SCUNLOCK_DATA] = userData[kSCUnlockDataItemName]; + } + if ([userData.allKeys containsObject:kSCUacItemName]) { + dict[@PLUDB_SCUAC] = userData[kSCUacItemName]; + } + if ([userData.allKeys containsObject:kLongNameItemName]) { + dict[@PLUDB_LUSERNAME] = userData[kLongNameItemName]; + } + + NSMutableArray *array = _dbDataDict[volumeUuid.UUIDString]; + if (array == nil) { + array = [NSMutableArray new]; + if (!array) { + os_log_error(AUTHD_LOG, "Failed to create users array"); + return; + } + _dbDataDict[volumeUuid.UUIDString] = array; + } + + os_log_info(AUTHD_LOG, "Prelogin UserDB added entry: %{public}@", dict); + [array addObject:dict]; + } +} + +@end + +OSStatus preloginudb_copy_userdb(const char *uuid, UInt32 flags, CFArrayRef *output) +{ + if (!output) { + return errAuthorizationBadAddress; + } + static PreloginUserDb *database; + static OSStatus loadError = errAuthorizationSuccess; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + + os_log_info(AUTHD_LOG, "Going to load User DB"); + + database = [[PreloginUserDb alloc] init]; + if (!database) { + loadError = errAuthorizationInvalidSet; + } else { + NSError *error; + if ([database loadWithError:&error]) { + loadError = (int)error.code; + } + } + }); + + if (loadError) { + return loadError; + } + + os_log_debug(AUTHD_LOG, "Processing user db for volume %{public}s with flags %d", uuid, flags); + + *output = CFBridgingRetain([database users:uuid ? [NSString stringWithUTF8String:uuid] : nil]); + return errAuthorizationSuccess; +} diff --git a/OSX/authd/authd-Entitlements.plist b/OSX/authd/authd-Entitlements.plist index 7ef4f57c..e73d9936 100644 --- a/OSX/authd/authd-Entitlements.plist +++ b/OSX/authd/authd-Entitlements.plist @@ -2,9 +2,13 @@ + com.apple.keystore.console + com.apple.private.LocalAuthentication.ExtractCredential - com.apple.keystore.console + com.apple.private.security.clear-library-validation + + com.apple.keystore.filevault diff --git a/OSX/authd/authd_private.h b/OSX/authd/authd_private.h index 4fc95b64..6d72a97c 100644 --- a/OSX/authd/authd_private.h +++ b/OSX/authd/authd_private.h @@ -106,7 +106,9 @@ enum { AUTHORIZATION_DISMISS, AUTHORIZATION_SETUP, AUTHORIZATION_ENABLE_SMARTCARD, - AUTHORIZATION_PREAUTHORIZE_CREDENTIALS + AUTHORIZATION_PREAUTHORIZE_CREDENTIALS, + AUTHORIZATION_COPY_PRELOGIN_USERDB, + AUTHORIZATION_COPY_RIGHT_PROPERTIES }; #if defined(__cplusplus) diff --git a/OSX/authd/authdb.c b/OSX/authd/authdb.c index c10ce840..959fc817 100644 --- a/OSX/authd/authdb.c +++ b/OSX/authd/authdb.c @@ -943,13 +943,18 @@ _import_rules(authdb_connection_t dbconn, CFMutableArrayRef rules, bool version_ if (version_check) { if (rule_get_id(rule) != 0) { // rule already exists see if we need to update rule_t current = rule_create_with_string(rule_get_name(rule), dbconn); - if (rule_get_version(rule) > rule_get_version(current)) { + int64_t currVer = rule_get_version(current); + int64_t newVer = rule_get_version(rule); + + if (newVer > currVer) { update = true; } CFReleaseSafe(current); if (!update) { continue; + } else { + os_log(AUTHD_LOG, "authdb: right %{public}s new version %lld vs existing version %lld, will update", rule_get_name(rule), newVer, currVer); } } } @@ -977,7 +982,7 @@ _import_rules(authdb_connection_t dbconn, CFMutableArrayRef rules, bool version_ if (!delayCommit) { bool success = rule_sql_commit(rule, dbconn, now, NULL); - os_log_debug(AUTHD_LOG, "authdb: %{public}s %{public}s %{public}s %{public}s", + os_log(AUTHD_LOG, "authdb: %{public}s %{public}s %{public}s %{public}s", update ? "updating" : "importing", rule_get_type(rule) == RT_RULE ? "rule" : "right", rule_get_name(rule), success ? "success" : "FAIL"); diff --git a/OSX/authd/authitems.c b/OSX/authd/authitems.c index ea49287a..4e5945f0 100644 --- a/OSX/authd/authitems.c +++ b/OSX/authd/authitems.c @@ -6,9 +6,12 @@ #include "authutilities.h" #include +#include #include #include +#include + AUTHD_DEFINE_LOG typedef struct _auth_item_s * auth_item_t; @@ -48,7 +51,7 @@ auth_item_copy_auth_item_xpc(auth_item_t item) xpc_dictionary_set_string(xpc_data, AUTH_XPC_ITEM_NAME, item->data.name); if (item->data.value) { // authd is holding on to multiple copies of my password in the clear - bool sensitive = strcmp(item->data.name, "password") == 0; + bool sensitive = strcmp(item->data.name, AGENT_PASSWORD) == 0; if (sensitive) { vm_address_t vmBytes = 0; size_t xpcOutOfBandBlockSize = (item->data.valueLength > 32768 ? item->data.valueLength : 32768); // min 16K on 64-bit systems and 12K on 32-bit systems diff --git a/OSX/authd/authorization.plist b/OSX/authd/authorization.plist index 43774837..4236dff6 100644 --- a/OSX/authd/authorization.plist +++ b/OSX/authd/authorization.plist @@ -578,14 +578,17 @@ See remaining rules for examples. com.apple.trust-settings.admin - allow-root - - class - user comment - For modifying Trust Settings in the Local Admin domain. - group - admin + For modifying Trust Settings in the Admin domain. Requires entitlement or admin authentication. + class + rule + k-of-n + 1 + rule + + entitled + authenticate-admin + com.apple.trust-settings.user @@ -596,10 +599,14 @@ See remaining rules for examples. com.apple.uninstalld.uninstall + authenticate-user + class - rule - rule - entitled-admin-or-authenticate-admin + user + entitled + + version + 1 config.add. @@ -675,6 +682,23 @@ See remaining rules for examples. comment For burning media. + com.apple.installassistant.requestpassword + + authenticate-user + + class + user + comment + Authenticate as an administrator, password only. + group + admin + password-only + + shared + + timeout + 0 + system.csfde.requestpassword.weak class @@ -825,7 +849,7 @@ See remaining rules for examples. class rule comment - Checked when user is installing Apple-provided software. + Checked when user is installing Apple software. rule root-or-entitled-admin-or-authenticate-admin @@ -914,6 +938,7 @@ See remaining rules for examples. mechanisms builtin:policy-banner + builtin:prelogin loginwindow:login builtin:login-begin builtin:reset-password,privileged @@ -931,7 +956,24 @@ See remaining rules for examples. loginwindow:done version - 7 + 8 + + system.login.filevault + + class + evaluate-mechanisms + comment + Login mechanism based rule for Filevault. + mechanisms + + builtin:policy-banner + loginwindow:login + builtin:login-begin + builtin:authenticate,privileged + builtin:login-success + loginwindow:success + loginwindow:done + system.login.fus @@ -1601,6 +1643,36 @@ See remaining rules for examples. version 1 + com.apple.configurationprofiles.deviceenrollment.install + + class + user + comment + This right is used by UserManagement to ask for an admin password. + group + admin + password-only + + shared + + version + 1 + + com.apple.configurationprofiles.deviceenrollment.uninstall + + class + user + comment + This right is used by UserManagement to ask for an admin password. + group + admin + password-only + + shared + + version + 1 + com.apple.safaridriver.allow comment @@ -1692,7 +1764,29 @@ See remaining rules for examples. shared - + com.apple.system-migration.launch + + comment + Used by Migration Assistant. + class + rule + rule + authenticate-admin-nonshared + shared + + + com.apple.system-migration.cleanup + + comment + Used by System Migration. + class + rule + rule + authenticate-admin-nonshared + shared + + + rules admin @@ -1741,8 +1835,9 @@ See remaining rules for examples. builtin:authenticate builtin:reset-password,privileged builtin:authenticate,privileged - PKINITMechanism:auth,privileged + version + 1 kcunlock diff --git a/OSX/authd/authtoken.c b/OSX/authd/authtoken.c index 611d4415..b39d393c 100644 --- a/OSX/authd/authtoken.c +++ b/OSX/authd/authtoken.c @@ -13,6 +13,8 @@ #include #include +#include + AUTHD_DEFINE_LOG static Boolean AuthTokenEqualCallBack(const void *value1, const void *value2) diff --git a/OSX/authd/authutilities.c b/OSX/authd/authutilities.c index 60b6b2fd..3bcd2c0c 100644 --- a/OSX/authd/authutilities.c +++ b/OSX/authd/authutilities.c @@ -5,7 +5,6 @@ #include "debugging.h" #include -#include AUTHD_DEFINE_LOG @@ -23,6 +22,11 @@ SerializeItemSet(const AuthorizationItemSet * itemSet) xpc_object_t item = xpc_dictionary_create(NULL, NULL, 0); require(item != NULL, done); + if (itemSet->items[i].name == NULL) { + os_log_error(AUTHD_LOG, "ItemSet - item #%d name is NULL", i); + xpc_release(item); + continue; + } xpc_dictionary_set_string(item, AUTH_XPC_ITEM_NAME, itemSet->items[i].name); xpc_dictionary_set_uint64(item, AUTH_XPC_ITEM_FLAGS, itemSet->items[i].flags); xpc_dictionary_set_data(item, AUTH_XPC_ITEM_VALUE, itemSet->items[i].value, itemSet->items[i].valueLength); @@ -305,3 +309,9 @@ done: free_safe(values); return result; } + +bool isInLWOS() +{ + // temporary solution until we find a better way + return getenv("__OSINSTALL_ENVIRONMENT") != NULL; +} diff --git a/OSX/authd/authutilities.h b/OSX/authd/authutilities.h index ebe1e5a4..981b9bef 100644 --- a/OSX/authd/authutilities.h +++ b/OSX/authd/authutilities.h @@ -26,7 +26,9 @@ void * _copy_data(const void * data, size_t dataLen); bool _cf_set_iterate(CFSetRef, bool(^iterator)(CFTypeRef value)); bool _cf_bag_iterate(CFBagRef, bool(^iterator)(CFTypeRef value)); bool _cf_dictionary_iterate(CFDictionaryRef, bool(^iterator)(CFTypeRef key,CFTypeRef value)); - + +bool isInLWOS(void); + #if defined(__cplusplus) } #endif diff --git a/OSX/authd/com.apple.authd.sb b/OSX/authd/com.apple.authd.sb index 5b94ca8a..0c17b4d6 100644 --- a/OSX/authd/com.apple.authd.sb +++ b/OSX/authd/com.apple.authd.sb @@ -27,7 +27,9 @@ (global-name "com.apple.security.authhost") (global-name "com.apple.SecurityServer") (global-name "com.apple.system.opendirectoryd.api") - (global-name "com.apple.ocspd")) + (global-name "com.apple.ocspd") + (global-name "com.apple.DiskArbitration.diskarbitrationd") + (global-name "com.apple.diskmanagementd")) (allow ipc-posix-shm (ipc-posix-name "apple.shm.notification_center") @@ -40,3 +42,7 @@ (preference-domain "com.apple.authd")) (allow system-audit system-sched) + +(allow iokit-open + (iokit-user-client-class "AppleAPFSUserClient") + (iokit-user-client-class "AppleKeyStoreUserClient")) diff --git a/OSX/authd/crc.h b/OSX/authd/crc.h index 85184384..fab34a2c 100644 --- a/OSX/authd/crc.h +++ b/OSX/authd/crc.h @@ -19,7 +19,7 @@ crc64_init() AUTH_INLINE uint64_t crc64_final(uint64_t crc) { - return crc ^= xorout; + return crc ^ xorout; } AUTH_INLINE AUTH_NONNULL_ALL uint64_t diff --git a/OSX/authd/credential.c b/OSX/authd/credential.c index 6fd46fc0..24c0f673 100644 --- a/OSX/authd/credential.c +++ b/OSX/authd/credential.c @@ -2,6 +2,8 @@ #include "credential.h" #include "authutilities.h" +#include "authitems.h" +#include #include "debugging.h" #include "crc.h" @@ -101,7 +103,7 @@ static credential_t _credential_create() { credential_t cred = NULL; - + cred = (credential_t)_CFRuntimeCreateInstance(kCFAllocatorDefault, credential_get_type_id(), AUTH_CLASS_SIZE(credential), NULL); require(cred != NULL, done); @@ -141,6 +143,23 @@ done: return cred; } +credential_t +credential_create_lwos(auth_items_t context, bool session) +{ + credential_t cred = NULL; + + cred = _credential_create(); + require(cred != NULL, done); + + const char *username = session ? "system session" : auth_items_get_string(context, AGENT_USERNAME); + cred->uid = session ? 0 : -500; + cred->name = _copy_string(username); + cred->realName = _copy_string(username); + cred->valid = false; +done: + return cred; +} + credential_t credential_create_with_credential(credential_t srcCred, bool shared) { @@ -220,9 +239,14 @@ credential_is_right(credential_t cred) } bool -credential_check_membership(credential_t cred,const char* group) +credential_check_membership(credential_t cred, const char* group) { bool result = false; + + if (isInLWOS()) { + return false; // cannot succeed in LWOS as we do not have group data + } + CFStringRef cachedGroup = NULL; require(group != NULL, done); require(cred->uid != 0 || cred->uid != (uid_t)-2, done); diff --git a/OSX/authd/credential.h b/OSX/authd/credential.h index 1f7576e7..fd283e44 100644 --- a/OSX/authd/credential.h +++ b/OSX/authd/credential.h @@ -20,6 +20,9 @@ credential_t credential_create_with_credential(credential_t,bool); AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED credential_t credential_create_with_right(const char *); +AUTH_WARN_RESULT AUTH_MALLOC AUTH_RETURNS_RETAINED +credential_t credential_create_lwos(auth_items_t context, bool session); + AUTH_NONNULL_ALL uid_t credential_get_uid(credential_t); diff --git a/OSX/authd/engine.c b/OSX/authd/engine.c index 7df8370c..08a4f80e 100644 --- a/OSX/authd/engine.c +++ b/OSX/authd/engine.c @@ -37,8 +37,8 @@ static void _set_auth_token_hints(auth_items_t, auth_items_t, auth_token_t); static OSStatus _evaluate_user_credential_for_rule(engine_t, credential_t, rule_t, bool, bool, enum Reason *); static void _engine_set_credential(engine_t, credential_t, bool); static OSStatus _evaluate_rule(engine_t, rule_t, bool *); -static bool _preevaluate_class_rule(engine_t engine, rule_t rule); -static bool _preevaluate_rule(engine_t engine, rule_t rule); +static bool _preevaluate_class_rule(engine_t engine, rule_t rule, const char **group); +static bool _preevaluate_rule(engine_t engine, rule_t rule, const char **group); static uint64_t global_engine_count; @@ -65,7 +65,6 @@ struct _engine_s { auth_rights_t grantedRights; CFTypeRef la_context; - bool preauthorizing; enum Reason reason; int32_t tries; @@ -156,14 +155,16 @@ engine_create(connection_t conn, auth_token_t auth) engine->reason = noReason; - engine->preauthorizing = false; - engine->la_context = NULL; engine->now = CFAbsoluteTimeGetCurrent(); session_update(auth_token_get_session(engine->auth)); - engine->sessionCredential = credential_create(session_get_uid(auth_token_get_session(engine->auth))); + if (isInLWOS()) { + engine->sessionCredential = credential_create_lwos(NULL, true); + } else { + engine->sessionCredential = credential_create(session_get_uid(auth_token_get_session(engine->auth))); + } engine->credentials = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); engine->effectiveCredentials = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); @@ -313,6 +314,27 @@ _evaluate_credential_for_rule(engine_t engine, credential_t cred, rule_t rule, b } } +static bool _is_lwos_user_in_group(engine_t engine, rule_t rule) +{ + if (!isInLWOS()) { + return false; + } + + const char *group = rule_get_group(rule); + if (!(group && strcmp(group, "admin") == 0)) { + os_log_error(AUTHD_LOG, "Group %{public}s not supported in FV mode (engine %lld)", group, engine->engine_index); + return false; + } + + const char *data = auth_items_get_string(engine->context, kAuthorizationFVAdmin); + if (!data) { + os_log_error(AUTHD_LOG, "User is not member of the group %{public}s (engine %lld)", group, engine->engine_index); + return false; + } + + return (strcmp(data, "1") == 0); +} + static OSStatus _evaluate_user_credential_for_rule(engine_t engine, credential_t cred, rule_t rule, bool ignoreShared, bool sessionOwner, enum Reason * reason) { @@ -329,7 +351,7 @@ _evaluate_user_credential_for_rule(engine_t engine, credential_t cred, rule_t ru return errAuthorizationDenied; } - if (credential_get_valid(cred) != true) { + if (credential_get_valid(cred) != true && !isInLWOS()) { os_log(AUTHD_LOG, "%{public}s %i invalid (does NOT satisfy rule) (engine %lld)", cred_label, credential_get_uid(cred), engine->engine_index); if (reason) { *reason = invalidPassphrase; } return errAuthorizationDenied; @@ -376,7 +398,7 @@ _evaluate_user_credential_for_rule(engine_t engine, credential_t cred, rule_t ru } } - if (credential_check_membership(cred, rule_get_group(rule))) { + if (credential_check_membership(cred, rule_get_group(rule)) || _is_lwos_user_in_group(engine, rule)) { os_log(AUTHD_LOG, "%{public}s %i is member of group %{public}s (does satisfy rule) (engine %lld)", cred_label, credential_get_uid(cred), rule_get_group(rule), engine->engine_index); return errAuthorizationSuccess; } else { @@ -651,11 +673,16 @@ done: static OSStatus _evaluate_authentication(engine_t engine, rule_t rule) { + os_log_debug(AUTHD_LOG, "engine %lld: FV mode %d", engine->engine_index, isInLWOS()); + OSStatus status = errAuthorizationDenied; ccaudit_t ccaudit = ccaudit_create(engine->proc, engine->auth, AUE_ssauthint); os_log_debug(AUTHD_LOG, "engine %lld: evaluate authentication", engine->engine_index); _set_rule_hints(engine->hints, rule); - _set_session_hints(engine, rule); + if (!isInLWOS()) { + // we do not need to set hints in LWOS as we do not know which user will be authenticated + _set_session_hints(engine, rule); + } CFArrayRef mechanisms = rule_get_mechanisms(rule); if (!(CFArrayGetCount(mechanisms) > 0)) { @@ -684,10 +711,14 @@ _evaluate_authentication(engine_t engine, rule_t rule) status = errAuthorizationDenied; credential_t newCred = NULL; - if (auth_items_exist(engine->context, "uid")) { - newCred = credential_create(auth_items_get_uint(engine->context, "uid")); + + if (isInLWOS() && auth_items_exist(engine->context, kAuthorizationFVAdmin)) { + os_log_debug(AUTHD_LOG, "Credentials for FV unlock (engine %lld)", engine->engine_index); + newCred = credential_create_lwos(engine->context, false); + } else if (auth_items_exist(engine->context, AGENT_CONTEXT_UID)) { + newCred = credential_create(auth_items_get_uint(engine->context, AGENT_CONTEXT_UID)); } else { - os_log_info(AUTHD_LOG, "Mechanism failed to return a valid uid (engine %lld)", engine->engine_index); + os_log_error(AUTHD_LOG, "Mechanism failed to return a valid UID (engine %lld)", engine->engine_index); if (engine->la_context) { // sheet failed so remove sheet reference and next time, standard dialog will be displayed CFReleaseNull(engine->la_context); @@ -695,12 +726,12 @@ _evaluate_authentication(engine_t engine, rule_t rule) } if (newCred) { - if (credential_get_valid(newCred)) { - os_log(AUTHD_LOG, "UID %u authenticated as user %{public}s (UID %u) for right '%{public}s'", auth_token_get_uid(engine->auth), credential_get_name(newCred), credential_get_uid(newCred), engine->currentRightName); + if (credential_get_valid(newCred) || isInLWOS()) { + os_log(AUTHD_LOG, "UID %u authenticated as user %{public}s (UID %i) for right '%{public}s'", auth_token_get_uid(engine->auth), credential_get_name(newCred), credential_get_uid(newCred), engine->currentRightName); ccaudit_log_success(ccaudit, newCred, engine->currentRightName); } else { - os_log(AUTHD_LOG, "UID %u failed to authenticate as user '%{public}s' for right '%{public}s'", auth_token_get_uid(engine->auth), auth_items_get_string(engine->context, "username"), engine->currentRightName); - ccaudit_log_failure(ccaudit, auth_items_get_string(engine->context, "username"), engine->currentRightName); + os_log(AUTHD_LOG, "UID %u failed to authenticate as user '%{public}s' for right '%{public}s'", auth_token_get_uid(engine->auth), auth_items_get_string(engine->context, AGENT_USERNAME), engine->currentRightName); + ccaudit_log_failure(ccaudit, auth_items_get_string(engine->context, AGENT_USERNAME), engine->currentRightName); } status = _evaluate_user_credential_for_rule(engine, newCred, rule, true, false, &engine->reason); @@ -799,10 +830,12 @@ _evaluate_class_user(engine_t engine, rule_t rule) } if (!rule_get_authenticate_user(rule)) { - status = _evaluate_user_credential_for_rule(engine, engine->sessionCredential, rule, true, true, NULL); - - if (status == errAuthorizationSuccess) { - return errAuthorizationSuccess; + if (!isInLWOS()) { + status = _evaluate_user_credential_for_rule(engine, engine->sessionCredential, rule, true, true, NULL); + + if (status == errAuthorizationSuccess) { + return errAuthorizationSuccess; + } } return errAuthorizationDenied; @@ -860,22 +893,22 @@ _evaluate_class_user(engine_t engine, rule_t rule) return errAuthorizationSuccess; } - if (!engine->preauthorizing) { - if (!(engine->flags & kAuthorizationFlagInteractionAllowed)) { + if (!(engine->flags & kAuthorizationFlagSheet)) { + if (!(engine->flags & kAuthorizationFlagInteractionAllowed)) { os_log_error(AUTHD_LOG, "Fatal: interaction not allowed (kAuthorizationFlagInteractionAllowed not set) (engine %lld)", engine->engine_index); - return errAuthorizationInteractionNotAllowed; - } - - if (!(session_get_attributes(auth_token_get_session(engine->auth)) & AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS)) { - os_log_error(AUTHD_LOG, "Fatal: interaction not allowed (session has no ui access) (engine %lld)", engine->engine_index); - return errAuthorizationInteractionNotAllowed; - } - - if (server_in_dark_wake() && !(engine->flags & kAuthorizationFlagIgnoreDarkWake)) { - os_log_error(AUTHD_LOG, "Fatal: authorization denied (DW) (engine %lld)", engine->engine_index); - return errAuthorizationDenied; - } - } + return errAuthorizationInteractionNotAllowed; + } + + if (!(session_get_attributes(auth_token_get_session(engine->auth)) & AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS)) { + os_log_error(AUTHD_LOG, "Fatal: interaction not allowed (session has no ui access) (engine %lld)", engine->engine_index); + return errAuthorizationInteractionNotAllowed; + } + + if (server_in_dark_wake() && !(engine->flags & kAuthorizationFlagIgnoreDarkWake)) { + os_log_error(AUTHD_LOG, "Fatal: authorization denied (DW) (engine %lld)", engine->engine_index); + return errAuthorizationDenied; + } + } return _evaluate_authentication(engine, rule); } @@ -925,15 +958,14 @@ _evaluate_class_rule(engine_t engine, rule_t rule, bool *save_pwd) } static bool -_preevaluate_class_rule(engine_t engine, rule_t rule) +_preevaluate_class_rule(engine_t engine, rule_t rule, const char **group) { os_log_debug(AUTHD_LOG, "engine %lld: _preevaluate_class_rule %{public}s", engine->engine_index, rule_get_name(rule)); __block bool password_only = false; rule_delegates_iterator(rule, ^bool(rule_t delegate) { - if (_preevaluate_rule(engine, delegate)) { + if (_preevaluate_rule(engine, delegate, group)) { password_only = true; - return false; } return true; }); @@ -972,8 +1004,8 @@ _evaluate_class_mechanism(engine_t engine, rule_t rule) if (status == errAuthorizationSuccess) { credential_t newCred = NULL; - if (auth_items_exist(engine->context, "uid")) { - newCred = credential_create(auth_items_get_uint(engine->context, "uid")); + if (auth_items_exist(engine->context, AGENT_CONTEXT_UID)) { + newCred = credential_create(auth_items_get_uint(engine->context, AGENT_CONTEXT_UID)); } else { os_log_info(AUTHD_LOG, "Mechanism did not return a uid (engine %lld)", engine->engine_index); } @@ -1049,7 +1081,7 @@ _evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) // returns true if this rule or its children contain RC_USER rule with password_only==true static bool -_preevaluate_rule(engine_t engine, rule_t rule) +_preevaluate_rule(engine_t engine, rule_t rule, const char **group) { os_log_debug(AUTHD_LOG, "engine %lld: _preevaluate_rule %{public}s", engine->engine_index, rule_get_name(rule)); @@ -1058,9 +1090,12 @@ _preevaluate_rule(engine_t engine, rule_t rule) case RC_DENY: return false; case RC_USER: + if (group && !*group) { + *group = rule_get_group(rule); + } return rule_get_password_only(rule); case RC_RULE: - return _preevaluate_class_rule(engine, rule); + return _preevaluate_class_rule(engine, rule, group); case RC_MECHANISM: return false; default: @@ -1183,129 +1218,49 @@ static bool _verify_sandbox(engine_t engine, const char * right) #pragma mark - #pragma mark engine methods -OSStatus engine_preauthorize(engine_t engine, auth_items_t credentials) +OSStatus engine_get_right_properties(engine_t engine, const char *rightName, CFDictionaryRef *output) { - os_log(AUTHD_LOG, "engine %lld: preauthorizing", engine->engine_index); - - OSStatus status = errAuthorizationDenied; - bool save_password = false; - - engine->flags = kAuthorizationFlagExtendRights; - engine->preauthorizing = true; - CFAssignRetained(engine->la_context, engine_copy_context(engine, credentials)); - _extract_password_from_la(engine); - - const char *user = auth_items_get_string(credentials, kAuthorizationEnvironmentUsername); - require(user, done); - - auth_items_set_string(engine->context, kAuthorizationEnvironmentUsername, user); - struct passwd *pwd = getpwnam(user); - require(pwd, done); - - auth_items_set_int(engine->context, AGENT_CONTEXT_UID, pwd->pw_uid); - - const char *service = auth_items_get_string(credentials, AGENT_CONTEXT_AP_PAM_SERVICE_NAME); - - if (service) { - auth_items_set_string(engine->context, AGENT_CONTEXT_AP_USER_NAME, user); - auth_items_set_string(engine->context, AGENT_CONTEXT_AP_PAM_SERVICE_NAME, service); - } - - if (auth_items_exist(credentials, AGENT_CONTEXT_AP_TOKEN)) { - size_t datalen = 0; - const void *data = auth_items_get_data(credentials, AGENT_CONTEXT_AP_TOKEN, &datalen); - if (data) { - auth_items_set_data(engine->context, AGENT_CONTEXT_AP_TOKEN, data, datalen); - } - } - - auth_items_t decrypted_items = auth_items_create(); - require_action(decrypted_items != NULL, done, os_log_error(AUTHD_LOG, "Unable to create items (engine %lld)", engine->engine_index)); - auth_items_content_copy(decrypted_items, auth_token_get_context(engine->auth)); - auth_items_decrypt(decrypted_items, auth_token_get_encryption_key(engine->auth)); - auth_items_copy(engine->context, decrypted_items); - CFReleaseSafe(decrypted_items); - - engine->dismissed = false; - auth_rights_clear(engine->grantedRights); - - rule_t rule = rule_create_preauthorization(); - engine->currentRightName = rule_get_name(rule); - engine->currentRule = rule; - status = _evaluate_rule(engine, rule, &save_password); - switch (status) { - case errAuthorizationSuccess: - os_log(AUTHD_LOG, "Succeeded preauthorizing client '%{public}s' [%d] for authorization created by '%{public}s' [%d] (%X,%d) (engine %lld)", - process_get_code_url(engine->proc), process_get_pid(engine->proc), - auth_token_get_code_url(engine->auth), auth_token_get_pid(engine->auth), (unsigned int)engine->flags, auth_token_least_privileged(engine->auth), engine->engine_index); - status = errAuthorizationSuccess; - break; - case errAuthorizationDenied: - case errAuthorizationInteractionNotAllowed: - case errAuthorizationCanceled: - os_log(AUTHD_LOG, "Failed to preauthorize client '%{public}s' [%d] for authorization created by '%{public}s' [%d] (%X,%d) (%i) (engine %lld)", - process_get_code_url(engine->proc), process_get_pid(engine->proc), - auth_token_get_code_url(engine->auth), auth_token_get_pid(engine->auth), (unsigned int)engine->flags, auth_token_least_privileged(engine->auth), (int)status, engine->engine_index); - break; - default: - os_log_error(AUTHD_LOG, "Preauthorize returned %d => returning errAuthorizationInternal (engine %lld)", (int)status, engine->engine_index); - status = errAuthorizationInternal; - break; - } - - CFReleaseSafe(rule); - - if (engine->dismissed) { - os_log_error(AUTHD_LOG, "Engine dismissed (engine %lld)", engine->engine_index); - status = errAuthorizationDenied; - } - - os_log_debug(AUTHD_LOG, "engine %lld: preauthorize result: %d", engine->engine_index, (int)status); - - _cf_set_iterate(engine->credentials, ^bool(CFTypeRef value) { - credential_t cred = (credential_t)value; - // skip all uid credentials when running in least privileged - if (auth_token_least_privileged(engine->auth) && !credential_is_right(cred)) - return true; - - session_t session = auth_token_get_session(engine->auth); - auth_token_set_credential(engine->auth, cred); - if (credential_get_shared(cred)) { - session_set_credential(session, cred); - } - if (credential_is_right(cred)) { - os_log(AUTHD_LOG, "engine %lld: adding least privileged %{public}scredential %{public}s to authorization", engine->engine_index, credential_get_shared(cred) ? "shared " : "", credential_get_name(cred)); - } else { - os_log(AUTHD_LOG, "engine %lld: adding %{public}scredential %{public}s (%i) to authorization", engine->engine_index, credential_get_shared(cred) ? "shared " : "", credential_get_name(cred), credential_get_uid(cred)); - } - return true; - }); - - - if (status == errAuthorizationSuccess && save_password) { - auth_items_set_flags(engine->context, kAuthorizationEnvironmentPassword, kAuthorizationContextFlagExtractable); - } + OSStatus status = errAuthorizationInternal; + + CFMutableDictionaryRef properties = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + require(properties != NULL, done); + require(rightName != NULL, done); - if ((status == errAuthorizationSuccess) || (status == errAuthorizationCanceled)) { - auth_items_t encrypted_items = auth_items_create(); - require_action(encrypted_items != NULL, done, os_log_error(AUTHD_LOG, "Unable to create items (engine %lld)", engine->engine_index)); - auth_items_content_copy_with_flags(encrypted_items, engine->context, kAuthorizationContextFlagExtractable); -#if DEBUG - os_log_debug(AUTHD_LOG, "engine %lld: ********** Dumping preauthorized context for encryption **********", engine->engine_index); - os_log_debug(AUTHD_LOG, "%@", encrypted_items); -#endif - auth_items_encrypt(encrypted_items, auth_token_get_encryption_key(engine->auth)); - auth_items_copy_with_flags(auth_token_get_context(engine->auth), encrypted_items, kAuthorizationContextFlagExtractable); - os_log_debug(AUTHD_LOG, "engine %lld: encrypted preauthorization context data", engine->engine_index); - CFReleaseSafe(encrypted_items); - } + // first check if any of rights uses rule with password-only set to true + // if so, set appropriate hint so SecurityAgent won't use alternate authentication methods like smartcard etc. + authdb_connection_t dbconn = authdb_connection_acquire(server_get_database()); // get db handle + + os_log_debug(AUTHD_LOG, "engine %lld: get right properties %{public}s", engine->engine_index, rightName); + rule_t rule = _find_rule(engine, dbconn, rightName); + + if (rule) { + const char *group = NULL; + bool passwordOnly = _preevaluate_rule(engine, rule, &group); + CFDictionarySetValue(properties, CFSTR(kAuthorizationRuleParameterPasswordOnly), passwordOnly ? kCFBooleanTrue : kCFBooleanFalse); + if (group) { + CFStringRef groupCf = CFStringCreateWithCString(kCFAllocatorDefault, group, kCFStringEncodingUTF8); + if (groupCf) { + CFDictionarySetValue(properties, CFSTR(kAuthorizationRuleParameterGroup), groupCf); + CFRelease(groupCf); + } + } + CFRelease(rule); + status = errAuthorizationSuccess; + } else { + os_log_debug(AUTHD_LOG, "engine %lld: cannot get right properties %{public}s", engine->engine_index, rightName); + status = errAuthorizationInvalidRef; + } + + authdb_connection_release(&dbconn); // release db handle + os_log_debug(AUTHD_LOG, "engine %lld: right properties %@", engine->engine_index, properties); + if (output && status == errAuthorizationSuccess) { + *output = properties; + CFRetain(*output); + } done: - engine->preauthorizing = false; - auth_items_clear(engine->context); - auth_items_clear(engine->sticky_context); - CFDictionaryRemoveAllValues(engine->mechanism_agents); - return status; + CFReleaseSafe(properties); + return status; } OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t environment, AuthorizationFlags flags) @@ -1313,11 +1268,12 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en __block OSStatus status = errAuthorizationSuccess; __block bool save_password = false; __block bool password_only = false; - CFIndex rights_count = auth_rights_get_count(rights); + CFIndex rights_count = 0; ccaudit_t ccaudit = NULL; - require(rights != NULL, done); + rights_count = auth_rights_get_count(rights); + ccaudit = ccaudit_create(engine->proc, engine->auth, AUE_ssauthorize); if (auth_rights_get_count(rights) > 0) { ccaudit_log(ccaudit, "begin evaluation", NULL, 0); @@ -1405,7 +1361,6 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en engine_acquire_sheet_data(engine); _extract_password_from_la(engine); - engine->preauthorizing = true; } engine->dismissed = false; @@ -1422,8 +1377,7 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en os_log_debug(AUTHD_LOG, "engine %lld: checking if rule %{public}s contains password-only item", engine->engine_index, key); rule_t rule = _find_rule(engine, dbconn, key); - - if (rule && _preevaluate_rule(engine, rule)) { + if (rule && _preevaluate_rule(engine, rule, NULL)) { password_only = true; CFReleaseSafe(rule); return false; @@ -1462,6 +1416,7 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en // only need the hints & mechanisms if we are going to show ui if (engine->flags & kAuthorizationFlagInteractionAllowed || engine->flags & kAuthorizationFlagSheet) { + os_log_debug(AUTHD_LOG, "setting hints for UI authorization"); _set_right_hints(engine->hints, key); _set_localization_hints(dbconn, engine->hints, rule); if (!engine->authenticateRule) { @@ -1545,10 +1500,6 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en os_log_debug(AUTHD_LOG, "engine %lld: authorize result: %d", engine->engine_index, (int)status); - if (engine->flags & kAuthorizationFlagSheet) { - engine->preauthorizing = false; - } - if ((engine->flags & kAuthorizationFlagExtendRights) && !(engine->flags & kAuthorizationFlagDestroyRights)) { _cf_set_iterate(engine->credentials, ^bool(CFTypeRef value) { credential_t cred = (credential_t)value; diff --git a/OSX/authd/engine.h b/OSX/authd/engine.h index aec7c296..5ef5ce41 100644 --- a/OSX/authd/engine.h +++ b/OSX/authd/engine.h @@ -17,7 +17,7 @@ AUTH_NONNULL1 AUTH_NONNULL2 OSStatus engine_authorize(engine_t, auth_rights_t rights, auth_items_t environment, AuthorizationFlags); AUTH_NONNULL1 AUTH_NONNULL2 -OSStatus engine_preauthorize(engine_t engine, auth_items_t credentials); +OSStatus engine_get_right_properties(engine_t engine, const char *rightName, CFDictionaryRef *output); AUTH_NONNULL_ALL OSStatus engine_verify_modification(engine_t, rule_t, bool remove, bool force_modify); diff --git a/OSX/authd/main.c b/OSX/authd/main.c index dbdcf436..8f220f3d 100644 --- a/OSX/authd/main.c +++ b/OSX/authd/main.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #if DEBUG @@ -109,9 +109,12 @@ security_auth_peer_event_handler(xpc_connection_t connection, xpc_object_t event } status = errAuthorizationSuccess; break; - case AUTHORIZATION_PREAUTHORIZE_CREDENTIALS: - status = authorization_preauthorize_credentials(conn,event,reply); + case AUTHORIZATION_COPY_RIGHT_PROPERTIES: + status = authorization_copy_right_properties(conn,event,reply); break; + case AUTHORIZATION_COPY_PRELOGIN_USERDB: + status = authorization_copy_prelogin_userdb(conn,event,reply); + break; #if DEBUG case AUTHORIZATION_DEV: server_dev(); diff --git a/OSX/authd/process.c b/OSX/authd/process.c index 4e5b5c16..9affe424 100644 --- a/OSX/authd/process.c +++ b/OSX/authd/process.c @@ -13,6 +13,8 @@ #include #include +#include + AUTHD_DEFINE_LOG struct _process_s { diff --git a/OSX/authd/rule.c b/OSX/authd/rule.c index a706b4d3..b854c1b7 100644 --- a/OSX/authd/rule.c +++ b/OSX/authd/rule.c @@ -175,36 +175,11 @@ rule_create_default() mech = mechanism_create_with_string("builtin:authenticate,privileged", NULL); CFArrayAppendValue(rule->mechanisms, mech); CFReleaseNull(mech); - - mech = mechanism_create_with_string("PKINITMechanism:auth,privileged", NULL); - CFArrayAppendValue(rule->mechanisms, mech); - CFReleaseNull(mech); done: return rule; } -rule_t -rule_create_preauthorization() -{ - rule_t rule = _rule_create(); - require(rule != NULL, done); - - auth_items_set_int64(rule->data, RULE_TYPE, RT_RIGHT); - auth_items_set_string(rule->data, RULE_NAME, "(preauthorization)"); - auth_items_set_int64(rule->data, RULE_CLASS, RC_USER); - auth_items_set_string(rule->data, RULE_GROUP, "admin"); - auth_items_set_int64(rule->data, RULE_TRIES, 1); - auth_items_set_int64(rule->data, RULE_FLAGS, RuleFlagShared | RuleFlagAuthenticateUser | RuleFlagRequireAppleSigned); - - mechanism_t mech = mechanism_create_with_string("builtin:authenticate,privileged", NULL); - CFArrayAppendValue(rule->mechanisms, mech); - CFReleaseNull(mech); - -done: - return rule; -} - rule_t rule_create_with_string(const char * str, authdb_connection_t dbconn) { @@ -1168,6 +1143,9 @@ rule_check_flags(rule_t rule, RuleFlags flags) bool rule_get_shared(rule_t rule) { + if (isInLWOS()) { + return false; + } return rule_check_flags(rule, RuleFlagShared); } diff --git a/OSX/authd/rule.h b/OSX/authd/rule.h index 098087d5..2d9b630e 100644 --- a/OSX/authd/rule.h +++ b/OSX/authd/rule.h @@ -50,9 +50,6 @@ typedef enum { AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED rule_t rule_create_default(void); -AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED -rule_t rule_create_preauthorization(void); - AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL1 AUTH_RETURNS_RETAINED rule_t rule_create_with_string(const char *,authdb_connection_t); diff --git a/OSX/authd/server.c b/OSX/authd/server.c index 728ae6e2..493105f3 100644 --- a/OSX/authd/server.c +++ b/OSX/authd/server.c @@ -15,6 +15,7 @@ #include "engine.h" #include "connection.h" #include "AuthorizationTags.h" +#include "PreloginUserDb.h" #include #include @@ -29,6 +30,8 @@ #include #include +#include + AUTHD_DEFINE_LOG #define MAX_PROCESS_RIGHTS 100 @@ -384,27 +387,26 @@ done: return status; } -static OSStatus _server_preauthorize(connection_t conn, auth_token_t auth, auth_items_t context, engine_t * engine_out) +static OSStatus _server_get_right_properties(connection_t conn, const char *rightName, CFDictionaryRef *properties) { - __block OSStatus status = errAuthorizationDenied; - engine_t engine = NULL; + OSStatus status = errAuthorizationDenied; + auth_token_t auth = NULL; + engine_t engine = NULL; - require_action(conn, done, status = errAuthorizationInternal); + require_action(conn, done, status = errAuthorizationInternal); + + auth = auth_token_create(connection_get_process(conn), false); + require_action(auth, done, status = errAuthorizationInternal); - engine = engine_create(conn, auth); - require_action(engine, done, status = errAuthorizationInternal); + engine = engine_create(conn, auth); + require_action(engine, done, status = errAuthorizationInternal); - status = engine_preauthorize(engine, context); + status = engine_get_right_properties(engine, rightName, properties); done: - if (engine) { - if (engine_out) { - *engine_out = engine; - } else { - CFRelease(engine); - } - } - return status; + CFReleaseSafe(engine); + CFReleaseSafe(auth); + return status; } static OSStatus _server_authorize(connection_t conn, auth_token_t auth, AuthorizationFlags flags, auth_rights_t rights, auth_items_t environment, engine_t * engine_out) @@ -546,28 +548,31 @@ done: // IN: AUTH_XPC_BLOB, AUTH_XPC_DATA // OUT: OSStatus -authorization_preauthorize_credentials(connection_t conn, xpc_object_t message, xpc_object_t reply) +authorization_copy_right_properties(connection_t conn, xpc_object_t message, xpc_object_t reply) { - OSStatus status = errAuthorizationDenied; - engine_t engine = NULL; - - process_t proc = connection_get_process(conn); - - // Passed in args - auth_items_t context = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_DATA)); - - auth_token_t auth = NULL; - status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); - require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "preauthorize_credentials: no auth token")); + OSStatus status = errAuthorizationDenied; + CFDataRef serializedProperties = NULL; + CFDictionaryRef properties = NULL; + + // Passed in args + const char *right = xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME); + os_log_debug(AUTHD_LOG, "server: right %s", right); - status = _server_preauthorize(conn, auth, context, &engine); - require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "preauthorize_credentials: authorization failed")); + require_action(right != NULL, done, status = errAuthorizationInvalidPointer); + status = _server_get_right_properties(conn, right, &properties); + require_noerr(status, done); + + if (properties) { + serializedProperties = CFPropertyListCreateData(kCFAllocatorDefault, properties, kCFPropertyListBinaryFormat_v1_0, 0, NULL); + if (serializedProperties) { + xpc_dictionary_set_data(reply, AUTH_XPC_OUT_ITEMS, CFDataGetBytePtr(serializedProperties), CFDataGetLength(serializedProperties)); + } + } + done: - CFReleaseSafe(context); - CFReleaseSafe(auth); - CFReleaseSafe(engine); - + CFReleaseSafe(serializedProperties); + CFReleaseSafe(properties); return status; } @@ -1175,3 +1180,29 @@ server_dev() { // CFReleaseSafe(items); } +// IN: AUTH_XPC_TAG, AUTH_XPC_FLAGS +// OUT: AUTH_XPC_DATA +OSStatus +authorization_copy_prelogin_userdb(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + OSStatus status = errAuthorizationDenied; + xpc_object_t xpcarr = NULL; + CFArrayRef cfarray = NULL; + + const char *uuid = xpc_dictionary_get_string(message, AUTH_XPC_TAG); + UInt32 flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS); + + status = preloginudb_copy_userdb(uuid, flags, &cfarray); + xpc_dictionary_set_int64(reply, AUTH_XPC_STATUS, status); + require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "authorization_copy_prelogin_userdb: database failed")); + + xpcarr = _CFXPCCreateXPCObjectFromCFObject(cfarray); + require(xpcarr != NULL, done); + xpc_dictionary_set_value(reply, AUTH_XPC_DATA, xpcarr); + +done: + CFReleaseSafe(cfarray); + xpc_release_safe(xpcarr); + + return status; +} diff --git a/OSX/authd/server.h b/OSX/authd/server.h index 7889bb32..5fe99d9a 100644 --- a/OSX/authd/server.h +++ b/OSX/authd/server.h @@ -47,7 +47,7 @@ AUTH_NONNULL_ALL OSStatus authorization_free(connection_t,xpc_object_t,xpc_object_t); AUTH_NONNULL_ALL -OSStatus authorization_preauthorize_credentials(connection_t, xpc_object_t, xpc_object_t); +OSStatus authorization_copy_right_properties(connection_t, xpc_object_t, xpc_object_t); AUTH_NONNULL_ALL OSStatus authorization_copy_rights(connection_t,xpc_object_t,xpc_object_t); @@ -76,6 +76,9 @@ OSStatus authorization_right_remove(connection_t,xpc_object_t,xpc_object_t); AUTH_NONNULL_ALL OSStatus session_set_user_preferences(connection_t,xpc_object_t,xpc_object_t); +AUTH_NONNULL_ALL +OSStatus authorization_copy_prelogin_userdb(connection_t,xpc_object_t,xpc_object_t); + #if defined(__cplusplus) } #endif diff --git a/OSX/authd/session.c b/OSX/authd/session.c index 83d548e8..0df2882e 100644 --- a/OSX/authd/session.c +++ b/OSX/authd/session.c @@ -6,6 +6,8 @@ #include #include +#include + AUTHD_DEFINE_LOG struct _session_s { diff --git a/OSX/authd/tests/authdtestlist.h b/OSX/authd/tests/authdtestlist.h index 1987df61..befca8f5 100644 --- a/OSX/authd/tests/authdtestlist.h +++ b/OSX/authd/tests/authdtestlist.h @@ -4,3 +4,4 @@ ONE_TEST(authd_01_authorizationdb) ONE_TEST(authd_02_basicauthorization) ONE_TEST(authd_04_executewithprivileges) +ONE_TEST(authd_05_rightproperties) diff --git a/OSX/authd/tests/authdtests.m b/OSX/authd/tests/authdtests.m index c6c45180..99bb8eac 100644 --- a/OSX/authd/tests/authdtests.m +++ b/OSX/authd/tests/authdtests.m @@ -4,6 +4,7 @@ // #import +#import #import #import #import @@ -282,3 +283,42 @@ int authd_04_executewithprivileges(int argc, char *const *argv) AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); return 0; } + +int authd_05_rightproperties(int argc, char *const *argv) +{ + plan_tests(5); + + NSDictionary *properties; + CFDictionaryRef cfProperties; + NSString *group; + NSNumber *passwordOnly; + + OSStatus status = AuthorizationCopyRightProperties("system.csfde.requestpassword", &cfProperties); + properties = CFBridgingRelease(cfProperties); + if (status != errAuthorizationSuccess) { + fail("AuthorizationCopyRightProperties failed with %d", (int)status); + goto done; + } + + pass("AuthorizationCopyRightProperties call succeess"); + passwordOnly = properties[@(kAuthorizationRuleParameterPasswordOnly)]; + ok(passwordOnly.boolValue, "Returned system.csfde.requestpassword as password only right"); + group = properties[@(kAuthorizationRuleParameterGroup)]; + ok([group isEqualToString:@"admin"], "Returned admin as a required group for system.csfde.requestpassword"); + + status = AuthorizationCopyRightProperties("com.apple.Safari.allow-unsigned-app-extensions", &cfProperties); + properties = CFBridgingRelease(cfProperties); + if (status != errAuthorizationSuccess) { + fail("AuthorizationCopyRightProperties failed with %d", (int)status); + goto done; + } + group = properties[@(kAuthorizationRuleParameterGroup)]; + passwordOnly = properties[@(kAuthorizationRuleParameterPasswordOnly)]; + ok(group.length == 0 && passwordOnly.boolValue == NO, "Returned safari right as non-password only, no specific group"); + + status = AuthorizationCopyRightProperties("non-existing-right", &cfProperties); + ok(status == errAuthorizationSuccess, "Returned success for default for unknown right: %d", (int)status); + +done: + return 0; +} diff --git a/OSX/config/lib.xcconfig b/OSX/config/lib.xcconfig index 7c298b95..81c1da20 100644 --- a/OSX/config/lib.xcconfig +++ b/OSX/config/lib.xcconfig @@ -14,7 +14,7 @@ SKIP_INSTALL = YES ALWAYS_SEARCH_USER_PATHS = NO -GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_C_LANGUAGE_STANDARD = gnu2x GCC_TREAT_WARNINGS_AS_ERRORS = YES; diff --git a/OSX/config/security_framework_macos.xcconfig b/OSX/config/security_framework_macos.xcconfig index f341fbd7..3ee4720d 100644 --- a/OSX/config/security_framework_macos.xcconfig +++ b/OSX/config/security_framework_macos.xcconfig @@ -12,16 +12,23 @@ DYLIB_CURRENT_VERSION = $(CURRENT_PROJECT_VERSION) MODULEMAP_FILE = Modules/Security.macOS.modulemap DEFINES_MODULE = YES -EXPORTED_SYMBOLS_FILE = $(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).exp +EXPORTED_SYMBOLS_FILE = $(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).$(CURRENT_ARCH).exp ORDER_FILE = OSX/lib/Security.order INFOPLIST_FILE = OSX/lib/Info-Security.plist INSTALL_PATH = $(SYSTEM_LIBRARY_DIR)/Frameworks ASAN_EXTRA_LDFLAGS_YES = -Wl,-no_warn_inits -ASAN_EXTRA_LDFLAGS_NO = -Wl,-no_inits +ASAN_EXTRA_LDFLAGS_NO = ASAN_EXTRA_LDFLAGS_ = $(ASAN_EXTRA_LDFLAGS_NO) -OTHER_LDFLAGS = -laks -lCrashReporterClient -Wl,-upward_framework,Foundation $(ASAN_EXTRA_LDFLAGS_$(ENABLE_ADDRESS_SANITIZER)) +TSAN_EXTRA_LDFLAGS_YES = -Wl,-no_warn_inits +TSAN_EXTRA_LDFLAGS_NO = +TSAN_EXTRA_LDFLAGS_ = $(TSAN_EXTRA_LDFLAGS_NO) + +// order here matters, so later more specific options override earlier. +NOINIT_LDFLAGS = -Wl,-no_inits $(ASAN_EXTRA_LDFLAGS_$(ENABLE_ADDRESS_SANITIZER)) $(TSAN_EXTRA_LDFLAGS_$(ENABLE_THREAD_SANITIZER)) + +OTHER_LDFLAGS = -laks -lCrashReporterClient -Wl,-upward_framework,Foundation $(NOINIT_LDFLAGS) SECTORDER_FLAGS = -order_file_statistics APPLY_RULES_IN_COPY_FILES = NO diff --git a/OSX/config/security_macos.xcconfig b/OSX/config/security_macos.xcconfig index 58ed08ab..bdd02709 100644 --- a/OSX/config/security_macos.xcconfig +++ b/OSX/config/security_macos.xcconfig @@ -11,7 +11,7 @@ LIBRARY_SEARCH_PATHS = $(inherited) /usr/lib/system STRIP_INSTALLED_PRODUCT = YES DEPLOYMENT_POSTPROCESSING = NO -GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_C_LANGUAGE_STANDARD = gnu2x SUPPORTED_PLATFORMS = macosx GCC_TREAT_WARNINGS_AS_ERRORS = YES diff --git a/OSX/include/security_asn1 b/OSX/include/security_asn1 deleted file mode 120000 index 09ef0802..00000000 --- a/OSX/include/security_asn1 +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_asn1/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_client b/OSX/include/security_cdsa_client deleted file mode 120000 index 9737c610..00000000 --- a/OSX/include/security_cdsa_client +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_cdsa_client/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_plugin b/OSX/include/security_cdsa_plugin deleted file mode 120000 index 2be156f8..00000000 --- a/OSX/include/security_cdsa_plugin +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_cdsa_plugin/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_utilities b/OSX/include/security_cdsa_utilities deleted file mode 120000 index 2634481d..00000000 --- a/OSX/include/security_cdsa_utilities +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_cdsa_utilities/lib \ No newline at end of file diff --git a/OSX/include/security_cdsa_utils b/OSX/include/security_cdsa_utils deleted file mode 120000 index f3e5247e..00000000 --- a/OSX/include/security_cdsa_utils +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_cdsa_utils/lib \ No newline at end of file diff --git a/OSX/include/security_codesigning b/OSX/include/security_codesigning deleted file mode 120000 index 7c67092b..00000000 --- a/OSX/include/security_codesigning +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_codesigning/lib \ No newline at end of file diff --git a/OSX/include/security_comcryption b/OSX/include/security_comcryption deleted file mode 120000 index cbcdf214..00000000 --- a/OSX/include/security_comcryption +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_comcryption/lib \ No newline at end of file diff --git a/OSX/include/security_cryptkit b/OSX/include/security_cryptkit deleted file mode 120000 index 609dcc3b..00000000 --- a/OSX/include/security_cryptkit +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_cryptkit/lib \ No newline at end of file diff --git a/OSX/include/security_filedb b/OSX/include/security_filedb deleted file mode 120000 index 99185cdc..00000000 --- a/OSX/include/security_filedb +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_filedb/lib \ No newline at end of file diff --git a/OSX/include/security_keychain b/OSX/include/security_keychain deleted file mode 120000 index aac53b6d..00000000 --- a/OSX/include/security_keychain +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_keychain/lib \ No newline at end of file diff --git a/OSX/include/security_ocspd b/OSX/include/security_ocspd deleted file mode 120000 index 449ea98b..00000000 --- a/OSX/include/security_ocspd +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_ocspd/common \ No newline at end of file diff --git a/OSX/include/security_pkcs12 b/OSX/include/security_pkcs12 deleted file mode 120000 index 8fdcb01e..00000000 --- a/OSX/include/security_pkcs12 +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_pkcs12/lib \ No newline at end of file diff --git a/OSX/include/security_smime b/OSX/include/security_smime deleted file mode 120000 index e1a40bad..00000000 --- a/OSX/include/security_smime +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_smime/lib \ No newline at end of file diff --git a/OSX/include/security_utilities b/OSX/include/security_utilities deleted file mode 120000 index 4d363d11..00000000 --- a/OSX/include/security_utilities +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_utilities/lib \ No newline at end of file diff --git a/OSX/include/securityd_client b/OSX/include/securityd_client deleted file mode 120000 index 2edb676a..00000000 --- a/OSX/include/securityd_client +++ /dev/null @@ -1 +0,0 @@ -./libsecurityd/lib \ No newline at end of file diff --git a/OSX/lib/en.lproj/InfoPlist.strings b/OSX/lib/en.lproj/InfoPlist.strings index b99cba584dfa7ac4c4f7c3e61d7f51641925b2a3..79058ccc58581eb0f607fa6da8625595f9418c54 100644 GIT binary patch delta 25 fcmZ3)w1|o6|G$aMFF1u2j2H|UfOz5;Jw^rqZ}bOv delta 24 ecmZ3)w1|oM-+zXQOfNWf8H^YVfY5Z}XFUL9E(db} diff --git a/OSX/lib/en.lproj/authorization.buttons.strings b/OSX/lib/en.lproj/authorization.buttons.strings index 1871c226..b7c044ed 100644 --- a/OSX/lib/en.lproj/authorization.buttons.strings +++ b/OSX/lib/en.lproj/authorization.buttons.strings @@ -143,3 +143,7 @@ "com.apple.security.sudo" = "Allow"; "com.apple.configurationprofiles.userenrollment.install" = "Enroll"; + +"com.apple.configurationprofiles.deviceenrollment.install" = "Enroll"; + +"com.apple.configurationprofiles.deviceenrollment.uninstall" = "Unenroll"; diff --git a/OSX/lib/en.lproj/authorization.dfr.prompts.strings b/OSX/lib/en.lproj/authorization.dfr.prompts.strings index e54e35f7..d434c80d 100644 --- a/OSX/lib/en.lproj/authorization.dfr.prompts.strings +++ b/OSX/lib/en.lproj/authorization.dfr.prompts.strings @@ -1,6 +1,6 @@ "system.preferences.accounts" = "Touch ID to Unlock Users & Groups Preferences."; -"com.apple.SoftwareUpdate.scan" = "Touch ID to Check for New Apple-provided Software."; +"com.apple.SoftwareUpdate.scan" = "Touch ID to Check for New Apple Software."; "system.preferences.datetime" = "Touch ID to Unlock the Date & Time Preferences."; @@ -48,9 +48,9 @@ "system.preferences.energysaver" = "Touch ID to Unlock the Energy Saver Preferences."; -"system.install.apple-software" = "Touch ID to Install Apple-provided Software."; +"system.install.apple-software" = "Touch ID to Install Apple Software."; -"system.install.apple-software.standard-user" = "Touch ID to Install Apple-provided software."; +"system.install.apple-software.standard-user" = "Touch ID to Install Apple software."; "com.apple.security.assessment.update" = "Touch ID to Install an App from an Unidentified Developer."; diff --git a/OSX/lib/en.lproj/authorization.prompts.strings b/OSX/lib/en.lproj/authorization.prompts.strings index 43870767..568c080a 100644 --- a/OSX/lib/en.lproj/authorization.prompts.strings +++ b/OSX/lib/en.lproj/authorization.prompts.strings @@ -1,6 +1,6 @@ "system.preferences.accounts" = "__APPNAME__ is trying to unlock Users & Groups preferences."; -"com.apple.SoftwareUpdate.scan" = "__APPNAME__ is trying to check for new Apple-provided software."; +"com.apple.SoftwareUpdate.scan" = "__APPNAME__ is trying to check for new Apple software."; "system.preferences.datetime" = "__APPNAME__ is trying to unlock the Date & Time preferences."; @@ -48,9 +48,9 @@ "system.preferences.energysaver" = "__APPNAME__ is trying to unlock the Energy Saver preferences."; -"system.install.apple-software" = "__APPNAME__ is trying to install Apple-provided software."; +"system.install.apple-software" = "__APPNAME__ is trying to install Apple software."; -"system.install.apple-software.standard-user" = "__APPNAME__ is trying to install Apple-provided software."; +"system.install.apple-software.standard-user" = "__APPNAME__ is trying to install Apple software."; "com.apple.security.assessment.update" = "You are overriding your security preferences to install an app from an unidentified developer."; @@ -175,3 +175,7 @@ "com.apple.system-extensions.admin" = "__APPNAME__ is trying to modify a System Extension."; "com.apple.tcc.util.admin" = "__APPNAME__ is trying to modify your Security & Privacy settings."; + +"com.apple.configurationprofiles.deviceenrollment.install" = "__APPNAME__ is trying to enroll you in a remote management (MDM) service."; + +"com.apple.configurationprofiles.deviceenrollment.uninstall" = "__APPNAME__ is trying to unenroll you from a remote management (MDM) service."; diff --git a/OSX/lib/framework.sb b/OSX/lib/framework.sb deleted file mode 100644 index e37bf7c4..00000000 --- a/OSX/lib/framework.sb +++ /dev/null @@ -1,11 +0,0 @@ -;; allow clients to communicate with secd -(allow mach-lookup (global-name "com.apple.secd")) -;; allow clients to communicate with coreauthd -(allow mach-lookup (global-name "com.apple.CoreAuthentication.daemon")) -(allow mach-lookup (global-name "com.apple.CoreAuthentication.agent")) -;; allow clients to communicate with ctkd -(allow mach-lookup (global-name "com.apple.ctkd.token-client")) - -;; On internal builds, allow clients to read the AMFITrustedKeys NVRAM variable -(with-filter (system-attribute apple-internal) - (allow nvram-get (nvram-variable "AMFITrustedKeys"))) diff --git a/OSX/libsecurity_apple_csp/lib/DH_keys.cpp b/OSX/libsecurity_apple_csp/lib/DH_keys.cpp index 6060dfe5..d5dc2e4e 100644 --- a/OSX/libsecurity_apple_csp/lib/DH_keys.cpp +++ b/OSX/libsecurity_apple_csp/lib/DH_keys.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_apple_csp/lib/DH_utils.cpp b/OSX/libsecurity_apple_csp/lib/DH_utils.cpp index aec4d18d..33232c7a 100644 --- a/OSX/libsecurity_apple_csp/lib/DH_utils.cpp +++ b/OSX/libsecurity_apple_csp/lib/DH_utils.cpp @@ -121,7 +121,7 @@ DH *rawCssmKeyToDh( // someone else's key (should never happen) CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); } - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); /* validate and figure out what we're dealing with */ switch(hdr->KeyClass) { case CSSM_KEYCLASS_PUBLIC_KEY: diff --git a/OSX/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp b/OSX/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp index 080d555d..d9c08703 100644 --- a/OSX/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp @@ -106,7 +106,7 @@ void CryptKit::FEEDContext::init( mAllocdPrivKey); } else { - assert(opStarted()); + assert(opStarted()); } if(mPubKey == NULL) { assert(!opStarted()); @@ -118,7 +118,7 @@ void CryptKit::FEEDContext::init( mAllocdPubKey); } else { - assert(opStarted()); + assert(opStarted()); } /* validate context - no other attributes allowed */ diff --git a/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp b/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp index 8c317b80..4966db8d 100644 --- a/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp @@ -168,7 +168,7 @@ feePubKey CryptKit::rawCssmKeyToFee( const CssmKey &cssmKey) { const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); switch(hdr->AlgorithmId) { case CSSM_ALGID_FEE: diff --git a/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp b/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp index e906bdf8..1dc36ae7 100644 --- a/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp @@ -31,7 +31,7 @@ #include #include "AppleCSPSession.h" #include "AppleCSPUtils.h" -#include +#include #include #define feeKeyDebug(args...) secinfo("feeKey", ## args) diff --git a/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp b/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp index 413b6cf1..4175a0cb 100644 --- a/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #define feeSigObjDebug(args...) secinfo("feeSig", ##args) diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp b/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp index e73c092f..5974f788 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include "RSA_DSA_utils.h" #include diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp b/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp index ae818296..fdcbf96b 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp @@ -23,7 +23,7 @@ #include "RSA_DSA_signature.h" #include "RSA_DSA_utils.h" #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp b/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp index 8fb48fd1..7b8f894e 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp @@ -114,7 +114,7 @@ RSAKeySizes::RSAKeySizes() if (d->dict()) { - auto_ptrapd(d); + unique_ptrapd(d); rsaLookupVal(*apd, kRSAMaxKeySizePref, maxKeySize); rsaLookupVal(*apd, kRSAMaxPublicExponentPref, maxPubExponentSize); } @@ -223,7 +223,7 @@ RSA *rawCssmKeyToRsa( bool isPub; bool isOaep = false; - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); switch(hdr->AlgorithmId) { case CSSM_ALGID_RSA: @@ -504,7 +504,7 @@ DSA *rawCssmKeyToDsa( const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; bool isPub; - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); + assert(hdr->BlobType == CSSM_KEYBLOB_RAW); if(hdr->AlgorithmId != CSSM_ALGID_DSA) { // someone else's key (should never happen) diff --git a/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp b/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp index d0983f5b..2d394aca 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp @@ -85,7 +85,7 @@ void RSA_CryptContext::init(const Context &context, bool encoding /*= true*/) } } else { - assert(opStarted()); + assert(opStarted()); } unsigned cipherBlockSize = RSA_size(mRsaKey); diff --git a/OSX/libsecurity_apple_csp/lib/pkcs12Derive.cpp b/OSX/libsecurity_apple_csp/lib/pkcs12Derive.cpp index 6e0b4279..dce62a69 100644 --- a/OSX/libsecurity_apple_csp/lib/pkcs12Derive.cpp +++ b/OSX/libsecurity_apple_csp/lib/pkcs12Derive.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/OSX/libsecurity_apple_csp/lib/pkcs8.cpp b/OSX/libsecurity_apple_csp/lib/pkcs8.cpp index 6d1a16c7..d68c3170 100644 --- a/OSX/libsecurity_apple_csp/lib/pkcs8.cpp +++ b/OSX/libsecurity_apple_csp/lib/pkcs8.cpp @@ -88,7 +88,7 @@ void AppleCSPSession::pkcs8InferKeyHeader( */ CSSM_KEY_SIZE keySize; try { - auto_ptr provider(infoProvider(key)); + unique_ptr provider(infoProvider(key)); provider->QueryKeySizeInBits(keySize); } catch(const CssmError &cerror) { @@ -103,7 +103,7 @@ void AppleCSPSession::pkcs8InferKeyHeader( (hdr.AlgorithmId == CSSM_ALGID_DSA)) { hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186; try { - auto_ptr provider(infoProvider(key)); + unique_ptr provider(infoProvider(key)); provider->QueryKeySizeInBits(keySize); } catch(...) { @@ -198,7 +198,7 @@ void AppleCSPSession::opensslInferKeyHeader( /* now figure out the key size by finding a provider for this key */ CSSM_KEY_SIZE keySize; try { - auto_ptr provider(infoProvider(key)); + unique_ptr provider(infoProvider(key)); provider->QueryKeySizeInBits(keySize); } catch(...) { diff --git a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_asm.c b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_asm.c index b956a092..eb23d658 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_asm.c +++ b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_asm.c @@ -80,7 +80,7 @@ #endif #include -#include +#include #include "cryptlib.h" #include "bn_lcl.h" diff --git a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c index c896a752..c769764d 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c +++ b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c @@ -78,7 +78,7 @@ #endif #include -#include +#include #include "cryptlib.h" #include diff --git a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_exp.c b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_exp.c index 81173237..6c67c1b9 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_exp.c +++ b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_exp.c @@ -116,7 +116,7 @@ #ifdef ATALLA # include # include -# include +# include # include #endif diff --git a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h index af312c7f..801b6fe2 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h +++ b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h @@ -225,13 +225,8 @@ extern "C" { #define Lw(t) (((BN_ULONG)(t))&BN_MASK2) #define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2) -/* This is used for internal error checking and is not normally used */ -#ifdef BN_DEBUG -# include -# define bn_check_top(a) assert ((a)->top >= 0 && (a)->top <= (a)->dmax); -#else -# define bn_check_top(a) -#endif +#include +#define bn_check_top(a) assert((a)->top >= 0 && (a)->top <= (a)->max); /* This macro is to add extra stuff for development checking */ #ifdef BN_DEBUG diff --git a/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp b/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp index cd652271..cb01bce2 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp +++ b/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp @@ -35,7 +35,7 @@ #include #include -#include +#include #define sslAsn1Debug(args...) secinfo("sslAsn1", ##args) diff --git a/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c b/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c index 55029916..1264b623 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c +++ b/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c @@ -155,8 +155,10 @@ int RSA_verify_ASN1_OCTET_STRING(int dtype, unsigned char *m, ret=1; err: if (sig != NULL) M_ASN1_OCTET_STRING_free(sig); - memset(s,0,(unsigned int)siglen); - Free(s); + if(s) { + memset(s,0,(unsigned int)siglen); + Free(s); + } return(ret); - } +} diff --git a/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c b/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c index fff3be5f..323dc930 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c +++ b/OSX/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c @@ -232,8 +232,10 @@ int RSA_verify(int dtype, unsigned char *m, unsigned int m_len, } err: if (sig != NULL) X509_SIG_free(sig); - memset(s,0,(unsigned int)siglen); - Free(s); + if(s) { + memset(s,0,(unsigned int)siglen); + Free(s); + } return(ret); - } +} diff --git a/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp b/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp index d079b3f0..48c60120 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp @@ -357,9 +357,9 @@ SSCSPSession::FreeKey(const AccessCredentials *accessCred, // that! // Find the key in the map. Tell tell the key to free itself - // (when the auto_ptr deletes the key it removes itself from the map). + // (when the unique_ptr deletes the key it removes itself from the map). secinfo("freeKey", "CSPDL FreeKey"); - auto_ptr ssKey(&mSSCSPDLSession.find(ioKey)); + unique_ptr ssKey(&mSSCSPDLSession.find(ioKey)); ssKey->free(accessCred, ioKey, deleteKey); } else diff --git a/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp b/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp index b0523932..4f23d986 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp @@ -488,7 +488,7 @@ SSCryptContext::final(CssmData &out) if(!inSize) return; const CssmData in(const_cast(mNullDigest.digestPtr()), inSize); - IFDEBUG(size_t origOutSize = out.length()); + size_t origOutSize = out.length(); if (encoding()) { clientSession().encrypt(*mContext, mKeyHandle, in, out); } diff --git a/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp b/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp index aa198e08..de2e019b 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp +++ b/OSX/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp @@ -335,7 +335,7 @@ bool getFieldSubjectKeyId( /* if this fails, we're out of sync with nssExtenInfo[] in * CLFieldsCommon.cpp */ - assert(nssObj != NULL); + assert(nssObj != NULL); clAllocCopyData(alloc, *nssObj, *cdsaObj); getFieldExtenCommon(cdsaObj, *decodedExt, fieldValue); return true; diff --git a/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp b/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp index d94b373d..3ebe668b 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp +++ b/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp @@ -37,7 +37,7 @@ /* * Avoid inlining this for debuggability */ -void *ArenaAllocator::malloc(size_t len) throw(std::bad_alloc) +void *ArenaAllocator::malloc(size_t len) { try { return mCoder.malloc(len); @@ -48,11 +48,11 @@ void *ArenaAllocator::malloc(size_t len) throw(std::bad_alloc) } /* intentionally not implemented, should never be called */ -void ArenaAllocator::free(void *p) throw() +void ArenaAllocator::free(void *p) _NOEXCEPT { } -void *ArenaAllocator::realloc(void *p, size_t len) throw(std::bad_alloc) +void *ArenaAllocator::realloc(void *p, size_t len) { throw std::bad_alloc(); } diff --git a/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.h b/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.h index e62cffac..ebca2ebd 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.h +++ b/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.h @@ -42,9 +42,9 @@ public: ArenaAllocator(SecNssCoder &coder) : mCoder(coder) { } ~ArenaAllocator() { } - void *malloc(size_t) throw(std::bad_alloc) ; - void free(void *) throw() ; - void *realloc(void *, size_t) throw(std::bad_alloc); + void *malloc(size_t); + void free(void *) _NOEXCEPT ; + void *realloc(void *, size_t); private: SecNssCoder &mCoder; }; diff --git a/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp b/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp index 460af75a..e5554ff0 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp index 0ad65a53..3bf095dc 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp @@ -30,154 +30,6 @@ #include #include -/* - * This is a temporary hack to allow verification of PKINIT server certs - * which are self-signed and not in the system anchors list. If the self- - * signed cert is in a magic keychain (whose location is not published), - * we'll allow it as if it were indeed a full-fledged anchor cert. - */ -#define TP_PKINIT_SERVER_HACK 1 -#if TP_PKINIT_SERVER_HACK - -#include -#include -#include -#include -#include -#include - -#define CFRELEASE(cf) if(cf) { CFRelease(cf); } - -/* - * Returns true if we are to allow/trust the specified - * cert as a PKINIT-only anchor. - */ -static bool tpCheckPkinitServerCert( - TPCertGroup &certGroup) -{ - /* - * Basic requirement: exactly one cert, self-signed. - * The numCerts == 1 requirement might change... - */ - unsigned numCerts = certGroup.numCerts(); - if(numCerts != 1) { - tpDebug("tpCheckPkinitServerCert: too many certs"); - return false; - } - /* end of chain... */ - TPCertInfo *theCert = certGroup.certAtIndex(numCerts - 1); - if(!theCert->isSelfSigned()) { - tpDebug("tpCheckPkinitServerCert: 1 cert, not self-signed"); - return false; - } - const CSSM_DATA *subjectName = theCert->subjectName(); - - /* - * Open the magic keychain. - * We're going up and over the Sec layer here, not generally - * kosher, but this is a hack. - */ - OSStatus ortn; - SecKeychainRef kcRef = NULL; - string fullPathName; - const char *homeDir = getenv("HOME"); - if (homeDir == NULL) - { - // If $HOME is unset get the current user's home directory - // from the passwd file. - uid_t uid = geteuid(); - if (!uid) uid = getuid(); - struct passwd *pw = getpwuid(uid); - if (!pw) { - return false; - } - homeDir = pw->pw_dir; - } - fullPathName = homeDir; - fullPathName += "/Library/Application Support/PKINIT/TrustedServers.keychain"; - ortn = SecKeychainOpen(fullPathName.c_str(), &kcRef); - if(ortn) { - tpDebug("tpCheckPkinitServerCert: keychain not found (1)"); - return false; - } - /* subsequent errors to errOut: */ - - bool ourRtn = false; - SecKeychainStatus kcStatus; - CSSM_DATA_PTR subjSerial = NULL; - CSSM_RETURN crtn; - SecKeychainSearchRef srchRef = NULL; - SecKeychainAttributeList attrList; - SecKeychainAttribute attrs[2]; - SecKeychainItemRef foundItem = NULL; - - ortn = SecKeychainGetStatus(kcRef, &kcStatus); - if(ortn) { - tpDebug("tpCheckPkinitServerCert: keychain not found (2)"); - goto errOut; - } - - /* - * We already have this cert's normalized name; get its - * serial number. - */ - crtn = theCert->fetchField(&CSSMOID_X509V1SerialNumber, &subjSerial); - if(crtn) { - /* should never happen */ - tpDebug("tpCheckPkinitServerCert: error fetching serial number"); - goto errOut; - } - - attrs[0].tag = kSecSubjectItemAttr; - attrs[0].length = (UInt32)subjectName->Length; - attrs[0].data = subjectName->Data; - attrs[1].tag = kSecSerialNumberItemAttr; - attrs[1].length = (UInt32)subjSerial->Length; - attrs[1].data = subjSerial->Data; - attrList.count = 2; - attrList.attr = attrs; - - ortn = SecKeychainSearchCreateFromAttributes(kcRef, - kSecCertificateItemClass, - &attrList, - &srchRef); - if(ortn) { - tpDebug("tpCheckPkinitServerCert: search failure"); - goto errOut; - } - for(;;) { - ortn = SecKeychainSearchCopyNext(srchRef, &foundItem); - if(ortn) { - tpDebug("tpCheckPkinitServerCert: end search"); - break; - } - - /* found a matching cert; do byte-for-byte compare */ - CSSM_DATA certData; - ortn = SecCertificateGetData((SecCertificateRef)foundItem, &certData); - if(ortn) { - tpDebug("tpCheckPkinitServerCert: SecCertificateGetData failure"); - continue; - } - if(tpCompareCssmData(&certData, theCert->itemData())){ - tpDebug("tpCheckPkinitServerCert: FOUND CERT"); - ourRtn = true; - break; - } - tpDebug("tpCheckPkinitServerCert: skipping matching cert"); - CFRelease(foundItem); - foundItem = NULL; - } -errOut: - CFRELEASE(kcRef); - CFRELEASE(srchRef); - CFRELEASE(foundItem); - if(subjSerial != NULL) { - theCert->freeField(&CSSMOID_X509V1SerialNumber, subjSerial); - } - return ourRtn; -} -#endif /* TP_PKINIT_SERVER_HACK */ /*----------------------------------------------------------------------------- * CertGroupConstruct @@ -829,16 +681,6 @@ void AppleTPSession::CertGroupVerify(CSSM_CL_HANDLE clHand, if(policyAbort) { break; } - #if TP_PKINIT_SERVER_HACK - if(tpPolicy == kTP_PKINIT_Server) { - /* possible override of "root not in anchors" */ - if(constructReturn == CSSMERR_TP_INVALID_ANCHOR_CERT) { - if(tpCheckPkinitServerCert(outCertGroup)) { - constructReturn = CSSM_OK; - } - } - } - #endif /* TP_PKINIT_SERVER_HACK */ } /* diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp index 28e9e179..2eb31d08 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #define tpCredDebug(args...) secinfo("tpCred", ## args) diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp index 5ac0ef4f..786e2f8a 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include /* * Set this flag nonzero to turn off this cache module. Generally used to debug diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp index 17c152f8..24a24e2e 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpTime.c b/OSX/libsecurity_apple_x509_tp/lib/tpTime.c index 058cab00..b0983af0 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpTime.c +++ b/OSX/libsecurity_apple_x509_tp/lib/tpTime.c @@ -28,6 +28,8 @@ #include #include +#include + /* * Given a string containing either a UTC-style or "generalized time" * time string, convert to a CFDateRef. Returns nonzero on diff --git a/OSX/libsecurity_asn1/lib/SecNssCoder.cpp b/OSX/libsecurity_asn1/lib/SecNssCoder.cpp index 067fb8d8..ef321524 100644 --- a/OSX/libsecurity_asn1/lib/SecNssCoder.cpp +++ b/OSX/libsecurity_asn1/lib/SecNssCoder.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #ifdef NDEBUG #define THROW_ENABLE 1 diff --git a/OSX/libsecurity_asn1/lib/X509Templates.c b/OSX/libsecurity_asn1/lib/X509Templates.c index 93dda3e7..302445c5 100644 --- a/OSX/libsecurity_asn1/lib/X509Templates.c +++ b/OSX/libsecurity_asn1/lib/X509Templates.c @@ -26,7 +26,6 @@ #include "SecAsn1Templates.h" #include "X509Templates.h" #include "keyTemplates.h" -#include #include /* diff --git a/OSX/libsecurity_asn1/lib/nameTemplates.c b/OSX/libsecurity_asn1/lib/nameTemplates.c index 84ce8b34..370512d9 100644 --- a/OSX/libsecurity_asn1/lib/nameTemplates.c +++ b/OSX/libsecurity_asn1/lib/nameTemplates.c @@ -28,7 +28,7 @@ #include "X509Templates.h" #include "keyTemplates.h" #include -#include +#include typedef struct { SecAsn1Oid typeId; diff --git a/OSX/libsecurity_asn1/lib/ocspTemplates.c b/OSX/libsecurity_asn1/lib/ocspTemplates.c index 0dcbf947..8721457f 100644 --- a/OSX/libsecurity_asn1/lib/ocspTemplates.c +++ b/OSX/libsecurity_asn1/lib/ocspTemplates.c @@ -27,7 +27,6 @@ #include "keyTemplates.h" /* for kSecAsn1AlgorithmIDTemplate */ #include "SecAsn1Templates.h" #include -#include // MARK: ----- OCSP Request ----- diff --git a/OSX/libsecurity_asn1/lib/plarena.c b/OSX/libsecurity_asn1/lib/plarena.c index 48c69b3e..b072da1e 100644 --- a/OSX/libsecurity_asn1/lib/plarena.c +++ b/OSX/libsecurity_asn1/lib/plarena.c @@ -300,8 +300,9 @@ static void FreeArenaList(PLArenaPool *pool, PLArena *head, PRBool reallyFree) ap = &head->next; a = *ap; - if (!a) + if (!a) { return; + } do { *ap = a->next; diff --git a/OSX/libsecurity_asn1/lib/prlog.h b/OSX/libsecurity_asn1/lib/prlog.h index c0b3b841..9256da95 100644 --- a/OSX/libsecurity_asn1/lib/prlog.h +++ b/OSX/libsecurity_asn1/lib/prlog.h @@ -236,7 +236,7 @@ NSPR_API(void) PR_LogFlush(void); #ifdef __APPLE__ -#include +#include #define PR_ASSERT(_exp) assert(_exp) #define PR_NOT_REACHED(_reas) assert(0) @@ -250,10 +250,19 @@ NSPR_API(void) PR_Assert(const char *s, const char *file, PRIntn ln); PR_Assert(_reasonStr,__FILE__,__LINE__) #endif -#else +#else /* defined(DEBUG) || defined(FORCE_PR_ASSERT) */ + +#ifdef __APPLE__ +#include + +#define PR_ASSERT(_exp) assert(_exp) +#define PR_NOT_REACHED(_reas) assert(0) + +#else #define PR_ASSERT(expr) ((void) 0) #define PR_NOT_REACHED(reasonStr) +#endif #endif /* defined(DEBUG) || defined(FORCE_PR_ASSERT) */ diff --git a/OSX/libsecurity_asn1/lib/secasn1d.c b/OSX/libsecurity_asn1/lib/secasn1d.c index cd37fc4a..f3385270 100644 --- a/OSX/libsecurity_asn1/lib/secasn1d.c +++ b/OSX/libsecurity_asn1/lib/secasn1d.c @@ -41,7 +41,7 @@ #include "secasn1.h" #include "secerr.h" -#include "assert.h" +#include #ifdef NDEBUG #define DEBUG_DECASN1 0 @@ -1879,8 +1879,9 @@ sec_asn1d_add_to_subitems (sec_asn1d_state *state, if (copy == NULL) { dprintf("decodeError: alloc\n"); state->top->status = decodeError; - if (!state->top->our_pool) + if (!state->top->our_pool) { PORT_Free(thing); + } return NULL; } PORT_Memcpy (copy, data, len); diff --git a/OSX/libsecurity_asn1/security_asn1 b/OSX/libsecurity_asn1/security_asn1 deleted file mode 120000 index 945c9b46..00000000 --- a/OSX/libsecurity_asn1/security_asn1 +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/OSX/libsecurity_authorization/lib/Authorization.c b/OSX/libsecurity_authorization/lib/Authorization.c index 92e1faf0..e88dae1f 100644 --- a/OSX/libsecurity_authorization/lib/Authorization.c +++ b/OSX/libsecurity_authorization/lib/Authorization.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -53,20 +52,24 @@ get_authorization_connection() connection = xpc_connection_create(SECURITY_AUTH_NAME, NULL); if (!connection) { - syslog(LOG_ERR, "Authorization, failed to create xpc connection to %s", SECURITY_AUTH_NAME); + os_log_error(AUTH_LOG, "Failed to create xpc connection to %s", SECURITY_AUTH_NAME); connection = xpc_connection_create(SECURITY_AUTH_NAME, NULL); } + if (connection == NULL) { + os_log_error(AUTH_LOG, "Still failed to create xpc connection to %s", SECURITY_AUTH_NAME); + return; + } xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { if (xpc_get_type(event) == XPC_TYPE_ERROR) { if (event == XPC_ERROR_CONNECTION_INVALID) { - syslog(LOG_ERR, "Authorization, server not available"); + os_log_error(AUTH_LOG, "Server not available"); } // XPC_ERROR_CONNECTION_INTERRUPTED // XPC_ERROR_TERMINATION_IMMINENT } else { char * desc = xpc_copy_description(event); - syslog(LOG_ERR, "Authorization, we should never get messages on this connection: %s", desc); + os_log_error(AUTH_LOG, "We should never get messages on this connection: %s", desc); free(desc); } }); @@ -119,7 +122,9 @@ OSStatus AuthorizationCreate(const AuthorizationRights *rights, xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags | (authorization ? 0 : kAuthorizationFlagNoData)); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action_quiet(reply != NULL, done, status = errAuthorizationInternal); require_action_quiet(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal;); @@ -131,7 +136,7 @@ OSStatus AuthorizationCreate(const AuthorizationRights *rights, size_t len; const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_BLOB, &len); require_action(data != NULL, done, status = errAuthorizationInternal); - assert(len == sizeof(AuthorizationBlob)); + require_action(len == sizeof(AuthorizationBlob), done, status = errAuthorizationInternal); AuthorizationBlob * blob = (AuthorizationBlob*)calloc(1u, sizeof(AuthorizationBlob)); require_action(blob != NULL, done, status = errAuthorizationInternal); @@ -167,7 +172,9 @@ OSStatus AuthorizationCreateWithAuditToken(audit_token_t token, xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -179,8 +186,8 @@ OSStatus AuthorizationCreateWithAuditToken(audit_token_t token, size_t len; const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_BLOB, &len); require_action(data != NULL, done, status = errAuthorizationInternal); - assert(len == sizeof(AuthorizationBlob)); - + require_action(len == sizeof(AuthorizationBlob), done, status = errAuthorizationInternal); + AuthorizationBlob * blob = (AuthorizationBlob*)calloc(1u, sizeof(AuthorizationBlob)); require_action(blob != NULL, done, status = errAuthorizationInternal); *blob = *(AuthorizationBlob*)data; @@ -213,7 +220,9 @@ OSStatus AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags fl xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -229,62 +238,40 @@ done: return status; } -static OSStatus -_AuthorizationPreauthorizeCredentials_send_message(xpc_object_t message) -{ - OSStatus status = errAuthorizationInternal; - xpc_object_t reply = NULL; - - // Send - require_action(message != NULL, done, status = errAuthorizationInternal); - - // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); - require_action(reply != NULL, done, status = errAuthorizationInternal); - require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); - - // Status - status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); - -done: - xpc_release_safe(reply); - return status; -} - -static OSStatus -_AuthorizationPreauthorizeCredentials_prepare_message(AuthorizationRef authorization, const AuthorizationItemSet *credentials, xpc_object_t *message_out) +OSStatus AuthorizationCopyRightProperties(const char *rightName, CFDictionaryRef *output) { - OSStatus status = errAuthorizationInternal; - AuthorizationBlob *blob = NULL; - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - require_action(message != NULL, done, status = errAuthorizationInternal); - - require_action(authorization != NULL, done, status = errAuthorizationInvalidRef); - blob = (AuthorizationBlob *)authorization; - - xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_PREAUTHORIZE_CREDENTIALS); - xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); - setItemSet(message, AUTH_XPC_DATA, credentials); - - *message_out = message; - message = NULL; - status = errAuthorizationSuccess; - -done: - xpc_release_safe(message); - return status; -} - -OSStatus AuthorizationPreauthorizeCredentials(AuthorizationRef authorization, const AuthorizationItemSet *credentials) -{ - OSStatus status = errAuthorizationInternal; - xpc_object_t message = NULL; - - require_noerr(status = _AuthorizationPreauthorizeCredentials_prepare_message(authorization, credentials, &message), done); - require_noerr(status = _AuthorizationPreauthorizeCredentials_send_message(message), done); - + OSStatus status = errAuthorizationInternal; + xpc_object_t reply = NULL; + CFDataRef data = NULL; + xpc_object_t message = NULL; + require_action(rightName != NULL, done, status = errAuthorizationInvalidPointer); + + message = xpc_dictionary_create(NULL, NULL, 0); + require_action(message != NULL, done, status = errAuthorizationInternal); + + xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_RIGHT_PROPERTIES); + xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName); + + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); + require_action(reply != NULL, done, status = errAuthorizationInternal); + require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); + + // Status + status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); + if (output && status == errAuthorizationSuccess) { + size_t len; + const void *bytes = xpc_dictionary_get_data(reply, AUTH_XPC_OUT_ITEMS, &len); + data = CFDataCreate(kCFAllocatorDefault, bytes, len); + require_action(data != NULL, done, status = errAuthorizationInternal); + *output = CFPropertyListCreateWithData(kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL, NULL); + } done: xpc_release_safe(message); + xpc_release_safe(reply); + CFReleaseSafe(data); + return status; } @@ -298,7 +285,9 @@ _AuthorizationCopyRights_send_message(xpc_object_t message, AuthorizationRights require_action(message != NULL, done, status = errAuthorizationInternal); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -440,7 +429,9 @@ OSStatus AuthorizationDismiss() xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_DISMISS); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -477,7 +468,9 @@ OSStatus AuthorizationCopyInfo(AuthorizationRef authorization, } // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -519,7 +512,9 @@ OSStatus AuthorizationMakeExternalForm(AuthorizationRef authorization, xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -531,8 +526,8 @@ OSStatus AuthorizationMakeExternalForm(AuthorizationRef authorization, size_t len; const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_EXTERNAL, &len); require_action(data != NULL, done, status = errAuthorizationInternal); - assert(len == sizeof(AuthorizationExternalForm)); - + require_action(len == sizeof(AuthorizationExternalForm), done, status = errAuthorizationInternal); + *extForm = *(AuthorizationExternalForm*)data; } @@ -560,7 +555,9 @@ OSStatus AuthorizationCreateFromExternalForm(const AuthorizationExternalForm *ex xpc_dictionary_set_data(message, AUTH_XPC_EXTERNAL, extForm, sizeof(AuthorizationExternalForm)); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -572,8 +569,8 @@ OSStatus AuthorizationCreateFromExternalForm(const AuthorizationExternalForm *ex size_t len; const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_BLOB, &len); require_action(data != NULL, done, status = errAuthorizationInternal); - assert(len == sizeof(AuthorizationBlob)); - + require_action(len == sizeof(AuthorizationBlob), done, status = errAuthorizationInternal); + AuthorizationBlob * blob = (AuthorizationBlob*)calloc(1u, sizeof(AuthorizationBlob)); require_action(blob != NULL, done, status = errAuthorizationInternal); *blob = *(AuthorizationBlob*)data; @@ -610,7 +607,9 @@ OSStatus AuthorizationEnableSmartCard(AuthorizationRef authRef, Boolean enable) xpc_dictionary_set_bool(message, AUTH_XPC_DATA, enable); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -640,7 +639,9 @@ OSStatus AuthorizationRightGet(const char *rightName, xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -784,7 +785,9 @@ OSStatus AuthorizationRightSet(AuthorizationRef authRef, xpc_release_safe(value); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -820,7 +823,9 @@ OSStatus AuthorizationRightRemove(AuthorizationRef authorization, xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName); // Reply - reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); require_action(reply != NULL, done, status = errAuthorizationInternal); require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); @@ -832,3 +837,40 @@ done: xpc_release_safe(reply); return status; } + +OSStatus AuthorizationCopyPreloginUserDatabase(const char * _Nullable const volumeUuid, const UInt32 flags, CFArrayRef _Nonnull * _Nonnull output) +{ + OSStatus status = errAuthorizationInternal; + xpc_object_t message = NULL; + xpc_object_t reply = NULL; + + require_action(output != NULL, done, status = errAuthorizationInvalidRef); + + // Send + message = xpc_dictionary_create(NULL, NULL, 0); + require_action(message != NULL, done, status = errAuthorizationInternal); + xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_PRELOGIN_USERDB); + if (volumeUuid) { + xpc_dictionary_set_string(message, AUTH_XPC_TAG, volumeUuid); + } + xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags); + + // Reply + xpc_connection_t conn = get_authorization_connection(); + require_action(conn != NULL, done, status = errAuthorizationInternal); + reply = xpc_connection_send_message_with_reply_sync(conn, message); + require_action(reply != NULL, done, status = errAuthorizationInternal); + require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); + + status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); + + // fill the output + if (status == errAuthorizationSuccess) { + *output = _CFXPCCreateCFObjectFromXPCObject(xpc_dictionary_get_value(reply, AUTH_XPC_DATA)); + } + +done: + xpc_release_safe(message); + xpc_release_safe(reply); + return status; +} diff --git a/OSX/libsecurity_authorization/lib/Authorization.cpp b/OSX/libsecurity_authorization/lib/Authorization.cpp index 71db80cf..5cdbab48 100644 --- a/OSX/libsecurity_authorization/lib/Authorization.cpp +++ b/OSX/libsecurity_authorization/lib/Authorization.cpp @@ -34,6 +34,7 @@ #include #include #include +#include "LegacyAPICounts.h" // // This no longer talks to securityd; it is a kernel function. @@ -105,75 +106,7 @@ OSStatus SessionGetDistinguishedUser(SecuritySessionId session, uid_t *user) END_API(CSSM) } -//OSStatus _SessionSetUserPreferences(SecuritySessionId session); -// -//static -//void SessionUserPreferencesChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) -//{ -//#warning "The cast will loose some information" -// _SessionSetUserPreferences((SecuritySessionId)uintptr_t(observer)); -//} -// -//OSStatus _SessionSetUserPreferences(SecuritySessionId session) -//{ -// BEGIN_API -// CFStringRef appleLanguagesStr = CFSTR("AppleLanguages"); -// CFStringRef controlTintStr = CFSTR("AppleAquaColorVariant"); -// CFStringRef keyboardUIModeStr = CFSTR("AppleKeyboardUIMode"); -// CFStringRef textDirectionStr = CFSTR("AppleTextDirection"); -// CFStringRef hitoolboxAppIDStr = CFSTR("com.apple.HIToolbox"); -// CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter(); -// -// CFRef userPrefsDict(CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); -// CFRef globalPrefsDict(CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); -// -// if (!userPrefsDict || !globalPrefsDict) -// return errSessionValueNotSet; -// -// CFRef appleLanguagesArray(static_cast(CFPreferencesCopyAppValue(appleLanguagesStr, kCFPreferencesCurrentApplication))); -// if (appleLanguagesArray) -// CFDictionarySetValue(globalPrefsDict, appleLanguagesStr, appleLanguagesArray); -// -// CFRef controlTintNumber(static_cast(CFPreferencesCopyAppValue(controlTintStr, kCFPreferencesCurrentApplication))); -// if (controlTintNumber) -// CFDictionarySetValue(globalPrefsDict, controlTintStr, controlTintNumber); -// -// CFRef keyboardUIModeNumber(static_cast(CFPreferencesCopyAppValue(keyboardUIModeStr, kCFPreferencesCurrentApplication))); -// if (keyboardUIModeNumber) -// CFDictionarySetValue(globalPrefsDict, keyboardUIModeStr, keyboardUIModeNumber); -// -// CFRef textDirectionNumber(static_cast(CFPreferencesCopyAppValue(textDirectionStr, kCFPreferencesCurrentApplication))); -// if (textDirectionNumber) -// CFDictionarySetValue(globalPrefsDict, textDirectionStr, textDirectionNumber); -// -// if (CFDictionaryGetCount(globalPrefsDict) > 0) -// CFDictionarySetValue(userPrefsDict, kCFPreferencesAnyApplication, globalPrefsDict); -// -// CFPreferencesSynchronize(hitoolboxAppIDStr, kCFPreferencesCurrentUser, -// kCFPreferencesCurrentHost); -// CFRef hitoolboxPrefsDict(static_cast(CFPreferencesCopyMultiple(NULL, hitoolboxAppIDStr, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost))); -// if (hitoolboxPrefsDict) { -// CFDictionarySetValue(userPrefsDict, hitoolboxAppIDStr, hitoolboxPrefsDict); -// CFNotificationCenterPostNotification(center, CFSTR("com.apple.securityagent.InputPrefsChanged"), CFSTR("com.apple.loginwindow"), hitoolboxPrefsDict, true); -// } -// -// CFRef userPrefsData(CFPropertyListCreateXMLData(NULL, userPrefsDict)); -// if (!userPrefsData) -// return errSessionValueNotSet; -// server().setSessionUserPrefs(session, (uint32_t)CFDataGetLength(userPrefsData), CFDataGetBytePtr(userPrefsData)); -// -// END_API(CSSM) -//} - OSStatus SessionSetUserPreferences(SecuritySessionId session) { -// OSStatus status = _SessionSetUserPreferences(session); -// if (errSecSuccess == status) { -// CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter(); -// // We've succeeded in setting up a static set of prefs, now set up -// CFNotificationCenterAddObserver(center, (void*)session, SessionUserPreferencesChanged, CFSTR("com.apple.Carbon.TISNotifySelectedKeyboardInputSourceChanged"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); -// CFNotificationCenterAddObserver(center, (void*)session, SessionUserPreferencesChanged, CFSTR("com.apple.Carbon.TISNotifyEnabledKeyboardInputSourcesChanged"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); -// } -// return status; return errSecSuccess; } diff --git a/OSX/libsecurity_authorization/lib/Authorization.h b/OSX/libsecurity_authorization/lib/Authorization.h index 41f33df7..534c8adf 100644 --- a/OSX/libsecurity_authorization/lib/Authorization.h +++ b/OSX/libsecurity_authorization/lib/Authorization.h @@ -145,7 +145,7 @@ typedef const char *AuthorizationString; /*! - @struct AuthorizationItem + @typedef AuthorizationItem Each AuthorizationItem describes a single string-named item with optional parameter value. The value must be contiguous memory of valueLength bytes; internal structure is defined separately for each name. @@ -165,7 +165,7 @@ typedef struct { /*! - @struct AuthorizationItemSet + @typedef AuthorizationItemSet An AuthorizationItemSet structure represents a set of zero or more AuthorizationItems. Since it is a set it should not contain any identical AuthorizationItems. @field count Number of items identified by items. @@ -179,7 +179,7 @@ typedef struct { static const size_t kAuthorizationExternalFormLength = 32; /*! - @struct AuthorizationExternalForm + @typedef AuthorizationExternalForm An AuthorizationExternalForm structure can hold the externalized form of an AuthorizationRef. As such, it can be transmitted across IPC channels to other processes, which can re-internalize it to recover a valid AuthorizationRef diff --git a/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h b/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h index de083b3f..4447c72a 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h @@ -181,7 +181,7 @@ enum { /*! - @struct + @typedef Callback API provided by the AuthorizationEngine. @field version Engine callback version. @@ -289,7 +289,7 @@ typedef struct AuthorizationCallbacks { /*! - @struct + @typedef Interface that must be implemented by each plugin. @field version Must be set to kAuthorizationPluginInterfaceVersion diff --git a/OSX/libsecurity_authorization/lib/AuthorizationPriv.h b/OSX/libsecurity_authorization/lib/AuthorizationPriv.h index bd9ec936..d66b9cca 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationPriv.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationPriv.h @@ -35,6 +35,7 @@ #include #include // uid_t #include +#include #if defined(__cplusplus) extern "C" { @@ -133,12 +134,13 @@ OSStatus AuthorizationExecuteWithPrivileges(AuthorizationRef _Nonnull authorizat FILE * __nullable * __nullable communicationsPipe) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_1,__MAC_10_7,__IPHONE_NA,__IPHONE_NA); /*! - @function AuthorizationPreauthorizeCredentials - Tries to preauthorize provided credentials by authorizationhost PAM. No user interface will be shown. - Credentials is set of the context items which will be passed to the authorizationhost. + @function AuthorizationCopyRightProperties + Returns a dictionary with the properties associated with the given authorization right + @param rightName right name for which we need the propertiers + @param output CFDictionaryRef which will hold the properties + */ -OSStatus AuthorizationPreauthorizeCredentials(AuthorizationRef _Nonnull authorization, - const AuthorizationItemSet * __nonnull credentials) __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); +OSStatus AuthorizationCopyRightProperties(const char * __nonnull rightName, CFDictionaryRef __nullable * __nullable output) __OSX_AVAILABLE_STARTING(__MAC_10_15, __IPHONE_NA); /*! @function AuthorizationCopyPrivilegedReference @@ -230,7 +232,7 @@ OSStatus AuthorizationEnableSmartCard(AuthorizationRef _Nonnull authRef, Boolean @param stdIn File descriptor which will contain write-end of the stdin pipe of the privileged tool, use -1 if not needed. @param processFinished This block is called when privileged process finishes. */ - OSStatus AuthorizationExecuteWithPrivilegesInternal(const AuthorizationRef _Nonnull authorization, +OSStatus AuthorizationExecuteWithPrivilegesInternal(const AuthorizationRef _Nonnull authorization, const char * _Nonnull pathToTool, const char * _Nonnull const * _Nonnull arguments, pid_t * _Nullable newProcessPid, @@ -259,7 +261,7 @@ OSStatus AuthorizationEnableSmartCard(AuthorizationRef _Nonnull authRef, Boolean @param stdIn File descriptor which will contain write-end of the stdin pipe of the privileged tool, use -1 if not needed. @param processFinished This block is called when privileged process finishes. */ - OSStatus AuthorizationExecuteWithPrivilegesExternalFormInternal(const AuthorizationExternalForm * _Nonnull extAuthorization, +OSStatus AuthorizationExecuteWithPrivilegesExternalFormInternal(const AuthorizationExternalForm * _Nonnull extAuthorization, const char * _Nonnull pathToTool, const char * _Nullable const * _Nullable arguments, pid_t * _Nullable newProcessPid, @@ -268,6 +270,17 @@ OSStatus AuthorizationEnableSmartCard(AuthorizationRef _Nonnull authRef, Boolean int stdErr, int stdIn, void(^__nullable processFinished)(const int exitStatus)); + +/*! + @function AuthorizationCopyPreloginUserDatabase + Returns CFArrayRef with user database from Prelogin volume + + @param volumeUuid Optional uuid of the volume for which user database will be returned. If not set, users from all volumes are returned. + @param flags Specifies subset of data required in the output + @param output Output array of dictionaries- each dictionary with details for each user +*/ +OSStatus AuthorizationCopyPreloginUserDatabase(const char * _Nullable const volumeUuid, const UInt32 flags, CFArrayRef _Nonnull * _Nonnull output); + #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h b/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h index 8800d326..b3654b18 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h @@ -265,6 +265,8 @@ #define AGENT_HINT_SHOW_RESET "show-reset" #define AGENT_HINT_PASSWORD_ONLY "password-only" #define AGENT_HINT_SHEET_CONTEXT "sheet-context" +#define AGENT_HINT_LACONTEXT "lacontext" +#define AGENT_HINT_REQUIRED_USER "required-user" // Public Key Hash from certificate used for login #define AGENT_HINT_TOKEN_HASH "token-hash" @@ -298,6 +300,9 @@ #define AGENT_HINT_IGNORE_SESSION "ignore-session-state" #define AGENT_HINT_NO_UI_EXPECTED "no-ui-expected" +/* LocalAuthentication specific */ +#define AGENT_HINT_EXT_PASSWORD "la-ext-passwd" + /* Keychain synchronization */ // iDisk keychain blob metainfo dictionary; follows "defaults" naming #define AGENT_HINT_KCSYNC_DICT "com.apple.keychainsync.dictionary" @@ -359,4 +364,32 @@ /* Sheet window ID */ #define kAuthorizationEnvironmentWindowId "cgwindowid" +/* LWOS authenticate approval and admin status */ +#define kAuthorizationFVAdmin "fvadmin" + +/* Prelogin user database defines */ +#define PLUDB_USERNAME "username" +#define PLUDB_LUSERNAME "lusername" +#define PLUDB_KEK "kek" +#define PLUDB_VEK "vek" +#define PLUDB_GUID "guid" +#define PLUDB_ADMIN "admin" +#define PLUDB_SCPAIR "scpairing" +#define PLUDB_IMAGE "image" +#define PLUDB_PWDHINT "pwdhint" +#define PLUDB_SCUNLOCK_DATA "scunl" +#define PLUDB_SCENF "scen" +#define PLUDB_SCUAC "scuac" +#define PLUDB_DNODE "dnode" +#define PLUDB_OWNER "owner" + +/* FVUnlock related defines */ +#define AGENT_FVUNLOCK_USER "fvusername" +#define AGENT_FVUNLOCK_PASSWORD "fvpassword" + +/* PRL related defines */ +#define AGENT_CONTEXT_AKS_MAX_ATTEMPTS "aks-max-attempts" +#define AGENT_CONTEXT_AKS_FAILURES "aks-fail-count" +#define AGENT_CONTEXT_AKS_BACKOFF "aks-backoff" + #endif /* !_SECURITY_AUTHORIZATIONTAGSPRIV_H_ */ diff --git a/OSX/libsecurity_authorization/lib/trampolineClient.cpp b/OSX/libsecurity_authorization/lib/trampolineClient.cpp index b7c5ee85..943a8bad 100644 --- a/OSX/libsecurity_authorization/lib/trampolineClient.cpp +++ b/OSX/libsecurity_authorization/lib/trampolineClient.cpp @@ -25,7 +25,6 @@ // // trampolineClient - Authorization trampoline client-side implementation // -#include #include #include #include @@ -106,13 +105,6 @@ FILE **communicationsPipe) if (extForm == NULL) return errAuthorizationInvalidPointer; - // report the caller to the authorities - aslmsg m = asl_new(ASL_TYPE_MSG); - asl_set(m, "com.apple.message.domain", "com.apple.libsecurity_authorization.AuthorizationExecuteWithPrivileges"); - asl_set(m, "com.apple.message.signature", getprogname()); - asl_log(NULL, m, ASL_LEVEL_NOTICE, "AuthorizationExecuteWithPrivileges!"); - asl_free(m); - // flags are currently reserved if (flags != 0) return errAuthorizationInvalidFlags; diff --git a/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp b/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp index 1fd0e6e8..bf2fccfa 100644 --- a/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp +++ b/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp @@ -38,7 +38,7 @@ using namespace CssmClient; // Exception model // const char * -Error::what () const throw() +Error::what () const _NOEXCEPT { return "CSSM client library error"; } diff --git a/OSX/libsecurity_cdsa_client/lib/cssmclient.h b/OSX/libsecurity_cdsa_client/lib/cssmclient.h index a7bc57ea..34fa6643 100644 --- a/OSX/libsecurity_cdsa_client/lib/cssmclient.h +++ b/OSX/libsecurity_cdsa_client/lib/cssmclient.h @@ -66,7 +66,7 @@ private: class Error : public CssmError { public: Error(CSSM_RETURN err) : CssmError(err, false) { } - virtual const char *what () const throw(); + virtual const char *what () const _NOEXCEPT; enum { objectBusy = -1, diff --git a/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp index 6caef051..7a8bf719 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp @@ -6,7 +6,8 @@ #include #include #include - +// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate +#include "LegacyAPICounts.h" ACAbstractPluginSession::~ACAbstractPluginSession() { /* virtual */ } diff --git a/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp index bfb5e7fe..daeade84 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp @@ -6,7 +6,8 @@ #include #include #include - +// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate +#include "LegacyAPICounts.h" CLAbstractPluginSession::~CLAbstractPluginSession() { /* virtual */ } diff --git a/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp index a138ed2e..980e4cd9 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp @@ -6,7 +6,8 @@ #include #include #include - +// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate +#include "LegacyAPICounts.h" CSPAbstractPluginSession::~CSPAbstractPluginSession() { /* virtual */ } diff --git a/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp index d29da3d4..a6dc6dcc 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp @@ -6,6 +6,8 @@ #include #include #include +// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate +#include "LegacyAPICounts.h" DLAbstractPluginSession::~DLAbstractPluginSession() diff --git a/OSX/libsecurity_cdsa_plugin/lib/DLsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/DLsession.cpp index 89a88690..1b9ee4bf 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/DLsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/DLsession.cpp @@ -47,11 +47,11 @@ DLPluginSession::DLPluginSession(CSSM_MODULE_HANDLE theHandle, // // Implement Allocator methods from the PluginSession side // -void *DLPluginSession::malloc(size_t size) throw(std::bad_alloc) +void *DLPluginSession::malloc(size_t size) { return PluginSession::malloc(size); } -void DLPluginSession::free(void *addr) throw() +void DLPluginSession::free(void *addr) _NOEXCEPT { return PluginSession::free(addr); } -void *DLPluginSession::realloc(void *addr, size_t size) throw(std::bad_alloc) +void *DLPluginSession::realloc(void *addr, size_t size) { return PluginSession::realloc(addr, size); } diff --git a/OSX/libsecurity_cdsa_plugin/lib/DLsession.h b/OSX/libsecurity_cdsa_plugin/lib/DLsession.h index 67c35ecb..cbd56135 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/DLsession.h +++ b/OSX/libsecurity_cdsa_plugin/lib/DLsession.h @@ -44,9 +44,9 @@ public: const CSSM_UPCALLS &upcalls, DatabaseManager &databaseManager); - void *malloc(size_t size) throw(std::bad_alloc); - void free(void *addr) throw(); - void *realloc(void *addr, size_t size) throw(std::bad_alloc); + void *malloc(size_t size); + void free(void *addr) _NOEXCEPT; + void *realloc(void *addr, size_t size); protected: CSSM_MODULE_FUNCS_PTR construct(); diff --git a/OSX/libsecurity_cdsa_plugin/lib/Database.cpp b/OSX/libsecurity_cdsa_plugin/lib/Database.cpp index ef7da434..f34f5ba4 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/Database.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/Database.cpp @@ -39,7 +39,7 @@ DatabaseManager::get (const DbName &inDbName) DatabaseMap::iterator anIterator = mDatabaseMap.find (inDbName); if (anIterator == mDatabaseMap.end()) { - auto_ptr aDatabase(make(inDbName)); + unique_ptr aDatabase(make(inDbName)); mDatabaseMap.insert(DatabaseMap::value_type(aDatabase->mDbName, aDatabase.get())); return aDatabase.release(); } @@ -164,7 +164,7 @@ Database::_dbOpen(DatabaseSession &inDatabaseSession, const AccessCredentials *inAccessCred, const void *inOpenParameters) { - auto_ptraDbContext(makeDbContext(inDatabaseSession, + unique_ptraDbContext(makeDbContext(inDatabaseSession, inAccessRequest, inAccessCred, inOpenParameters)); @@ -195,7 +195,7 @@ Database::_dbCreate(DatabaseSession &inDatabaseSession, const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, const void *inOpenParameters) { - auto_ptraDbContext(makeDbContext(inDatabaseSession, + unique_ptraDbContext(makeDbContext(inDatabaseSession, inAccessRequest, (inCredAndAclEntry ? AccessCredentials::optional(inCredAndAclEntry->AccessCred) diff --git a/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp b/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp index 15a6f695..723b1e2f 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp @@ -192,7 +192,7 @@ DatabaseSession::DbClose(CSSM_DB_HANDLE inDbHandle) DbContextMap::iterator it = mDbContextMap.find(inDbHandle); if (it == mDbContextMap.end()) CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE); - auto_ptr aDbContext(it->second); + unique_ptr aDbContext(it->second); mDbContextMap.erase(it); mDatabaseManager.dbClose(*aDbContext); } diff --git a/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp index acfb0493..1396717f 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp @@ -6,7 +6,8 @@ #include #include #include - +// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate +#include "LegacyAPICounts.h" TPAbstractPluginSession::~TPAbstractPluginSession() { /* virtual */ } diff --git a/OSX/libsecurity_cdsa_plugin/lib/csputilities.cpp b/OSX/libsecurity_cdsa_plugin/lib/csputilities.cpp index e0d78ff1..55a43002 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/csputilities.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/csputilities.cpp @@ -33,9 +33,10 @@ using LowLevelMemoryUtilities::increment; CSPFullPluginSession::Writer::Writer(CssmData *v, uint32 n, CssmData *rem) : vec(v), firstVec(v), lastVec(v + n - 1), remData(rem) { - if (vec == NULL || n == 0) + if (vec == NULL || n == 0) { CssmError::throwMe(CSSMERR_CSP_INVALID_OUTPUT_VECTOR); // CDSA p.253, amended - useData(vec); + } + useData(vec); written = 0; } diff --git a/OSX/libsecurity_cdsa_plugin/lib/cssmplugin.cpp b/OSX/libsecurity_cdsa_plugin/lib/cssmplugin.cpp index c8680c4b..c1c7e7c6 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/cssmplugin.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/cssmplugin.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "LegacyAPICounts.h" ModuleNexus CssmPlugin::sessionMap; @@ -54,10 +55,13 @@ void CssmPlugin::moduleLoad(const Guid &cssmGuid, const Guid &moduleGuid, const ModuleCallback &newCallback) { - if (mLoaded) + static dispatch_once_t onceToken; + countLegacyAPI(&onceToken, "CssmPlugin::moduleLoad"); + if (mLoaded) { CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); - - mMyGuid = moduleGuid; + } + + mMyGuid = moduleGuid; // let the implementation know that we're loading this->load(); @@ -78,12 +82,16 @@ void CssmPlugin::moduleUnload(const Guid &cssmGuid, const Guid &moduleGuid, const ModuleCallback &oldCallback) { + // These are called from the public pluginspi.h + static dispatch_once_t onceToken; + countLegacyAPI(&onceToken, "CssmPlugin::moduleUnload"); // check the callback vector - if (!mLoaded || oldCallback != mCallback) + if (!mLoaded || oldCallback != mCallback) { CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + } // tell our subclass that we're closing down - this->unload(); + this->unload(); // commit closure mLoaded = false; @@ -108,12 +116,14 @@ void CssmPlugin::moduleAttach(CSSM_MODULE_HANDLE theHandle, const CSSM_UPCALLS &upcalls, CSSM_MODULE_FUNCS_PTR &funcTbl) { + static dispatch_once_t onceToken; + countLegacyAPI(&onceToken, "CssmPlugin::moduleAttach"); // basic (in)sanity checks if (moduleGuid != mMyGuid) CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID); // make the new session object, hanging in thin air - auto_ptr session(this->makeSession(theHandle, + unique_ptr session(this->makeSession(theHandle, version, subserviceId, subserviceType, attachFlags, @@ -140,6 +150,8 @@ void CssmPlugin::moduleAttach(CSSM_MODULE_HANDLE theHandle, // void CssmPlugin::moduleDetach(CSSM_MODULE_HANDLE handle) { + static dispatch_once_t onceToken; + countLegacyAPI(&onceToken, "CssmPlugin::moduleDetach"); // locate the plugin and hold the sessionMapLock PluginSession *session; { diff --git a/OSX/libsecurity_cdsa_plugin/lib/pluginsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/pluginsession.cpp index c73328ce..8de73c8d 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/pluginsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/pluginsession.cpp @@ -61,18 +61,20 @@ void PluginSession::detach() // // Allocation management // -void *PluginSession::malloc(size_t size) throw(std::bad_alloc) +void *PluginSession::malloc(size_t size) { - if (void *addr = upcalls.malloc_func(handle(), size)) + if (void *addr = upcalls.malloc_func(handle(), size)) { return addr; - throw std::bad_alloc(); + } + throw std::bad_alloc(); } -void *PluginSession::realloc(void *oldAddr, size_t size) throw(std::bad_alloc) +void *PluginSession::realloc(void *oldAddr, size_t size) { - if (void *addr = upcalls.realloc_func(handle(), oldAddr, size)) + if (void *addr = upcalls.realloc_func(handle(), oldAddr, size)) { return addr; - throw std::bad_alloc(); + } + throw std::bad_alloc(); } diff --git a/OSX/libsecurity_cdsa_plugin/lib/pluginsession.h b/OSX/libsecurity_cdsa_plugin/lib/pluginsession.h index d58ba5ea..fe8c6461 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/pluginsession.h +++ b/OSX/libsecurity_cdsa_plugin/lib/pluginsession.h @@ -68,9 +68,9 @@ protected: public: // implement Allocator - void *malloc(size_t size) throw(std::bad_alloc); - void *realloc(void *addr, size_t size) throw(std::bad_alloc); - void free(void *addr) throw() { upcalls.free_func(handle(), addr); } + void *malloc(size_t size); + void *realloc(void *addr, size_t size); + void free(void *addr) _NOEXCEPT { upcalls.free_func(handle(), addr); } // about ourselves const CSSM_VERSION &version() const { return mVersion; } diff --git a/OSX/libsecurity_cdsa_plugin/lib/pluginspi.h b/OSX/libsecurity_cdsa_plugin/lib/pluginspi.h index f5d8d491..3bc97d29 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/pluginspi.h +++ b/OSX/libsecurity_cdsa_plugin/lib/pluginspi.h @@ -47,7 +47,7 @@ SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleLoad) (const CSSM_GUID *CssmGuid, CSSM_SPI_ModuleEventHandler CssmNotifyCallback, void *CssmNotifyCallbackCtx) { - BEGIN_API + BEGIN_API_NO_METRICS plugin().moduleLoad(Guid::required(CssmGuid), Guid::required(ModuleGuid), ModuleCallback(CssmNotifyCallback, CssmNotifyCallbackCtx)); @@ -64,7 +64,7 @@ SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleUnload) (const CSSM_GUID *CssmGuid, CSSM_SPI_ModuleEventHandler CssmNotifyCallback, void *CssmNotifyCallbackCtx) { - BEGIN_API + BEGIN_API_NO_METRICS plugin().moduleUnload(Guid::required(CssmGuid), Guid::required(ModuleGuid), ModuleCallback(CssmNotifyCallback, CssmNotifyCallbackCtx)); @@ -97,7 +97,7 @@ SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleAttach) (const CSSM_GUID *ModuleGui const CSSM_UPCALLS *Upcalls, CSSM_MODULE_FUNCS_PTR *FuncTbl) { - BEGIN_API + BEGIN_API_NO_METRICS plugin().moduleAttach(ModuleHandle, Guid::required(CssmGuid), Guid::required(ModuleGuid), @@ -117,7 +117,7 @@ SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleDetach) (CSSM_MODULE_HANDLE ModuleH SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleDetach) (CSSM_MODULE_HANDLE ModuleHandle) { - BEGIN_API + BEGIN_API_NO_METRICS plugin().moduleDetach(ModuleHandle); END_API(CSSM) } diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp index fdc29c9f..dccd5d93 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp @@ -104,9 +104,7 @@ CommentAclSubject *CommentAclSubject::Maker::make(Version, Reader &pub, Reader & // Phew. I'd rather be lucky than good... // // So let's get started: -#ifndef NDEBUG static const size_t minCssmList = 12; // min(sizeof(CSSM_LIST)) of all architectures -#endif pub.get(4); // skip first 4 bytes uint32_t lop; pub(lop); // read L4n-or-(bottom of)P8h uint32_t tol; pub(tol); // read T4h-or-L4n diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp index 7918ff47..d9773dae 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp @@ -89,11 +89,12 @@ ProcessAclSubject *ProcessAclSubject::Maker::make(const TypedList &list) const // validate input if (selector.version != CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION) CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); - if (!selector.uses(CSSM_ACL_MATCH_BITS)) + if (!selector.uses(CSSM_ACL_MATCH_BITS)) { CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } // okay - return new ProcessAclSubject(selector); + return new ProcessAclSubject(selector); } ProcessAclSubject *ProcessAclSubject::Maker::make(Version, Reader &pub, Reader &priv) const diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp index 7cccfa6d..9d45cd8e 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp @@ -112,8 +112,9 @@ ThresholdAclSubject *ThresholdAclSubject::Maker::make(const TypedList &list) con // now compile the subSubjects AclSubjectVector elements(totalSubjects); const ListElement *subSubject = &list[3]; - for (uint32 n = 0; n < totalSubjects; n++, subSubject = subSubject->next()) + for (uint32 n = 0; n < totalSubjects; n++, subSubject = subSubject->next()) { elements[n] = ObjectAcl::make(subSubject->typedList()); + } return new ThresholdAclSubject(totalSubjects, minimumNeeded, elements); } diff --git a/OSX/libsecurity_cdsa_utilities/lib/context.h b/OSX/libsecurity_cdsa_utilities/lib/context.h index d5e9532d..03db058f 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/context.h +++ b/OSX/libsecurity_cdsa_utilities/lib/context.h @@ -187,11 +187,11 @@ public: } public: - void *operator new (size_t size, Allocator &alloc) throw(std::bad_alloc) + void *operator new (size_t size, Allocator &alloc) { return alloc.malloc(size); } - void operator delete (void *addr, size_t, Allocator &alloc) throw() + void operator delete (void *addr, size_t, Allocator &alloc) _NOEXCEPT { return alloc.free(addr); } - static void destroy(Context *context, Allocator &alloc) throw() + static void destroy(Context *context, Allocator &alloc) _NOEXCEPT { alloc.free(context->ContextAttributes); alloc.free(context); } public: diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp index 63d262b2..a7bb291c 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp @@ -40,13 +40,13 @@ namespace Security { // // CssmMemoryFunctionsAllocators // -void *CssmMemoryFunctionsAllocator::malloc(size_t size) throw(std::bad_alloc) +void *CssmMemoryFunctionsAllocator::malloc(size_t size) { return functions.malloc(size); } -void CssmMemoryFunctionsAllocator::free(void *addr) throw() +void CssmMemoryFunctionsAllocator::free(void *addr) _NOEXCEPT { return functions.free(addr); } -void *CssmMemoryFunctionsAllocator::realloc(void *addr, size_t size) throw(std::bad_alloc) +void *CssmMemoryFunctionsAllocator::realloc(void *addr, size_t size) { return functions.realloc(addr, size); } @@ -62,16 +62,16 @@ CssmAllocatorMemoryFunctions::CssmAllocatorMemoryFunctions(Allocator &alloc) calloc_func = relayCalloc; } -void *CssmAllocatorMemoryFunctions::relayMalloc(size_t size, void *ref) throw(std::bad_alloc) +void *CssmAllocatorMemoryFunctions::relayMalloc(size_t size, void *ref) { return allocator(ref).malloc(size); } -void CssmAllocatorMemoryFunctions::relayFree(void *mem, void *ref) throw() +void CssmAllocatorMemoryFunctions::relayFree(void *mem, void *ref) _NOEXCEPT { allocator(ref).free(mem); } -void *CssmAllocatorMemoryFunctions::relayRealloc(void *mem, size_t size, void *ref) throw(std::bad_alloc) +void *CssmAllocatorMemoryFunctions::relayRealloc(void *mem, size_t size, void *ref) { return allocator(ref).realloc(mem, size); } -void *CssmAllocatorMemoryFunctions::relayCalloc(uint32 count, size_t size, void *ref) throw(std::bad_alloc) +void *CssmAllocatorMemoryFunctions::relayCalloc(uint32 count, size_t size, void *ref) { // Allocator doesn't have a calloc() method size_t alloc_size = 0; diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.h b/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.h index 01a14e37..6c4365ea 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.h @@ -46,30 +46,30 @@ public: { *(CSSM_MEMORY_FUNCS *)this = funcs; } CssmMemoryFunctions() { } - void *malloc(size_t size) const throw(std::bad_alloc); - void free(void *mem) const throw() { free_func(mem, AllocRef); } - void *realloc(void *mem, size_t size) const throw(std::bad_alloc); - void *calloc(uint32 count, size_t size) const throw(std::bad_alloc); + void *malloc(size_t size) const; + void free(void *mem) const _NOEXCEPT { free_func(mem, AllocRef); } + void *realloc(void *mem, size_t size) const; + void *calloc(uint32 count, size_t size) const; - bool operator == (const CSSM_MEMORY_FUNCS &other) const throw() + bool operator == (const CSSM_MEMORY_FUNCS &other) const _NOEXCEPT { return !memcmp(this, &other, sizeof(*this)); } }; -inline void *CssmMemoryFunctions::malloc(size_t size) const throw(std::bad_alloc) +inline void *CssmMemoryFunctions::malloc(size_t size) const { if (void *addr = malloc_func(size, AllocRef)) return addr; throw std::bad_alloc(); } -inline void *CssmMemoryFunctions::calloc(uint32 count, size_t size) const throw(std::bad_alloc) +inline void *CssmMemoryFunctions::calloc(uint32 count, size_t size) const { if (void *addr = calloc_func(count, size, AllocRef)) return addr; throw std::bad_alloc(); } -inline void *CssmMemoryFunctions::realloc(void *mem, size_t size) const throw(std::bad_alloc) +inline void *CssmMemoryFunctions::realloc(void *mem, size_t size) const { if (void *addr = realloc_func(mem, size, AllocRef)) return addr; @@ -84,11 +84,11 @@ class CssmMemoryFunctionsAllocator : public Allocator { public: CssmMemoryFunctionsAllocator(const CssmMemoryFunctions &memFuncs) : functions(memFuncs) { } - void *malloc(size_t size) throw(std::bad_alloc); - void free(void *addr) throw(); - void *realloc(void *addr, size_t size) throw(std::bad_alloc); + void *malloc(size_t size); + void free(void *addr) _NOEXCEPT; + void *realloc(void *addr, size_t size); - operator const CssmMemoryFunctions & () const throw() { return functions; } + operator const CssmMemoryFunctions & () const _NOEXCEPT { return functions; } private: const CssmMemoryFunctions functions; @@ -106,12 +106,12 @@ public: CssmAllocatorMemoryFunctions() { /*IFDEBUG(*/ AllocRef = NULL /*)*/ ; } // later assignment req'd private: - static void *relayMalloc(size_t size, void *ref) throw(std::bad_alloc); - static void relayFree(void *mem, void *ref) throw(); - static void *relayRealloc(void *mem, size_t size, void *ref) throw(std::bad_alloc); - static void *relayCalloc(uint32 count, size_t size, void *ref) throw(std::bad_alloc); + static void *relayMalloc(size_t size, void *ref); + static void relayFree(void *mem, void *ref) _NOEXCEPT; + static void *relayRealloc(void *mem, size_t size, void *ref); + static void *relayCalloc(uint32 count, size_t size, void *ref); - static Allocator &allocator(void *ref) throw() + static Allocator &allocator(void *ref) _NOEXCEPT { return *reinterpret_cast(ref); } }; diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmbridge.h b/OSX/libsecurity_cdsa_utilities/lib/cssmbridge.h index f2f92dbd..73e0d4b2 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmbridge.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmbridge.h @@ -32,10 +32,8 @@ #include #include - namespace Security { - // // API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions. // Usage: @@ -46,7 +44,12 @@ namespace Security { // END_API0 // completely ignores exceptions; falls through in all cases // END_API1(bad) // return (bad) on exception; fall through on success // -#define BEGIN_API try { +#define BEGIN_API try { \ + static dispatch_once_t countToken; \ + countLegacyAPI(&countToken, __FUNCTION__); + +#define BEGIN_API_NO_METRICS try { + #define END_API(base) } \ catch (const CommonError &err) { return CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \ catch (const std::bad_alloc &) { return CssmError::cssmError(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmdata.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmdata.cpp index 5dec094e..28165909 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmdata.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmdata.cpp @@ -240,7 +240,7 @@ CssmDateData::CssmDateData(const CSSM_DATE &date) } -CssmData& CssmOwnedData::get() const throw() +CssmData& CssmOwnedData::get() const _NOEXCEPT { return referent; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmdata.h b/OSX/libsecurity_cdsa_utilities/lib/cssmdata.h index eee84a0a..c69172d7 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmdata.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmdata.h @@ -243,7 +243,7 @@ public: void *data() const { return get().data(); } size_t length() const { return get().length(); } - virtual CssmData &get() const throw() = 0; // get shared copy, no ownership change + virtual CssmData &get() const _NOEXCEPT = 0; // get shared copy, no ownership change virtual CssmData release() = 0; // give up copy, ownership is transferred virtual void reset() = 0; // give up copy, data is discarded }; @@ -372,7 +372,7 @@ public: void operator = (CssmOwnedData &source) { set(source); } void operator = (const CSSM_DATA &source) { copy(source); } - CssmData &get() const throw(); + CssmData &get() const _NOEXCEPT; public: void fromOid(const char *oid); // fill from text OID form (1.2.3...) diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h b/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h index 66c9bcb2..be227a3b 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h @@ -220,9 +220,7 @@ class CssmDLPolyData public: CssmDLPolyData(const CSSM_DATA &data, CSSM_DB_ATTRIBUTE_FORMAT format) : mData(CssmData::overlay(data)) -#ifndef NDEBUG , mFormat(format) -#endif {} // @@@ Don't use assert, but throw an exception. @@ -269,9 +267,7 @@ public: private: const CssmData &mData; -#ifndef NDEBUG CSSM_DB_ATTRIBUTE_FORMAT mFormat; -#endif }; @@ -686,6 +682,8 @@ public: const CSSM_NET_ADDRESS *location = NULL) : mImpl(new Impl(CssmSubserviceUid(guid, NULL, ssid, sstype), name, location)) { } + DLDbIdentifier(const DLDbIdentifier& i) : mImpl(i.mImpl) {} + // Conversion Operators bool operator !() const { return !mImpl; } operator bool() const { return mImpl; } @@ -749,7 +747,10 @@ struct DLDbFlatIdentifier { address(const_cast(ident.dbLocation())) { } - operator DLDbIdentifier () { return DLDbIdentifier(*uid, name, address); } + operator DLDbIdentifier () { + DLDbIdentifier db(*uid, name, address); + return db; + } }; template diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp index 98ec8dd8..12e3bc74 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp @@ -53,7 +53,7 @@ CssmError::CssmError(CSSM_RETURN err, bool suppresslogging) : error(err) } -const char *CssmError::what() const throw () +const char *CssmError::what() const _NOEXCEPT { return whatBuffer; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.h b/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.h index 7da29adb..6da470fa 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.h @@ -46,7 +46,7 @@ public: const CSSM_RETURN error; virtual OSStatus osStatus() const; virtual int unixError() const; - virtual const char *what () const throw (); + virtual const char *what () const _NOEXCEPT; static CSSM_RETURN merge(CSSM_RETURN error, CSSM_RETURN base); diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmlist.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmlist.cpp index 911cf2c6..055bf7da 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmlist.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmlist.cpp @@ -152,6 +152,14 @@ ListElement &CssmList::operator [] (unsigned ix) const throw 999; //@@@ } +CssmList &CssmList::operator =(const CssmList& other) +{ + ListType = other.ListType; + Head = other.Head; + Tail = other.Tail; + return *this; +} + unsigned int CssmList::length() const { unsigned int len = 0; diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h b/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h index 40f77b76..1e65adbd 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h @@ -141,6 +141,8 @@ public: // logically remove the first element (skip it) void snip(); + + CssmList &operator =(const CssmList& other); public: void clear(Allocator &alloc); // free my contents diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmpods.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmpods.cpp index 8915894d..2a067c44 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmpods.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmpods.cpp @@ -38,9 +38,10 @@ char *Guid::toString(char buffer[stringRepLength+1]) const { sprintf(buffer, "{%8.8x-%4.4hx-%4.4hx-", int(n2h(Data1)), n2h(Data2), n2h(Data3)); - for (int n = 0; n < 2; n++) + for (int n = 0; n < 2; n++) { sprintf(buffer + 20 + 2*n, "%2.2hhx", Data4[n]); - buffer[24] = '-'; + } + buffer[24] = '-'; for (int n = 2; n < 8; n++) sprintf(buffer + 21 + 2*n, "%2.2hhx", Data4[n]); buffer[37] = '}'; @@ -86,8 +87,9 @@ void Guid::parseGuid(const char *string) int d1; uint16 d2, d3; - if (sscanf(string, "{%8x-%4hx-%4hx-", &d1, &d2, &d3) != 3) + if (sscanf(string, "{%8x-%4hx-%4hx-", &d1, &d2, &d3) != 3) { CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID); + } Data1 = h2n(uint32(d1)); Data2 = h2n(d2); Data3 = h2n(d3); @@ -131,7 +133,7 @@ CssmSubserviceUid::CssmSubserviceUid(const CSSM_GUID &guid, } -bool CssmSubserviceUid::operator == (const CSSM_SUBSERVICE_UID &otherUid) const +bool CssmSubserviceUid::operator == (const CssmSubserviceUid &otherUid) const { // make sure we don't crash if we get bad data #pragma clang diagnostic push @@ -145,7 +147,7 @@ bool CssmSubserviceUid::operator == (const CSSM_SUBSERVICE_UID &otherUid) const && guid() == other.guid(); } -bool CssmSubserviceUid::operator < (const CSSM_SUBSERVICE_UID &otherUid) const +bool CssmSubserviceUid::operator < (const CssmSubserviceUid &otherUid) const { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-undefined-compare" @@ -173,7 +175,7 @@ CryptoDataClass::~CryptoDataClass() CSSM_RETURN CryptoDataClass::callbackShim(CSSM_DATA *output, void *ctx) { - BEGIN_API + BEGIN_API_NO_METRICS *output = reinterpret_cast(ctx)->yield(); END_API(CSSM) } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmpods.h b/OSX/libsecurity_cdsa_utilities/lib/cssmpods.h index c1b1c542..55d7e2ed 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmpods.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmpods.h @@ -43,17 +43,18 @@ class Guid : public PodWrapper { public: Guid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; } Guid(const CSSM_GUID &rGuid) { memcpy(this, &rGuid, sizeof(*this)); } + Guid(const Guid &rGuid) { memcpy(this, &rGuid, sizeof(*this)); } Guid(const char *string); Guid(const std::string &s); - Guid &operator = (const CSSM_GUID &rGuid) + Guid &operator = (const Guid &rGuid) { memcpy(this, &rGuid, sizeof(CSSM_GUID)); return *this; } - bool operator == (const CSSM_GUID &other) const + bool operator == (const Guid &other) const { return (this == &other) || !memcmp(this, &other, sizeof(CSSM_GUID)); } - bool operator != (const CSSM_GUID &other) const + bool operator != (const Guid &other) const { return (this != &other) && memcmp(this, &other, sizeof(CSSM_GUID)); } - bool operator < (const CSSM_GUID &other) const + bool operator < (const Guid &other) const { return memcmp(this, &other, sizeof(CSSM_GUID)) < 0; } size_t hash() const { //@@@ revisit this hash return Data1 + (Data2 << 3) + (Data3 << 11) + (Data4[3]) + (Data4[6] << 22); @@ -84,12 +85,12 @@ public: CssmSubserviceUid() { clearPod(); } CssmSubserviceUid(const CSSM_SUBSERVICE_UID &rSSuid) { memcpy(this, &rSSuid, sizeof(*this)); } - CssmSubserviceUid &operator = (const CSSM_SUBSERVICE_UID &rSSuid) + CssmSubserviceUid &operator = (const CssmSubserviceUid &rSSuid) { memcpy(this, &rSSuid, sizeof(CSSM_SUBSERVICE_UID)); return *this; } - bool operator == (const CSSM_SUBSERVICE_UID &other) const; - bool operator != (const CSSM_SUBSERVICE_UID &other) const { return !(*this == other); } - bool operator < (const CSSM_SUBSERVICE_UID &other) const; + bool operator == (const CssmSubserviceUid &other) const; + bool operator != (const CssmSubserviceUid &other) const { return !(*this == other); } + bool operator < (const CssmSubserviceUid &other) const; CssmSubserviceUid(const CSSM_GUID &guid, const CSSM_VERSION *version = NULL, uint32 subserviceId = 0, diff --git a/OSX/libsecurity_cms/lib/CMSUtils.h b/OSX/libsecurity_cms/lib/CMSUtils.h index 6211a11d..d715d72c 100644 --- a/OSX/libsecurity_cms/lib/CMSUtils.h +++ b/OSX/libsecurity_cms/lib/CMSUtils.h @@ -31,7 +31,6 @@ #include #include /* cssmPerror() */ #include -#include #ifdef __cplusplus extern "C" { @@ -65,13 +64,14 @@ OSStatus cmsRtnToOSStatus( #define CFRELEASE(cfr) if(cfr != NULL) { CFRelease(cfr); } +#include +#define ASSERT(s) assert(s) + #define CMS_DEBUG 0 #if CMS_DEBUG -#define ASSERT(s) assert(s) #define CSSM_PERROR(s, r) cssmPerror(s, r) #define dprintf(args...) printf(args) #else -#define ASSERT(s) #define CSSM_PERROR(s, r) #define dprintf(args...) #endif diff --git a/OSX/libsecurity_codesigning/CodeSigningHelper/main.c b/OSX/libsecurity_codesigning/CodeSigningHelper/main.c index f81de057..7a493755 100644 --- a/OSX/libsecurity_codesigning/CodeSigningHelper/main.c +++ b/OSX/libsecurity_codesigning/CodeSigningHelper/main.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp b/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp index a7e46bcd..10465dff 100644 --- a/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp +++ b/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp @@ -34,8 +34,6 @@ static void request(xpc_connection_t peer, xpc_object_t event) { - OSStatus rc; - pid_t pid = (pid_t)xpc_dictionary_get_int64(event, "pid"); if (pid <= 0) return; @@ -61,11 +59,11 @@ request(xpc_connection_t peer, xpc_object_t event) auditData); } CFRef code; - if ((rc = SecCodeCopyGuestWithAttributes(NULL, attributes, kSecCSDefaultFlags, &code.aref())) == noErr) { + if (SecCodeCopyGuestWithAttributes(NULL, attributes, kSecCSDefaultFlags, &code.aref()) == noErr) { // path to base of client code CFRef codePath; - if ((rc = SecCodeCopyPath(code, kSecCSDefaultFlags, &codePath.aref())) == noErr) { + if (SecCodeCopyPath(code, kSecCSDefaultFlags, &codePath.aref()) == noErr) { CFRef data = CFURLCreateData(NULL, codePath, kCFStringEncodingUTF8, true); xpc_dictionary_set_data(reply, "bundleURL", CFDataGetBytePtr(data), CFDataGetLength(data)); } diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp index c91e927d..47c974a8 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp @@ -27,7 +27,7 @@ public: : text(s) { } - virtual ~ANTLRException() throw() + virtual ~ANTLRException() _NOEXCEPT { } diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp index ee7ad437..96e3b416 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp @@ -19,7 +19,7 @@ class ANTLR_API CharStreamException : public ANTLRException { public: CharStreamException(const ANTLR_USE_NAMESPACE(std)string& s) : ANTLRException(s) {} - ~CharStreamException() throw() {} + ~CharStreamException() _NOEXCEPT {} }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp index ebbb0fd6..f4bdcd22 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp @@ -21,7 +21,7 @@ public: CharStreamIOException(ANTLR_USE_NAMESPACE(std)exception& e) : CharStreamException(e.what()), io(e) {} - ~CharStreamIOException() throw() {} + ~CharStreamIOException() _NOEXCEPT {} }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/IOException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/IOException.hpp index ed87f8ac..41840d47 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/IOException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/IOException.hpp @@ -33,7 +33,7 @@ public: : ANTLRException(mesg) { } - virtual ~IOException() throw() + virtual ~IOException() _NOEXCEPT { } }; diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp index 45054129..ce10e42d 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp @@ -87,7 +87,7 @@ public: CharScanner* scanner_ ); - ~MismatchedCharException() throw() {} + ~MismatchedCharException() _NOEXCEPT {} /** * Returns a clean error message (no line number/column information) diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp index 4631f50b..6099efc7 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp @@ -81,7 +81,7 @@ public: bool matchNot, const ANTLR_USE_NAMESPACE(std)string& fileName_ ); - ~MismatchedTokenException() throw() {} + ~MismatchedTokenException() _NOEXCEPT {} /** * Returns a clean error message (no line number/column information) diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp index e3677ded..51f30610 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp @@ -25,7 +25,7 @@ public: NoViableAltException(RefAST t); NoViableAltException(RefToken t,const ANTLR_USE_NAMESPACE(std)string& fileName_); - ~NoViableAltException() throw() {} + ~NoViableAltException() _NOEXCEPT {} /** * Returns a clean error message (no line number/column information) diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp index d61c18b0..54c1344c 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp @@ -24,7 +24,7 @@ public: NoViableAltForCharException(int c, const ANTLR_USE_NAMESPACE(std)string& fileName_, int line_, int column_); - virtual ~NoViableAltForCharException() throw() + virtual ~NoViableAltForCharException() _NOEXCEPT { } diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp index c131831b..410adb3d 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp @@ -24,26 +24,26 @@ namespace antlr const ANTLR_USE_NAMESPACE(std)string& fileName, int line, int column ); - virtual ~RecognitionException() throw() + virtual ~RecognitionException() _NOEXCEPT { } /// Return file where mishap occurred. - virtual ANTLR_USE_NAMESPACE(std)string getFilename() const throw() + virtual ANTLR_USE_NAMESPACE(std)string getFilename() const _NOEXCEPT { return fileName; } /** * @return the line number that this exception happened on. */ - virtual int getLine() const throw() + virtual int getLine() const _NOEXCEPT { return line; } /** * @return the column number that this exception happened on. */ - virtual int getColumn() const throw() + virtual int getColumn() const _NOEXCEPT { return column; } diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp index c8e9ea39..71aab7bb 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp @@ -28,7 +28,7 @@ public: { } - ~SemanticException() throw() + ~SemanticException() _NOEXCEPT { } }; diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp index a3f4d548..7763c072 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp @@ -29,7 +29,7 @@ public: : ANTLRException(s) { } - virtual ~TokenStreamException() throw() + virtual ~TokenStreamException() _NOEXCEPT { } }; diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp index 29f508bf..9ad18556 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp @@ -26,7 +26,7 @@ public: , io(e) { } - ~TokenStreamIOException() throw() + ~TokenStreamIOException() _NOEXCEPT { } private: diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp index 39685789..9c8ec589 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp @@ -26,7 +26,7 @@ public: , recog(re) { } - virtual ~TokenStreamRecognitionException() throw() + virtual ~TokenStreamRecognitionException() _NOEXCEPT { } virtual ANTLR_USE_NAMESPACE(std)string toString() const @@ -34,15 +34,15 @@ public: return recog.getFileLineColumnString()+getMessage(); } - virtual ANTLR_USE_NAMESPACE(std)string getFilename() const throw() + virtual ANTLR_USE_NAMESPACE(std)string getFilename() const _NOEXCEPT { return recog.getFilename(); } - virtual int getLine() const throw() + virtual int getLine() const _NOEXCEPT { return recog.getLine(); } - virtual int getColumn() const throw() + virtual int getColumn() const _NOEXCEPT { return recog.getColumn(); } diff --git a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp index 7d17b3cd..a50cfb07 100644 --- a/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp +++ b/OSX/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp @@ -18,7 +18,7 @@ namespace antlr { class TokenStreamRetryException : public TokenStreamException { public: TokenStreamRetryException() {} - ~TokenStreamRetryException() throw() {} + ~TokenStreamRetryException() _NOEXCEPT {} }; #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE diff --git a/OSX/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp b/OSX/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp index 4279355e..a44f3ef0 100644 --- a/OSX/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp +++ b/OSX/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp @@ -129,29 +129,30 @@ void TokenStreamRewriteEngine::toStream( std::ostream& out, size_t tokenCursor = firstToken; // make sure we don't run out of the tokens we have... - if( lastToken > (tokens.size() - 1) ) - lastToken = tokens.size() - 1; + if( lastToken > (tokens.size() - 1) ) { + lastToken = tokens.size() - 1; + } - while ( tokenCursor <= lastToken ) - { + while ( tokenCursor <= lastToken ) + { // std::cout << "tokenCursor = " << tokenCursor << " first prog index = " << (*rewriteOpIndex)->getIndex() << std::endl; - if( rewriteOpIndex != rewriteOpEnd ) - { - size_t up_to_here = std::min(lastToken,(*rewriteOpIndex)->getIndex()); - while( tokenCursor < up_to_here ) - out << tokens[tokenCursor++]->getText(); - } - while ( rewriteOpIndex != rewriteOpEnd && - tokenCursor == (*rewriteOpIndex)->getIndex() && - tokenCursor <= lastToken ) - { - tokenCursor = (*rewriteOpIndex)->execute(out); - ++rewriteOpIndex; - } - if( tokenCursor <= lastToken ) - out << tokens[tokenCursor++]->getText(); - } + if( rewriteOpIndex != rewriteOpEnd ) + { + size_t up_to_here = std::min(lastToken,(*rewriteOpIndex)->getIndex()); + while( tokenCursor < up_to_here ) + out << tokens[tokenCursor++]->getText(); + } + while ( rewriteOpIndex != rewriteOpEnd && + tokenCursor == (*rewriteOpIndex)->getIndex() && + tokenCursor <= lastToken ) + { + tokenCursor = (*rewriteOpIndex)->execute(out); + ++rewriteOpIndex; + } + if( tokenCursor <= lastToken ) + out << tokens[tokenCursor++]->getText(); + } // std::cout << "Handling tail operations # left = " << std::distance(rewriteOpIndex,rewriteOpEnd) << std::endl; // now see if there are operations (append) beyond last token index std::for_each( rewriteOpIndex, rewriteOpEnd, executeOperation(out) ); diff --git a/OSX/libsecurity_codesigning/lib/CSCommon.h b/OSX/libsecurity_codesigning/lib/CSCommon.h index d3a6bb18..b39fbe6f 100644 --- a/OSX/libsecurity_codesigning/lib/CSCommon.h +++ b/OSX/libsecurity_codesigning/lib/CSCommon.h @@ -215,6 +215,7 @@ typedef CF_OPTIONS(uint32_t, SecCSFlags) { kSecCSReportProgress = 1 << 28, /* make progress report call-backs when configured */ kSecCSCheckTrustedAnchors = 1 << 27, /* build certificate chain to system trust anchors, not to any self-signed certificate */ kSecCSQuickCheck = 1 << 26, /* (internal) */ + kSecCSApplyEmbeddedPolicy = 1 << 25, /* Apply Embedded (iPhone) policy regardless of the platform we're running on */ }; @@ -251,6 +252,9 @@ typedef CF_OPTIONS(uint32_t, SecCSFlags) { @constant kSecCodeSignatureRuntime Instructs the kernel to apply runtime hardening policies as required by the hardened runtime version + @constant kSecCodeSignatureLinkerSigned + The code was automatically signed by the linker. This signature should be + ignored in any new signing operation. */ typedef CF_OPTIONS(uint32_t, SecCodeSignatureFlags) { kSecCodeSignatureHost = 0x0001, /* may host guest code */ @@ -262,6 +266,7 @@ typedef CF_OPTIONS(uint32_t, SecCodeSignatureFlags) { kSecCodeSignatureEnforcement = 0x1000, /* enforce code signing */ kSecCodeSignatureLibraryValidation = 0x2000, /* library validation required */ kSecCodeSignatureRuntime = 0x10000, /* apply runtime hardening policies */ + kSecCodeSignatureLinkerSigned = 0x20000, /* identify that the signature was auto-generated by the linker*/ }; /*! diff --git a/OSX/libsecurity_codesigning/lib/Code.cpp b/OSX/libsecurity_codesigning/lib/Code.cpp index 712b2ff4..a3f11c4f 100644 --- a/OSX/libsecurity_codesigning/lib/Code.cpp +++ b/OSX/libsecurity_codesigning/lib/Code.cpp @@ -48,7 +48,7 @@ SecCode::SecCode(SecCode *host) // // Clean up a SecCode object // -SecCode::~SecCode() throw() +SecCode::~SecCode() _NOEXCEPT try { } catch (...) { return; diff --git a/OSX/libsecurity_codesigning/lib/Code.h b/OSX/libsecurity_codesigning/lib/Code.h index aa5942c9..bb189a6c 100644 --- a/OSX/libsecurity_codesigning/lib/Code.h +++ b/OSX/libsecurity_codesigning/lib/Code.h @@ -49,7 +49,7 @@ public: SECCFFUNCTIONS(SecCode, SecCodeRef, errSecCSInvalidObjectRef, gCFObjects().Code) SecCode(SecCode *host); - virtual ~SecCode() throw(); + virtual ~SecCode() _NOEXCEPT; bool equal(SecCFObject &other); CFHashCode hash(); diff --git a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp index bc11737f..8cbc67f8 100644 --- a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp +++ b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp @@ -121,7 +121,7 @@ SecCodeSigner::SecCodeSigner(SecCSFlags flags) // // Clean up a SecCodeSigner // -SecCodeSigner::~SecCodeSigner() throw() +SecCodeSigner::~SecCodeSigner() _NOEXCEPT try { delete mLimitedAsync; } catch (...) { @@ -182,9 +182,13 @@ bool SecCodeSigner::valid() const // void SecCodeSigner::sign(SecStaticCode *code, SecCSFlags flags) { - code->setValidationFlags(flags); - if (code->isSigned() && (flags & kSecCSSignPreserveSignature)) + //Never preserve a linker signature. + if (code->isSigned() && + (flags & kSecCSSignPreserveSignature) && + !code->flag(kSecCodeSignatureLinkerSigned)) { return; + } + code->setValidationFlags(flags); Signer operation(*this, code); if ((flags | mOpFlags) & kSecCSRemoveSignature) { secinfo("signer", "%p will remove signature from %p", this, code); diff --git a/OSX/libsecurity_codesigning/lib/CodeSigner.h b/OSX/libsecurity_codesigning/lib/CodeSigner.h index 099d18c7..7e897850 100644 --- a/OSX/libsecurity_codesigning/lib/CodeSigner.h +++ b/OSX/libsecurity_codesigning/lib/CodeSigner.h @@ -51,7 +51,7 @@ public: SECCFFUNCTIONS(SecCodeSigner, SecCodeSignerRef, errSecCSInvalidObjectRef, gCFObjects().CodeSigner) SecCodeSigner(SecCSFlags flags); - virtual ~SecCodeSigner() throw(); + virtual ~SecCodeSigner() _NOEXCEPT; void parameters(CFDictionaryRef args); // parse and set parameters bool valid() const; diff --git a/OSX/libsecurity_codesigning/lib/Requirements.cpp b/OSX/libsecurity_codesigning/lib/Requirements.cpp index d2fb04fe..36a2786f 100644 --- a/OSX/libsecurity_codesigning/lib/Requirements.cpp +++ b/OSX/libsecurity_codesigning/lib/Requirements.cpp @@ -62,7 +62,7 @@ SecRequirement::SecRequirement(const Requirement *req, bool transferOwnership) // // Clean up a SecRequirement object // -SecRequirement::~SecRequirement() throw() +SecRequirement::~SecRequirement() _NOEXCEPT try { ::free((void *)mReq); } catch (...) { diff --git a/OSX/libsecurity_codesigning/lib/Requirements.h b/OSX/libsecurity_codesigning/lib/Requirements.h index 8a266f1c..f4212685 100644 --- a/OSX/libsecurity_codesigning/lib/Requirements.h +++ b/OSX/libsecurity_codesigning/lib/Requirements.h @@ -46,7 +46,7 @@ public: SecRequirement(const void *data, size_t length); SecRequirement(const Requirement *req, bool transferOwnership = false); - virtual ~SecRequirement() throw(); + virtual ~SecRequirement() _NOEXCEPT; bool equal(SecCFObject &other); CFHashCode hash(); diff --git a/OSX/libsecurity_codesigning/lib/SecAssessment.cpp b/OSX/libsecurity_codesigning/lib/SecAssessment.cpp index 1db11311..84f5c10e 100644 --- a/OSX/libsecurity_codesigning/lib/SecAssessment.cpp +++ b/OSX/libsecurity_codesigning/lib/SecAssessment.cpp @@ -425,10 +425,10 @@ CFDictionaryRef SecAssessmentCopyUpdate(CFTypeRef target, if (flags & kSecAssessmentFlagDirect) { // ask the engine right here to do its thing - result = gEngine().update(target, flags, ctx); + result.take(gEngine().update(target, flags, ctx)); } else { // relay the question to our daemon for consideration - result = xpcEngineUpdate(target, flags, ctx); + result.take(xpcEngineUpdate(target, flags, ctx)); } traceUpdate(target, context, result); diff --git a/OSX/libsecurity_codesigning/lib/SecCode.cpp b/OSX/libsecurity_codesigning/lib/SecCode.cpp index 2a494dc7..40cc8203 100644 --- a/OSX/libsecurity_codesigning/lib/SecCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecCode.cpp @@ -33,6 +33,7 @@ #include "cskernel.h" #include #include +#include using namespace CodeSigning; @@ -213,6 +214,31 @@ OSStatus SecCodeCreateWithAuditToken(const audit_token_t *audit, END_CSAPI } + +OSStatus SecCodeCreateWithXPCMessage(xpc_object_t message, SecCSFlags flags, + SecCodeRef * __nonnull CF_RETURNS_RETAINED target) +{ + BEGIN_CSAPI + + checkFlags(flags); + + if (xpc_get_type(message) != XPC_TYPE_DICTIONARY) { + return errSecCSInvalidObjectRef; + } + + xpc_connection_t connection = xpc_dictionary_get_remote_connection(message); + if (connection == NULL) { + return errSecCSInvalidObjectRef; + } + + audit_token_t t = {0}; + xpc_connection_get_audit_token(connection, &t); + + return SecCodeCreateWithAuditToken(&t, flags, target); + + END_CSAPI +} + #endif // TARGET_OS_OSX @@ -289,6 +315,7 @@ const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory"); const CFStringRef kSecCodeInfoNotarizationDate = CFSTR("NotarizationDate"); const CFStringRef kSecCodeInfoCMSDigestHashType = CFSTR("CMSDigestHashType"); const CFStringRef kSecCodeInfoCMSDigest = CFSTR("CMSDigest"); +const CFStringRef kSecCodeInfoSignatureVersion = CFSTR("SignatureVersion"); /* DiskInfoRepInfo types */ const CFStringRef kSecCodeInfoDiskRepVersionPlatform = CFSTR("VersionPlatform"); diff --git a/OSX/libsecurity_codesigning/lib/SecCode.h b/OSX/libsecurity_codesigning/lib/SecCode.h index aa53b5ac..14009a51 100644 --- a/OSX/libsecurity_codesigning/lib/SecCode.h +++ b/OSX/libsecurity_codesigning/lib/SecCode.h @@ -32,6 +32,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -187,6 +188,28 @@ extern const CFStringRef kSecGuestAttributeSubarchitecture; OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef __nullable host, CFDictionaryRef __nullable attributes, SecCSFlags flags, SecCodeRef * __nonnull CF_RETURNS_RETAINED guest); + +/*! + @function SecCodeCreateWithXPCMessage + Creates a SecCode reference to the process that sent the provided XPC message, using the + associated audit token. + + @param message The xpc_object_t of a message recieved via xpc to look up the audit token + of the process that sent the message. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param processRef On successful return, a SecCode object reference identifying + the particular guest of the process from the audit token. This argument will not be + changed if the call fails (does not return errSecSuccess). + @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. In particular: + @error errSecCSInvalidObjectRef The xpc_object_t was not of type XPC_TYPE_DICTIONARY. + @error errSecCSInvalidObjectRef The xpc_object_t was not an xpc message with an associated + connection. + For a complete list of errors, please see {@link SecCodeCopyGuestWithAttributes}. +*/ +OSStatus SecCodeCreateWithXPCMessage(xpc_object_t message, SecCSFlags flags, + SecCodeRef * __nonnull CF_RETURNS_RETAINED target); + #endif // TARGET_OS_OSX @@ -215,7 +238,7 @@ OSStatus SecCodeCheckValidity(SecCodeRef code, SecCSFlags flags, SecRequirementRef __nullable requirement); /*! - @function SecCodeCheckValidityWifErrors + @function SecCodeCheckValidityWithErrors Performs dynamic validation of the given SecCode object. The call obtains and verifies the signature on the code object. It checks the validity of only those sealed components required to establish identity. It checks the SecCode's @@ -290,7 +313,10 @@ OSStatus SecCodeCopyDesignatedRequirement(SecStaticCodeRef code, SecCSFlags flag @function SecCodeCopySigningInformation For a given Code or StaticCode object, extract various pieces of information from its code signature and return them in the form of a CFDictionary. The amount - and detail level of the data is controlled by the flags passed to the call. + and detail level of the data is controlled by the flags passed to the call. For + Code objects, some of the signing information returned will be from disk. You can + call one of the CheckValidity functions to check that the content on disk matches + the signing information attached to the running Code. If the code exists but is not signed at all, this call will succeed and return a dictionary that does NOT contain the kSecCodeInfoIdentifier key. This is the diff --git a/OSX/libsecurity_codesigning/lib/SecCodePriv.h b/OSX/libsecurity_codesigning/lib/SecCodePriv.h index d88239c8..e2cac5dd 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodePriv.h +++ b/OSX/libsecurity_codesigning/lib/SecCodePriv.h @@ -47,6 +47,7 @@ extern const CFStringRef kSecCodeInfoResourceDirectory; /* Internal */ extern const CFStringRef kSecCodeInfoNotarizationDate; /* Internal */ extern const CFStringRef kSecCodeInfoCMSDigestHashType; /* Internal */ extern const CFStringRef kSecCodeInfoCMSDigest; /* Internal */ +extern const CFStringRef kSecCodeInfoSignatureVersion; /* Internal */ extern const CFStringRef kSecCodeInfoDiskRepVersionPlatform; /* Number */ extern const CFStringRef kSecCodeInfoDiskRepVersionMin; /* Number */ @@ -229,7 +230,10 @@ OSStatus SecCodeValidateFileResource(SecStaticCodeRef code, CFStringRef relative entirely eventually, we makes this a private flag. */ CF_ENUM(uint32_t) { + // NOTE: These values needs to align with the public definitions for static code validity too. kSecCSStrictValidateStructure = 1 << 13, + kSecCSSkipRootVolumeExceptions = 1 << 14, + }; #if TARGET_OS_OSX diff --git a/OSX/libsecurity_codesigning/lib/SecCodeSigner.h b/OSX/libsecurity_codesigning/lib/SecCodeSigner.h index eba11830..c1a83ba4 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodeSigner.h +++ b/OSX/libsecurity_codesigning/lib/SecCodeSigner.h @@ -38,7 +38,11 @@ extern "C" { @typedef SecCodeSignerRef This is the type of a reference to a code requirement. */ +#ifdef BRIDGED_SECCODESIGNER +typedef struct CF_BRIDGED_TYPE(id) __SecCodeSigner *SecCodeSignerRef; /* code signing object */ +#else typedef struct __SecCodeSigner *SecCodeSignerRef; /* code signing object */ +#endif /*! @@ -215,10 +219,13 @@ enum { kSecCSEditSignature = 1 << 10, // edit existing signature }; - +#ifdef BRIDGED_SECCODESIGNER +OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, + SecCodeSignerRef * __nonnull CF_RETURNS_RETAINED signer); +#else OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, SecCodeSignerRef *signer); - +#endif /*! @function SecCodeSignerAddSignature diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp index b240b4b8..0fa873e1 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp @@ -122,21 +122,26 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se | kSecCSCheckGatekeeperArchitectures | kSecCSRestrictSymlinks | kSecCSRestrictToAppLike - | kSecCSUseSoftwareSigningCert - | kSecCSValidatePEH + | kSecCSUseSoftwareSigningCert + | kSecCSValidatePEH | kSecCSSingleThreaded + | kSecCSApplyEmbeddedPolicy + | kSecCSSkipRootVolumeExceptions ); if (errors) flags |= kSecCSFullReport; // internal-use flag +#if !TARGET_OS_OSX + flags |= kSecCSApplyEmbeddedPolicy; +#endif + SecPointer code = SecStaticCode::requiredStatic(staticCodeRef); code->setValidationFlags(flags); const SecRequirement *req = SecRequirement::optional(requirementRef); DTRACK(CODESIGN_EVAL_STATIC, code, (char*)code->mainExecutablePath().c_str()); code->staticValidate(flags, req); -#if TARGET_OS_IPHONE // Everything checked out correctly but we need to make sure that when // we validated the code directory, we trusted the signer. We defer this // until now because the caller may still trust the signer via a @@ -144,10 +149,9 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se // the directory, we potentially skip resource validation even though the // caller will go on to trust the signature // Applications that are validated against a provisioning profile do not have their resources checked - if (code->trustedSigningCertChain() == false) { + if ((flags & kSecCSApplyEmbeddedPolicy) && code->trustedSigningCertChain() == false) { return CSError::cfError(errors, errSecCSSignatureUntrusted); } -#endif END_CSAPI_ERRORS @@ -251,7 +255,7 @@ OSStatus SecCodeMapMemory(SecStaticCodeRef codeRef, SecCSFlags flags) MacOSError::throwMe(errSecCSNoMainExecutable); } - auto_ptr arch(execImage->architecture()); + unique_ptr arch(execImage->architecture()); if (arch.get() == NULL) { MacOSError::throwMe(errSecCSNoMainExecutable); } diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.h b/OSX/libsecurity_codesigning/lib/SecStaticCode.h index b053623e..53712cbf 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.h +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.h @@ -178,9 +178,10 @@ CF_ENUM(uint32_t) { kSecCSRestrictSymlinks = 1 << 7, kSecCSRestrictToAppLike = 1 << 8, kSecCSRestrictSidebandData = 1 << 9, - kSecCSUseSoftwareSigningCert = 1 << 10, + kSecCSUseSoftwareSigningCert = 1 << 10, kSecCSValidatePEH = 1 << 11, kSecCSSingleThreaded = 1 << 12, + // NOTE: These values have gaps for internal usage. }; OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCode, SecCSFlags flags, diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.cpp b/OSX/libsecurity_codesigning/lib/StaticCode.cpp index 2d5a3e90..033ef507 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/StaticCode.cpp @@ -67,6 +67,7 @@ #include #include #include +#import namespace Security { @@ -109,11 +110,7 @@ SecStaticCode::SecStaticCode(DiskRep *rep, uint32_t flags) mOuterScope(NULL), mResourceScope(NULL), mDesignatedReq(NULL), mGotResourceBase(false), mMonitor(NULL), mLimitedAsync(NULL), mFlags(flags), mNotarizationChecked(false), mStaplingChecked(false), mNotarizationDate(NAN) -#if TARGET_OS_OSX - , mEvalDetails(NULL) -#else , mTrustedSigningCertChain(false) -#endif { CODESIGN_STATIC_CREATE(this, rep); @@ -126,7 +123,7 @@ SecStaticCode::SecStaticCode(DiskRep *rep, uint32_t flags) // // Clean up a SecStaticCode object // -SecStaticCode::~SecStaticCode() throw() +SecStaticCode::~SecStaticCode() _NOEXCEPT try { ::free(const_cast(mDesignatedReq)); delete mResourcesValidContext; @@ -361,9 +358,6 @@ void SecStaticCode::resetValidity() mNotarizationChecked = false; mStaplingChecked = false; mNotarizationDate = NAN; -#if TARGET_OS_OSX - mEvalDetails = NULL; -#endif mRep->flush(); #if TARGET_OS_OSX @@ -771,297 +765,292 @@ bool SecStaticCode::verifySignature() DTRACK(CODESIGN_EVAL_STATIC_SIGNATURE, this, (char*)this->mainExecutablePath().c_str()); #if TARGET_OS_OSX - // decode CMS and extract SecTrust for verification - CFRef cms; - MacOSError::check(CMSDecoderCreate(&cms.aref())); // create decoder - CFDataRef sig = this->signature(); - MacOSError::check(CMSDecoderUpdateMessage(cms, CFDataGetBytePtr(sig), CFDataGetLength(sig))); - this->codeDirectory(); // load CodeDirectory (sets mDir) - MacOSError::check(CMSDecoderSetDetachedContent(cms, mBaseDir)); - MacOSError::check(CMSDecoderFinalizeMessage(cms)); - MacOSError::check(CMSDecoderSetSearchKeychain(cms, cfEmptyArray())); - CFRef vf_policies(createVerificationPolicies()); - CFRef ts_policies(createTimeStampingAndRevocationPolicies()); - - CMSSignerStatus status; - MacOSError::check(CMSDecoderCopySignerStatus(cms, 0, vf_policies, - false, &status, &mTrust.aref(), NULL)); - - if (status != kCMSSignerValid) { - const char *reason; - switch (status) { - case kCMSSignerUnsigned: reason="kCMSSignerUnsigned"; break; - case kCMSSignerNeedsDetachedContent: reason="kCMSSignerNeedsDetachedContent"; break; - case kCMSSignerInvalidSignature: reason="kCMSSignerInvalidSignature"; break; - case kCMSSignerInvalidCert: reason="kCMSSignerInvalidCert"; break; - case kCMSSignerInvalidIndex: reason="kCMSSignerInvalidIndex"; break; - default: reason="unknown"; break; - } - Security::Syslog::error("CMSDecoderCopySignerStatus failed with %s error (%d)", - reason, (int)status); - MacOSError::throwMe(errSecCSSignatureFailed); - } - - // retrieve auxiliary v1 data bag and verify against current state - CFRef hashAgilityV1; - switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgility(cms, 0, &hashAgilityV1.aref())) { - case noErr: - if (hashAgilityV1) { - CFRef hashDict = makeCFDictionaryFrom(hashAgilityV1); - CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes"))); - CFArrayRef myCdList = this->cdHashes(); - - /* Note that this is not very "agile": There's no way to calculate the exact - * list for comparison if it contains hash algorithms we don't know yet... */ - if (cdList == NULL || !CFEqual(cdList, myCdList)) - MacOSError::throwMe(errSecCSSignatureFailed); + if (!(mValidationFlags & kSecCSApplyEmbeddedPolicy)) { + // decode CMS and extract SecTrust for verification + CFRef cms; + MacOSError::check(CMSDecoderCreate(&cms.aref())); // create decoder + CFDataRef sig = this->signature(); + MacOSError::check(CMSDecoderUpdateMessage(cms, CFDataGetBytePtr(sig), CFDataGetLength(sig))); + this->codeDirectory(); // load CodeDirectory (sets mDir) + MacOSError::check(CMSDecoderSetDetachedContent(cms, mBaseDir)); + MacOSError::check(CMSDecoderFinalizeMessage(cms)); + MacOSError::check(CMSDecoderSetSearchKeychain(cms, cfEmptyArray())); + CFRef vf_policies(createVerificationPolicies()); + CFRef ts_policies(createTimeStampingAndRevocationPolicies()); + + CMSSignerStatus status; + MacOSError::check(CMSDecoderCopySignerStatus(cms, 0, vf_policies, + false, &status, &mTrust.aref(), NULL)); + + if (status != kCMSSignerValid) { + const char *reason; + switch (status) { + case kCMSSignerUnsigned: reason="kCMSSignerUnsigned"; break; + case kCMSSignerNeedsDetachedContent: reason="kCMSSignerNeedsDetachedContent"; break; + case kCMSSignerInvalidSignature: reason="kCMSSignerInvalidSignature"; break; + case kCMSSignerInvalidCert: reason="kCMSSignerInvalidCert"; break; + case kCMSSignerInvalidIndex: reason="kCMSSignerInvalidIndex"; break; + default: reason="unknown"; break; + } + Security::Syslog::error("CMSDecoderCopySignerStatus failed with %s error (%d)", + reason, (int)status); + MacOSError::throwMe(errSecCSSignatureFailed); } - break; - case -1: /* CMS used to return this for "no attribute found", so tolerate it. Now returning noErr/NULL */ - break; - default: - MacOSError::throwMe(rc); - } - // retrieve auxiliary v2 data bag and verify against current state - CFRef hashAgilityV2; - switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgilityV2(cms, 0, &hashAgilityV2.aref())) { + // retrieve auxiliary v1 data bag and verify against current state + CFRef hashAgilityV1; + switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgility(cms, 0, &hashAgilityV1.aref())) { case noErr: - if (hashAgilityV2) { - /* Require number of code directoris and entries in the hash agility - * dict to be the same size (no stripping out code directories). - */ - if (CFDictionaryGetCount(hashAgilityV2) != mCodeDirectories.size()) { + if (hashAgilityV1) { + CFRef hashDict = makeCFDictionaryFrom(hashAgilityV1); + CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes"))); + CFArrayRef myCdList = this->cdHashes(); + + /* Note that this is not very "agile": There's no way to calculate the exact + * list for comparison if it contains hash algorithms we don't know yet... */ + if (cdList == NULL || !CFEqual(cdList, myCdList)) MacOSError::throwMe(errSecCSSignatureFailed); - } + } + break; + case -1: /* CMS used to return this for "no attribute found", so tolerate it. Now returning noErr/NULL */ + break; + default: + MacOSError::throwMe(rc); + } - /* Require every cdhash of every code directory whose hash - * algorithm we know to be in the agility dictionary. - * - * We check untruncated cdhashes here because we can. - */ - bool foundOurs = false; - for (auto& entry : mCodeDirectories) { - SECOidTag tag = CodeDirectorySet::SECOidTagForAlgorithm(entry.first); - - if (tag == SEC_OID_UNKNOWN) { - // Unknown hash algorithm, ignore. - continue; + // retrieve auxiliary v2 data bag and verify against current state + CFRef hashAgilityV2; + switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgilityV2(cms, 0, &hashAgilityV2.aref())) { + case noErr: + if (hashAgilityV2) { + /* Require number of code directoris and entries in the hash agility + * dict to be the same size (no stripping out code directories). + */ + if (CFDictionaryGetCount(hashAgilityV2) != mCodeDirectories.size()) { + MacOSError::throwMe(errSecCSSignatureFailed); } - CFRef key = makeCFNumber(int(tag)); - CFRef entryCdhash; - entryCdhash = (CFDataRef)CFDictionaryGetValue(hashAgilityV2, (void*)key.get()); - - CodeDirectory const *cd = (CodeDirectory const*)CFDataGetBytePtr(entry.second); - CFRef ourCdhash = cd->cdhash(false); // Untruncated cdhash! - if (!CFEqual(entryCdhash, ourCdhash)) { - MacOSError::throwMe(errSecCSSignatureFailed); + /* Require every cdhash of every code directory whose hash + * algorithm we know to be in the agility dictionary. + * + * We check untruncated cdhashes here because we can. + */ + bool foundOurs = false; + for (auto& entry : mCodeDirectories) { + SECOidTag tag = CodeDirectorySet::SECOidTagForAlgorithm(entry.first); + + if (tag == SEC_OID_UNKNOWN) { + // Unknown hash algorithm, ignore. + continue; + } + + CFRef key = makeCFNumber(int(tag)); + CFRef entryCdhash; + entryCdhash = (CFDataRef)CFDictionaryGetValue(hashAgilityV2, (void*)key.get()); + + CodeDirectory const *cd = (CodeDirectory const*)CFDataGetBytePtr(entry.second); + CFRef ourCdhash = cd->cdhash(false); // Untruncated cdhash! + if (!CFEqual(entryCdhash, ourCdhash)) { + MacOSError::throwMe(errSecCSSignatureFailed); + } + + if (entry.first == this->hashAlgorithm()) { + foundOurs = true; + } } - if (entry.first == this->hashAlgorithm()) { - foundOurs = true; + /* Require the cdhash of our chosen code directory to be in the dictionary. + * In theory, the dictionary could be full of unsupported cdhashes, but we + * really want ours, which is bound to be supported, to be covered. + */ + if (!foundOurs) { + MacOSError::throwMe(errSecCSSignatureFailed); } } + break; + case -1: /* CMS used to return this for "no attribute found", so tolerate it. Now returning noErr/NULL */ + break; + default: + MacOSError::throwMe(rc); + } - /* Require the cdhash of our chosen code directory to be in the dictionary. - * In theory, the dictionary could be full of unsupported cdhashes, but we - * really want ours, which is bound to be supported, to be covered. - */ - if (!foundOurs) { - MacOSError::throwMe(errSecCSSignatureFailed); - } - } - break; - case -1: /* CMS used to return this for "no attribute found", so tolerate it. Now returning noErr/NULL */ + // internal signing time (as specified by the signer; optional) + mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) + switch (OSStatus rc = CMSDecoderCopySignerSigningTime(cms, 0, &mSigningTime)) { + case errSecSuccess: + case errSecSigningTimeMissing: break; default: + Security::Syslog::error("Could not get signing time (error %d)", (int)rc); MacOSError::throwMe(rc); - } - - // internal signing time (as specified by the signer; optional) - mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) - switch (OSStatus rc = CMSDecoderCopySignerSigningTime(cms, 0, &mSigningTime)) { - case errSecSuccess: - case errSecSigningTimeMissing: - break; - default: - Security::Syslog::error("Could not get signing time (error %d)", (int)rc); - MacOSError::throwMe(rc); - } - - // certified signing time (as specified by a TSA; optional) - mSigningTimestamp = 0; - switch (OSStatus rc = CMSDecoderCopySignerTimestampWithPolicy(cms, ts_policies, 0, &mSigningTimestamp)) { - case errSecSuccess: - case errSecTimestampMissing: - break; - default: - Security::Syslog::error("Could not get timestamp (error %d)", (int)rc); - MacOSError::throwMe(rc); - } + } - // set up the environment for SecTrust - if (mValidationFlags & kSecCSNoNetworkAccess) { - MacOSError::check(SecTrustSetNetworkFetchAllowed(mTrust,false)); // no network? - } - MacOSError::check(SecTrustSetKeychainsAllowed(mTrust, false)); + // certified signing time (as specified by a TSA; optional) + mSigningTimestamp = 0; + switch (OSStatus rc = CMSDecoderCopySignerTimestampWithPolicy(cms, ts_policies, 0, &mSigningTimestamp)) { + case errSecSuccess: + case errSecTimestampMissing: + break; + default: + Security::Syslog::error("Could not get timestamp (error %d)", (int)rc); + MacOSError::throwMe(rc); + } - CSSM_APPLE_TP_ACTION_DATA actionData = { - CSSM_APPLE_TP_ACTION_VERSION, // version of data structure - 0 // action flags - }; + // set up the environment for SecTrust + if (mValidationFlags & kSecCSNoNetworkAccess) { + MacOSError::check(SecTrustSetNetworkFetchAllowed(mTrust,false)); // no network? + } + MacOSError::check(SecTrustSetKeychainsAllowed(mTrust, false)); - if (!(mValidationFlags & kSecCSCheckTrustedAnchors)) { - /* no need to evaluate anchor trust when building cert chain */ - MacOSError::check(SecTrustSetAnchorCertificates(mTrust, cfEmptyArray())); // no anchors - actionData.ActionFlags |= CSSM_TP_ACTION_IMPLICIT_ANCHORS; // action flags - } + CSSM_APPLE_TP_ACTION_DATA actionData = { + CSSM_APPLE_TP_ACTION_VERSION, // version of data structure + 0 // action flags + }; - for (;;) { // at most twice - MacOSError::check(SecTrustSetParameters(mTrust, - CSSM_TP_ACTION_DEFAULT, CFTempData(&actionData, sizeof(actionData)))); + if (!(mValidationFlags & kSecCSCheckTrustedAnchors)) { + /* no need to evaluate anchor trust when building cert chain */ + MacOSError::check(SecTrustSetAnchorCertificates(mTrust, cfEmptyArray())); // no anchors + actionData.ActionFlags |= CSSM_TP_ACTION_IMPLICIT_ANCHORS; // action flags + } - // evaluate trust and extract results - SecTrustResultType trustResult; - MacOSError::check(SecTrustEvaluate(mTrust, &trustResult)); - MacOSError::check(SecTrustGetResult(mTrust, &trustResult, &mCertChain.aref(), &mEvalDetails)); - - // if this is an Apple developer cert.... - if (teamID() && SecStaticCode::isAppleDeveloperCert(mCertChain)) { - CFRef teamIDFromCert; - if (CFArrayGetCount(mCertChain) > 0) { - /* Note that SecCertificateCopySubjectComponent sets the out parameter to NULL if there is no field present */ - MacOSError::check(SecCertificateCopySubjectComponent((SecCertificateRef)CFArrayGetValueAtIndex(mCertChain, Requirement::leafCert), - &CSSMOID_OrganizationalUnitName, - &teamIDFromCert.aref())); - - if (teamIDFromCert) { - CFRef teamIDFromCD = CFStringCreateWithCString(NULL, teamID(), kCFStringEncodingUTF8); - if (!teamIDFromCD) { - Security::Syslog::error("Could not get team identifier (%s)", teamID()); - MacOSError::throwMe(errSecCSInvalidTeamIdentifier); + for (;;) { // at most twice + MacOSError::check(SecTrustSetParameters(mTrust, + CSSM_TP_ACTION_DEFAULT, CFTempData(&actionData, sizeof(actionData)))); + + // evaluate trust and extract results + SecTrustResultType trustResult; + MacOSError::check(SecTrustEvaluate(mTrust, &trustResult)); + mCertChain.take(copyCertChain(mTrust)); + + // if this is an Apple developer cert.... + if (teamID() && SecStaticCode::isAppleDeveloperCert(mCertChain)) { + CFRef teamIDFromCert; + if (CFArrayGetCount(mCertChain) > 0) { + SecCertificateRef leaf = (SecCertificateRef)CFArrayGetValueAtIndex(mCertChain, Requirement::leafCert); + CFArrayRef organizationalUnits = SecCertificateCopyOrganizationalUnit(leaf); + if (organizationalUnits) { + teamIDFromCert.take((CFStringRef)CFRetain(CFArrayGetValueAtIndex(organizationalUnits, 0))); + CFRelease(organizationalUnits); + } else { + teamIDFromCert = NULL; } - if (CFStringCompare(teamIDFromCert, teamIDFromCD, 0) != kCFCompareEqualTo) { - Security::Syslog::error("Team identifier in the signing certificate (%s) does not match the team identifier (%s) in the code directory", - cfString(teamIDFromCert).c_str(), teamID()); - MacOSError::throwMe(errSecCSBadTeamIdentifier); + if (teamIDFromCert) { + CFRef teamIDFromCD = CFStringCreateWithCString(NULL, teamID(), kCFStringEncodingUTF8); + if (!teamIDFromCD) { + Security::Syslog::error("Could not get team identifier (%s)", teamID()); + MacOSError::throwMe(errSecCSInvalidTeamIdentifier); + } + + if (CFStringCompare(teamIDFromCert, teamIDFromCD, 0) != kCFCompareEqualTo) { + Security::Syslog::error("Team identifier in the signing certificate (%s) does not match the team identifier (%s) in the code directory", + cfString(teamIDFromCert).c_str(), teamID()); + MacOSError::throwMe(errSecCSBadTeamIdentifier); + } } } } - } - CODESIGN_EVAL_STATIC_SIGNATURE_RESULT(this, trustResult, mCertChain ? (int)CFArrayGetCount(mCertChain) : 0); - switch (trustResult) { - case kSecTrustResultProceed: - case kSecTrustResultUnspecified: - break; // success - case kSecTrustResultDeny: - MacOSError::throwMe(CSSMERR_APPLETP_TRUST_SETTING_DENY); // user reject - case kSecTrustResultInvalid: - assert(false); // should never happen - MacOSError::throwMe(CSSMERR_TP_NOT_TRUSTED); - default: - { - OSStatus result; - MacOSError::check(SecTrustGetCssmResultCode(mTrust, &result)); - // if we have a valid timestamp, CMS validates against (that) signing time and all is well. - // If we don't have one, may validate against *now*, and must be able to tolerate expiration. - if (mSigningTimestamp == 0) { // no timestamp available - if (((result == CSSMERR_TP_CERT_EXPIRED) || (result == CSSMERR_TP_CERT_NOT_VALID_YET)) - && !(actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED)) { - CODESIGN_EVAL_STATIC_SIGNATURE_EXPIRED(this); - actionData.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED; // (this also allows postdated certs) - continue; // retry validation while tolerating expiration + CODESIGN_EVAL_STATIC_SIGNATURE_RESULT(this, trustResult, mCertChain ? (int)CFArrayGetCount(mCertChain) : 0); + switch (trustResult) { + case kSecTrustResultProceed: + case kSecTrustResultUnspecified: + break; // success + case kSecTrustResultDeny: + MacOSError::throwMe(CSSMERR_APPLETP_TRUST_SETTING_DENY); // user reject + case kSecTrustResultInvalid: + assert(false); // should never happen + MacOSError::throwMe(CSSMERR_TP_NOT_TRUSTED); + default: + { + OSStatus result; + MacOSError::check(SecTrustGetCssmResultCode(mTrust, &result)); + // if we have a valid timestamp, CMS validates against (that) signing time and all is well. + // If we don't have one, may validate against *now*, and must be able to tolerate expiration. + if (mSigningTimestamp == 0) { // no timestamp available + if (((result == CSSMERR_TP_CERT_EXPIRED) || (result == CSSMERR_TP_CERT_NOT_VALID_YET)) + && !(actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED)) { + CODESIGN_EVAL_STATIC_SIGNATURE_EXPIRED(this); + actionData.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED; // (this also allows postdated certs) + continue; // retry validation while tolerating expiration + } } + if (checkfix41082220(result)) { + break; // success + } + Security::Syslog::error("SecStaticCode: verification failed (trust result %d, error %d)", trustResult, (int)result); + MacOSError::throwMe(result); } - if (checkfix41082220(result)) { - break; // success - } - Security::Syslog::error("SecStaticCode: verification failed (trust result %d, error %d)", trustResult, (int)result); - MacOSError::throwMe(result); } - } - if (mSigningTimestamp) { - CFIndex rootix = CFArrayGetCount(mCertChain); - if (SecCertificateRef mainRoot = SecCertificateRef(CFArrayGetValueAtIndex(mCertChain, rootix-1))) - if (isAppleCA(mainRoot)) { - // impose policy: if the signature itself draws to Apple, then so must the timestamp signature - CFRef tsCerts; - OSStatus result = CMSDecoderCopySignerTimestampCertificates(cms, 0, &tsCerts.aref()); - if (result) { - Security::Syslog::error("SecStaticCode: could not get timestamp certificates (error %d)", (int)result); - MacOSError::check(result); + if (mSigningTimestamp) { + CFIndex rootix = CFArrayGetCount(mCertChain); + if (SecCertificateRef mainRoot = SecCertificateRef(CFArrayGetValueAtIndex(mCertChain, rootix-1))) + if (isAppleCA(mainRoot)) { + // impose policy: if the signature itself draws to Apple, then so must the timestamp signature + CFRef tsCerts; + OSStatus result = CMSDecoderCopySignerTimestampCertificates(cms, 0, &tsCerts.aref()); + if (result) { + Security::Syslog::error("SecStaticCode: could not get timestamp certificates (error %d)", (int)result); + MacOSError::check(result); + } + CFIndex tsn = CFArrayGetCount(tsCerts); + bool good = tsn > 0 && isAppleCA(SecCertificateRef(CFArrayGetValueAtIndex(tsCerts, tsn-1))); + if (!good) { + result = CSSMERR_TP_NOT_TRUSTED; + Security::Syslog::error("SecStaticCode: timestamp policy verification failed (error %d)", (int)result); + MacOSError::throwMe(result); + } } - CFIndex tsn = CFArrayGetCount(tsCerts); - bool good = tsn > 0 && isAppleCA(SecCertificateRef(CFArrayGetValueAtIndex(tsCerts, tsn-1))); - if (!good) { - result = CSSMERR_TP_NOT_TRUSTED; - Security::Syslog::error("SecStaticCode: timestamp policy verification failed (error %d)", (int)result); - MacOSError::throwMe(result); - } - } + } + + return actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED; } - return actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED; - } -#else - // Do some pre-verification initialization - CFDataRef sig = this->signature(); - this->codeDirectory(); // load CodeDirectory (sets mDir) - mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) - - CFRef attrs; - CFRef vf_policies(createVerificationPolicies()); - - // Verify the CMS signature against mBaseDir (SHA1) - MacOSError::check(SecCMSVerifyCopyDataAndAttributes(sig, mBaseDir, vf_policies, &mTrust.aref(), NULL, &attrs.aref())); - - // Copy the signing time - mSigningTime = SecTrustGetVerifyTime(mTrust); - - // Validate the cert chain - SecTrustResultType trustResult; - MacOSError::check(SecTrustEvaluate(mTrust, &trustResult)); - - // retrieve auxiliary data bag and verify against current state - CFRef hashBag; - hashBag = CFDataRef(CFDictionaryGetValue(attrs, kSecCMSHashAgility)); - if (hashBag) { - CFRef hashDict = makeCFDictionaryFrom(hashBag); - CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes"))); - CFArrayRef myCdList = this->cdHashes(); - if (cdList == NULL || !CFEqual(cdList, myCdList)) - MacOSError::throwMe(errSecCSSignatureFailed); - } + } else +#endif + { + // Do some pre-verification initialization + CFDataRef sig = this->signature(); + this->codeDirectory(); // load CodeDirectory (sets mDir) + mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) - /* - * Populate mCertChain with the certs. If we failed validation, the - * signer's cert will be checked installed provisioning profiles as an - * alternative to verification against the policy for store-signed binaries - */ - SecCertificateRef leafCert = SecTrustGetCertificateAtIndex(mTrust, 0); - if (leafCert != NULL) { - CFIndex count = SecTrustGetCertificateCount(mTrust); - - CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, count, - &kCFTypeArrayCallBacks); - - CFArrayAppendValue(certs, leafCert); - for (CFIndex i = 1; i < count; ++i) { - CFArrayAppendValue(certs, SecTrustGetCertificateAtIndex(mTrust, i)); - } - - mCertChain.take((CFArrayRef)certs); - } - - // Did we implicitly trust the signer? - mTrustedSigningCertChain = (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed); + CFRef attrs; + CFRef vf_policies(createVerificationPolicies()); - return false; // XXX: Not checking for expired certs -#endif + // Verify the CMS signature against mBaseDir (SHA1) + MacOSError::check(SecCMSVerifyCopyDataAndAttributes(sig, mBaseDir, vf_policies, &mTrust.aref(), NULL, &attrs.aref())); + + // Copy the signing time + mSigningTime = SecTrustGetVerifyTime(mTrust); + + // Validate the cert chain + SecTrustResultType trustResult; + MacOSError::check(SecTrustEvaluate(mTrust, &trustResult)); + + // retrieve auxiliary data bag and verify against current state + CFRef hashBag; + hashBag = CFDataRef(CFDictionaryGetValue(attrs, kSecCMSHashAgility)); + if (hashBag) { + CFRef hashDict = makeCFDictionaryFrom(hashBag); + CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes"))); + CFArrayRef myCdList = this->cdHashes(); + if (cdList == NULL || !CFEqual(cdList, myCdList)) + MacOSError::throwMe(errSecCSSignatureFailed); + } + + /* + * Populate mCertChain with the certs. If we failed validation, the + * signer's cert will be checked installed provisioning profiles as an + * alternative to verification against the policy for store-signed binaries + */ + mCertChain.take(copyCertChain(mTrust)); + + // Did we implicitly trust the signer? + mTrustedSigningCertChain = (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed); + + return false; // XXX: Not checking for expired certs + } } #if TARGET_OS_OSX @@ -1084,6 +1073,11 @@ CFArrayRef SecStaticCode::createVerificationPolicies() return makeCFArray(1, ssRef.get()); } #if TARGET_OS_OSX + if (mValidationFlags & kSecCSApplyEmbeddedPolicy) { + CFRef iOSRef = SecPolicyCreateiPhoneApplicationSigning(); + return makeCFArray(1, iOSRef.get()); + } + CFRef core; MacOSError::check(SecPolicyCopy(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_CODE_SIGNING, &core.aref())); @@ -1134,6 +1128,25 @@ CFArrayRef SecStaticCode::createTimeStampingAndRevocationPolicies() } +CFArrayRef SecStaticCode::copyCertChain(SecTrustRef trust) +{ + SecCertificateRef leafCert = SecTrustGetCertificateAtIndex(trust, 0); + if (leafCert != NULL) { + CFIndex count = SecTrustGetCertificateCount(trust); + + CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, count, + &kCFTypeArrayCallBacks); + + CFArrayAppendValue(certs, leafCert); + for (CFIndex i = 1; i < count; ++i) { + CFArrayAppendValue(certs, SecTrustGetCertificateAtIndex(trust, i)); + } + + return certs; + } + return NULL; +} + // // Validate a particular sealed, cached resource against its (special) CodeDirectory slot. @@ -1242,6 +1255,14 @@ void SecStaticCode::validateResources(SecCSFlags flags) } if (doit) { + string root = cfStringRelease(copyCanonicalPath()); + bool itemIsOnRootFS = isOnRootFilesystem(root.c_str()); + bool requestForcedValidation = (mValidationFlags & kSecCSSkipRootVolumeExceptions); + bool useRootFSPolicy = itemIsOnRootFS && !requestForcedValidation; + + secinfo("staticCode", "performing resource validation for %s (%d, %d, %d)", root.c_str(), + itemIsOnRootFS, requestForcedValidation, useRootFSPolicy); + if (mLimitedAsync == NULL) { bool runMultiThreaded = ((flags & kSecCSSingleThreaded) == kSecCSSingleThreaded) ? false : (diskRep()->fd().mediumType() == kIOPropertyMediumTypeSolidStateKey); @@ -1264,13 +1285,15 @@ void SecStaticCode::validateResources(SecCSFlags flags) // check for weak resource rules bool strict = flags & kSecCSStrictValidate; - if (strict) { - if (hasWeakResourceRules(rules, version, mAllowOmissions)) - if (mTolerateErrors.find(errSecCSWeakResourceRules) == mTolerateErrors.end()) - MacOSError::throwMe(errSecCSWeakResourceRules); - if (version == 1) - if (mTolerateErrors.find(errSecCSWeakResourceEnvelope) == mTolerateErrors.end()) - MacOSError::throwMe(errSecCSWeakResourceEnvelope); + if (!useRootFSPolicy) { + if (strict) { + if (hasWeakResourceRules(rules, version, mAllowOmissions)) + if (mTolerateErrors.find(errSecCSWeakResourceRules) == mTolerateErrors.end()) + MacOSError::throwMe(errSecCSWeakResourceRules); + if (version == 1) + if (mTolerateErrors.find(errSecCSWeakResourceEnvelope) == mTolerateErrors.end()) + MacOSError::throwMe(errSecCSWeakResourceEnvelope); + } } Dispatch::Group group; @@ -1288,7 +1311,21 @@ void SecStaticCode::validateResources(SecCSFlags flags) bool isSymlink = (ent->fts_info == FTS_SL); void (^validate)() = ^{ - validateResource(files, relpath, isSymlink, *mResourcesValidContext, flags, version); + bool needsValidation = true; + + if (useRootFSPolicy) { + CFRef itemURL = makeCFURL(relpath, false, resourceBase()); + string itemPath = cfString(itemURL); + if (isOnRootFilesystem(itemPath.c_str())) { + secinfo("staticCode", "resource validation on root volume skipped: %s", itemPath.c_str()); + needsValidation = false; + } + } + + if (needsValidation) { + secinfo("staticCode", "performing resource validation on item: %s", relpath.c_str()); + validateResource(files, relpath, isSymlink, *mResourcesValidContext, flags, version); + } reportProgress(); }; @@ -1296,10 +1333,15 @@ void SecStaticCode::validateResources(SecCSFlags flags) }); group.wait(); // wait until all async resources have been validated as well - unsigned leftovers = unsigned(CFDictionaryGetCount(resourceMap)); - if (leftovers > 0) { - secinfo("staticCode", "%d sealed resource(s) not found in code", int(leftovers)); - CFDictionaryApplyFunction(resourceMap, SecStaticCode::checkOptionalResource, mResourcesValidContext); + if (useRootFSPolicy) { + // It's ok to allow leftovers on the root filesystem for now. + } else { + // Look through the leftovers and make sure they're all properly optional resources. + unsigned leftovers = unsigned(CFDictionaryGetCount(resourceMap)); + if (leftovers > 0) { + secinfo("staticCode", "%d sealed resource(s) not found in code", int(leftovers)); + CFDictionaryApplyFunction(resourceMap, SecStaticCode::checkOptionalResource, mResourcesValidContext); + } } // now check for any errors found in the reporting context @@ -2070,7 +2112,7 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) //DR not currently supported on iOS #if TARGET_OS_OSX - try { + try { if (const Requirements *reqs = this->internalRequirements()) { CFDictionaryAddValue(dict, kSecCodeInfoRequirements, CFTempString(Dumper::dump(reqs))); @@ -2090,10 +2132,26 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) #endif try { - if (CFDataRef ent = this->component(cdEntitlementSlot)) { - CFDictionaryAddValue(dict, kSecCodeInfoEntitlements, ent); - if (CFDictionaryRef entdict = this->entitlements()) - CFDictionaryAddValue(dict, kSecCodeInfoEntitlementsDict, entdict); + if (CFDataRef ent = this->component(cdEntitlementSlot)) { + CFDictionaryAddValue(dict, kSecCodeInfoEntitlements, ent); + if (CFDictionaryRef entdict = this->entitlements()) { + if (needsCatalystEntitlementFixup(entdict)) { + // If this entitlement dictionary needs catalyst entitlements, make a copy and stick that into the + // output dictionary instead. + secinfo("staticCode", "%p fixed catalyst entitlements", this); + CFRef tempEntitlements = makeCFMutableDictionary(entdict); + updateCatalystEntitlements(tempEntitlements); + CFRef newEntitlements = CFDictionaryCreateCopy(NULL, tempEntitlements); + if (newEntitlements) { + CFDictionaryAddValue(dict, kSecCodeInfoEntitlementsDict, newEntitlements.get()); + } else { + secerror("%p unable to fixup entitlement dictionary", this); + CFDictionaryAddValue(dict, kSecCodeInfoEntitlementsDict, entdict); + } + } else { + CFDictionaryAddValue(dict, kSecCodeInfoEntitlementsDict, entdict); + } + } } } catch (...) { } @@ -2123,6 +2181,10 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) secerror("Error creating date from timestamp: %f", mNotarizationDate); } } + if (this->codeDirectory()) { + uint32_t version = this->codeDirectory()->version; + CFDictionaryAddValue(dict, kSecCodeInfoSignatureVersion, CFTempNumber(version)); + } } if (flags & kSecCSCalculateCMSDigest) { @@ -2248,8 +2310,9 @@ void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) reportEvent(CFSTR("prepared"), NULL); // resources: once for all architectures - if (!(flags & kSecCSDoNotValidateResources)) + if (!(flags & kSecCSDoNotValidateResources)) { this->validateResources(flags); + } // perform strict validation if desired if (flags & kSecCSStrictValidate) { diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.h b/OSX/libsecurity_codesigning/lib/StaticCode.h index 56726824..ae4cc602 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.h +++ b/OSX/libsecurity_codesigning/lib/StaticCode.h @@ -107,7 +107,7 @@ public: static SecCode *optionalDynamic(SecStaticCodeRef ref); // extract SecCodeRef or NULL if static SecStaticCode(DiskRep *rep, uint32_t flags = 0); - virtual ~SecStaticCode() throw(); + virtual ~SecStaticCode() _NOEXCEPT; void initializeFromParent(const SecStaticCode& parent); @@ -200,9 +200,7 @@ public: CFDictionaryRef signingInformation(SecCSFlags flags); // omnibus information-gathering API (creates new dictionary) static bool isAppleDeveloperCert(CFArrayRef certs); // determines if this is an apple developer certificate for library validation -#if !TARGET_OS_OSX bool trustedSigningCertChain() { return mTrustedSigningCertChain; } -#endif void handleOtherArchitectures(void (^handle)(SecStaticCode* other)); @@ -231,6 +229,7 @@ private: void validateOtherVersions(CFURLRef path, SecCSFlags flags, SecRequirementRef req, SecStaticCode *code); bool checkfix30814861(string path, bool addition); bool checkfix41082220(OSStatus result); + CFArrayRef copyCertChain(SecTrustRef trust); ResourceBuilder *mCheckfix30814861builder1; dispatch_once_t mCheckfix30814861builder1_once; @@ -306,11 +305,7 @@ private: // signature verification outcome (mTrust == NULL => not done yet) CFRef mTrust; // outcome of crypto validation (valid or not) CFRef mCertChain; -#if TARGET_OS_OSX - CSSM_TP_APPLE_EVIDENCE_INFO *mEvalDetails; -#else bool mTrustedSigningCertChain; -#endif }; diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp index 7c490970..efc14c1c 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp @@ -198,7 +198,7 @@ void BundleDiskRep::setup(const Context *ctx) // we're getting desperate here. Perhaps an oldish-style installer package? Look for a *.dist file std::string distFile = findDistFile(this->resourcesRootPath()); if (!distFile.empty()) { - mMainExecutableURL = makeCFURL(distFile); + mMainExecutableURL.take(makeCFURL(distFile)); mExecRep = new FileDiskRep(this->mainExecutablePath().c_str()); checkPlainFile(mExecRep->fd(), this->mainExecutablePath()); mInstallerPackage = true; diff --git a/OSX/libsecurity_codesigning/lib/codedirectory.cpp b/OSX/libsecurity_codesigning/lib/codedirectory.cpp index 4d3c1c80..9c559dcd 100644 --- a/OSX/libsecurity_codesigning/lib/codedirectory.cpp +++ b/OSX/libsecurity_codesigning/lib/codedirectory.cpp @@ -419,5 +419,6 @@ const SecCodeDirectoryFlagTable kSecCodeDirectoryFlagTable[] = { { "enforcement", kSecCodeSignatureEnforcement, true }, { "library-validation", kSecCodeSignatureLibraryValidation, true }, { "runtime", kSecCodeSignatureRuntime, true }, + { "linker-signed", kSecCodeSignatureLinkerSigned, true }, { NULL } }; diff --git a/OSX/libsecurity_codesigning/lib/cserror.cpp b/OSX/libsecurity_codesigning/lib/cserror.cpp index 1e6d98e7..907e1ee3 100644 --- a/OSX/libsecurity_codesigning/lib/cserror.cpp +++ b/OSX/libsecurity_codesigning/lib/cserror.cpp @@ -34,7 +34,7 @@ namespace CodeSigning { // // We need a nothrow destructor // -CSError::~CSError() throw () +CSError::~CSError() _NOEXCEPT { } diff --git a/OSX/libsecurity_codesigning/lib/cserror.h b/OSX/libsecurity_codesigning/lib/cserror.h index f46528f1..41b97ac3 100644 --- a/OSX/libsecurity_codesigning/lib/cserror.h +++ b/OSX/libsecurity_codesigning/lib/cserror.h @@ -42,7 +42,7 @@ class CSError : public MacOSError { public: CSError(OSStatus rc) : MacOSError(rc) { } CSError(OSStatus rc, CFDictionaryRef dict) : MacOSError(rc), mInfoDict(dict) { } // takes dict - ~CSError() throw (); + ~CSError() _NOEXCEPT; static void throwMe(OSStatus rc) __attribute__((noreturn)); static void throwMe(OSStatus rc, CFDictionaryRef info) __attribute__ ((noreturn)); // takes dict diff --git a/OSX/libsecurity_codesigning/lib/cskernel.cpp b/OSX/libsecurity_codesigning/lib/cskernel.cpp index 0d1c4852..0eca9653 100644 --- a/OSX/libsecurity_codesigning/lib/cskernel.cpp +++ b/OSX/libsecurity_codesigning/lib/cskernel.cpp @@ -175,7 +175,7 @@ SecCodeStatus KernelCode::getGuestStatus(SecCode *iguest) { if (ProcessCode *guest = dynamic_cast(iguest)) { uint32_t pFlags; - csops(guest, CS_OPS_STATUS, &pFlags); + csops(guest, CS_OPS_STATUS, &pFlags, sizeof(pFlags)); secinfo("kcode", "guest %p(%d) kernel status 0x%x", guest, guest->pid(), pFlags); return pFlags; } else diff --git a/OSX/libsecurity_codesigning/lib/csprocess.h b/OSX/libsecurity_codesigning/lib/csprocess.h index b0a370e4..0d717e55 100644 --- a/OSX/libsecurity_codesigning/lib/csprocess.h +++ b/OSX/libsecurity_codesigning/lib/csprocess.h @@ -43,7 +43,7 @@ namespace CodeSigning { class ProcessCode : public SecCode { public: ProcessCode(pid_t pid, const audit_token_t* token, PidDiskRep *pidDiskRep = NULL); - ~ProcessCode() throw () { delete mAudit; } + ~ProcessCode() _NOEXCEPT { delete mAudit; } pid_t pid() const { return mPid; } const audit_token_t* audit() const { return mAudit; } diff --git a/OSX/libsecurity_codesigning/lib/csutilities.cpp b/OSX/libsecurity_codesigning/lib/csutilities.cpp index 774b6ee2..2d9c65bf 100644 --- a/OSX/libsecurity_codesigning/lib/csutilities.cpp +++ b/OSX/libsecurity_codesigning/lib/csutilities.cpp @@ -34,13 +34,16 @@ #include #include #include +#include #include #include #include "requirement.h" #include #include #include +#include #include +#include "debugging.h" extern "C" { @@ -85,13 +88,7 @@ void hashOfCertificate(const void *certData, size_t certLength, SHA1::Digest dig void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest) { assert(cert); -#if TARGET_OS_OSX - CSSM_DATA certData; - MacOSError::check(SecCertificateGetData(cert, &certData)); - hashOfCertificate(certData.Data, certData.Length, digest); -#else hashOfCertificate(SecCertificateGetBytePtr(cert), SecCertificateGetLength(cert), digest); -#endif } @@ -112,36 +109,32 @@ bool verifyHash(SecCertificateRef cert, const Hashing::Byte *digest) // bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid) { - assert(cert); - CSSM_DATA *value; - switch (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &oid, &value)) { - case errSecSuccess: - MacOSError::check(SecCertificateReleaseFirstFieldValue(cert, &oid, value)); - return true; // extension found by oid - case errSecUnknownTag: - break; // oid not recognized by CL - continue below - default: - MacOSError::throwMe(rc); // error: fail + CFDataRef oidData = NULL; + CFDataRef data = NULL; + bool isCritical = false; + bool matched = false; + + oidData = CFDataCreateWithBytesNoCopy(NULL, oid.Data, oid.Length, + kCFAllocatorNull); + if (!(cert && oidData)) { + goto out; } - - // check the CL's bag of unrecognized extensions - CSSM_DATA **values; - bool found = false; - if (SecCertificateCopyFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, &values)) - return false; // no unrecognized extensions - no match - if (values) - for (CSSM_DATA **p = values; *p; p++) { - const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)(*p)->Data; - if (oid == ext->extnId) { - found = true; - break; - } - } - MacOSError::check(SecCertificateReleaseFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, values)); - return found; + data = SecCertificateCopyExtensionValue(cert, oidData, &isCritical); + if (data == NULL) { + goto out; + } + matched = true; +out: + if (data) { + CFRelease(data); + } + if (oidData) { + CFRelease(oidData); + } + return matched; } - - + + // // Retrieve X.509 policy extension OIDs, if any. // This currently ignores policy qualifiers. @@ -149,24 +142,16 @@ bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid) bool certificateHasPolicy(SecCertificateRef cert, const CSSM_OID &policyOid) { bool matched = false; - assert(cert); - CSSM_DATA *data; - if (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_CertificatePolicies, &data)) - MacOSError::throwMe(rc); - if (data && data->Data && data->Length == sizeof(CSSM_X509_EXTENSION)) { - const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)data->Data; - assert(ext->format == CSSM_X509_DATAFORMAT_PARSED); - const CE_CertPolicies *policies = (const CE_CertPolicies *)ext->value.parsedValue; - if (policies) - for (unsigned int n = 0; n < policies->numPolicies; n++) { - const CE_PolicyInformation &cp = policies->policies[n]; - if (cp.certPolicyId == policyOid) { - matched = true; - break; - } - } + CFDataRef oidData = CFDataCreateWithBytesNoCopy(NULL, policyOid.Data, policyOid.Length, + kCFAllocatorNull); + if (!(cert && oidData)) { + goto out; + } + matched = SecPolicyCheckCertCertificatePolicy(cert, oidData); +out: + if (oidData) { + CFRelease(oidData); } - SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_PolicyConstraints, data); return matched; } @@ -337,5 +322,18 @@ bool LimitedAsync::perform(Dispatch::Group &groupRef, void (^block)()) { } } +bool isOnRootFilesystem(const char *path) +{ + int rc = 0; + struct statfs sfb; + + rc = statfs(path, &sfb); + if (rc != 0) { + secerror("Unable to check if path is on rootfs: %d, %s", errno, path); + return false; + } + return ((sfb.f_flags & MNT_ROOTFS) == MNT_ROOTFS); +} + } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/csutilities.h b/OSX/libsecurity_codesigning/lib/csutilities.h index bd4408cd..2c9017f3 100644 --- a/OSX/libsecurity_codesigning/lib/csutilities.h +++ b/OSX/libsecurity_codesigning/lib/csutilities.h @@ -225,6 +225,8 @@ private: Dispatch::Semaphore *mResourceSemaphore; }; +// Check if the path is on the root filesystem, protected by the OS. +bool isOnRootFilesystem(const char *path); } // end namespace CodeSigning diff --git a/OSX/libsecurity_codesigning/lib/dirscanner.cpp b/OSX/libsecurity_codesigning/lib/dirscanner.cpp index 15140fac..83d96190 100644 --- a/OSX/libsecurity_codesigning/lib/dirscanner.cpp +++ b/OSX/libsecurity_codesigning/lib/dirscanner.cpp @@ -28,6 +28,8 @@ #include #include "dirscanner.h" +#include + namespace Security { namespace CodeSigning { @@ -157,7 +159,9 @@ void DirValidator::validate(const string &root, OSStatus error) reqMatched.insert(rule); } if (reqMatched.size() != (unsigned long) mRequireCount) { - secinfo("dirval", "matched %lu of %d required rules", reqMatched.size(), mRequireCount); + ostringstream os; + os << "matched " << reqMatched.size() << " of " << mRequireCount << " required rules"; + secinfo("dirval", "%s", os.str().c_str()); MacOSError::throwMe(error); // not all required rules were matched } } diff --git a/OSX/libsecurity_codesigning/lib/machorep.cpp b/OSX/libsecurity_codesigning/lib/machorep.cpp index 02e7faa8..157e6e7a 100644 --- a/OSX/libsecurity_codesigning/lib/machorep.cpp +++ b/OSX/libsecurity_codesigning/lib/machorep.cpp @@ -25,6 +25,7 @@ // machorep - DiskRep mix-in for handling Mach-O main executables // #include "machorep.h" +#include "notarization.h" #include "StaticCode.h" #include "reqmaker.h" #include @@ -53,7 +54,7 @@ MachORep::MachORep(const char *path, const Context *ctx) if (ctx->offset) mExecutable = new Universal(fd(), (size_t)ctx->offset, ctx->size); else if (ctx->arch) { - auto_ptr full(new Universal(fd())); + unique_ptr full(new Universal(fd())); mExecutable = new Universal(fd(), full->archOffset(ctx->arch), full->archLength(ctx->arch)); } else mExecutable = new Universal(fd()); @@ -109,7 +110,7 @@ Universal *MachORep::mainExecutableImage() void MachORep::prepareForSigning(SigningContext &context) { if (context.digestAlgorithms().empty()) { - auto_ptr macho(mainExecutableImage()->architecture()); + unique_ptr macho(mainExecutableImage()->architecture()); uint32_t limit = 0; switch (macho->platform()) { @@ -150,19 +151,22 @@ size_t MachORep::signingBase() size_t MachORep::signingLimit() { - auto_ptr macho(mExecutable->architecture()); + unique_ptr macho(mExecutable->architecture()); return macho->signingExtent(); } bool MachORep::needsExecSeg(const MachO& macho) { uint32_t platform = macho.platform(); - // Everything embedded gets an exec segment. - return platform != 0 && platform != PLATFORM_MACOS; + + // Everything gets an exec segment. This is ignored + // on non-PPL devices, and explicitly wastes some + // space on those devices, but is simpler logic. + return platform != 0; } size_t MachORep::execSegBase(const Architecture *arch) { - auto_ptr macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture()); + unique_ptr macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture()); if (!needsExecSeg(*macho)) { return 0; @@ -187,7 +191,7 @@ size_t MachORep::execSegBase(const Architecture *arch) size_t MachORep::execSegLimit(const Architecture *arch) { - auto_ptr macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture()); + unique_ptr macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture()); if (!needsExecSeg(*macho)) { return 0; @@ -218,7 +222,7 @@ size_t MachORep::execSegLimit(const Architecture *arch) // CFDataRef MachORep::identification() { - std::auto_ptr macho(mainExecutableImage()->architecture()); + std::unique_ptr macho(mainExecutableImage()->architecture()); return identificationFor(macho.get()); } @@ -271,6 +275,12 @@ CFDataRef MachORep::component(CodeDirectory::SpecialSlot slot) EditableDiskRep::RawComponentMap MachORep::createRawComponents() { EditableDiskRep::RawComponentMap blobMap; + + // First call to signingData() caches the result, so this + // _should_ not cause performance issues. + if (NULL == signingData()) { + MacOSError::throwMe(errSecCSUnsigned); + } const EmbeddedSignatureBlob &blobs = *signingData(); for (unsigned int i = 0; i < blobs.count(); ++i) { @@ -304,7 +314,7 @@ CFDataRef MachORep::embeddedComponent(CodeDirectory::SpecialSlot slot) EmbeddedSignatureBlob *MachORep::signingData() { if (!mSigningData) { // fetch and cache - auto_ptr macho(mainExecutableImage()->architecture()); + unique_ptr macho(mainExecutableImage()->architecture()); if (macho.get()) if (const linkedit_data_command *cs = macho->findCodeSignature()) { size_t offset = macho->flip(cs->dataoff); @@ -332,7 +342,7 @@ CFDataRef MachORep::infoPlist() { CFRef info; try { - auto_ptr macho(mainExecutableImage()->architecture()); + unique_ptr macho(mainExecutableImage()->architecture()); if (const section *sect = macho->findSection("__TEXT", "__info_plist")) { if (macho->is64()) { const section_64 *sect64 = reinterpret_cast(sect); @@ -391,7 +401,7 @@ void MachORep::flush() CFDictionaryRef MachORep::diskRepInformation() { - auto_ptr macho (mainExecutableImage()->architecture()); + unique_ptr macho (mainExecutableImage()->architecture()); CFRef info; uint32_t platform = 0; @@ -469,7 +479,7 @@ const Requirements *MachORep::defaultRequirements(const Architecture *arch, cons Requirement *MachORep::libraryRequirements(const Architecture *arch, const SigningContext &ctx) { - auto_ptr macho(mainExecutableImage()->architecture(*arch)); + unique_ptr macho(mainExecutableImage()->architecture(*arch)); Requirement::Maker maker; Requirement::Maker::Chain chain(maker, opOr); @@ -564,6 +574,14 @@ void MachORep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data MacOSError::throwMe(errSecCSInternalError); } +void MachORep::registerStapledTicket() +{ + CFRef data = NULL; + if (mSigningData) { + data.take(mSigningData->component(cdTicketSlot)); + registerStapledTicketInMachO(data); + } +} } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/machorep.h b/OSX/libsecurity_codesigning/lib/machorep.h index ef2181bb..0a904467 100644 --- a/OSX/libsecurity_codesigning/lib/machorep.h +++ b/OSX/libsecurity_codesigning/lib/machorep.h @@ -71,6 +71,7 @@ public: void flush(); // flush cache static bool candidate(UnixPlusPlus::FileDesc &fd); + void registerStapledTicket(); public: static CFDataRef identificationFor(MachO *macho); diff --git a/OSX/libsecurity_codesigning/lib/notarization.cpp b/OSX/libsecurity_codesigning/lib/notarization.cpp index f645fd2e..6587dccd 100644 --- a/OSX/libsecurity_codesigning/lib/notarization.cpp +++ b/OSX/libsecurity_codesigning/lib/notarization.cpp @@ -299,5 +299,15 @@ registerStapledTicketInDMG(CFDataRef ticketData) registerStapledTicketWithSystem(ticketData); } +void +registerStapledTicketInMachO(CFDataRef ticketData) +{ + if (ticketData == NULL) { + return; + } + secinfo("notarization", "successfully found stapled ticket in MachO"); + registerStapledTicketWithSystem(ticketData); +} + } } diff --git a/OSX/libsecurity_codesigning/lib/notarization.h b/OSX/libsecurity_codesigning/lib/notarization.h index 21ae3c16..1e2a22b4 100644 --- a/OSX/libsecurity_codesigning/lib/notarization.h +++ b/OSX/libsecurity_codesigning/lib/notarization.h @@ -44,6 +44,7 @@ bool isNotarized(const Requirement::Context *context); void registerStapledTicketInPackage(const std::string& path); void registerStapledTicketInBundle(const std::string& path); void registerStapledTicketInDMG(CFDataRef ticketData); +void registerStapledTicketInMachO(CFDataRef ticketData); } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/piddiskrep.cpp b/OSX/libsecurity_codesigning/lib/piddiskrep.cpp index 0aeeb81e..7f74d24b 100644 --- a/OSX/libsecurity_codesigning/lib/piddiskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/piddiskrep.cpp @@ -86,10 +86,11 @@ PidDiskRep::fetchData(void) xpc_release(request); xpc_release(conn); - if (!mBundleURL) + if (!mBundleURL) { MacOSError::throwMe(errSecCSNoSuchCode); - - mDataFetched = true; + } + + mDataFetched = true; } diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.cpp b/OSX/libsecurity_codesigning/lib/reqinterp.cpp index 4ff17212..f3970650 100644 --- a/OSX/libsecurity_codesigning/lib/reqinterp.cpp +++ b/OSX/libsecurity_codesigning/lib/reqinterp.cpp @@ -34,10 +34,20 @@ #include #include #include +#include #include "csutilities.h" #include "notarization.h" #include "legacydevid.h" +#define WAITING_FOR_LIB_AMFI_INTERFACE 1 + +#if WAITING_FOR_LIB_AMFI_INTERFACE +#define __mac_syscall __sandbox_ms +#include + +#define AMFI_INTF_CD_HASH_LEN 20 +#endif + namespace Security { namespace CodeSigning { @@ -242,7 +252,6 @@ bool Requirement::Interpreter::entitlementValue(const string &key, const Match & bool Requirement::Interpreter::certFieldValue(const string &key, const Match &match, SecCertificateRef cert) { -// XXX: Not supported on embedded yet due to lack of supporting API #if TARGET_OS_OSX // no cert, no chance if (cert == NULL) @@ -251,32 +260,31 @@ bool Requirement::Interpreter::certFieldValue(const string &key, const Match &ma // a table of recognized keys for the "certificate[foo]" syntax static const struct CertField { const char *name; - const CSSM_OID *oid; + const DERItem *oid; } certFields[] = { - { "subject.C", &CSSMOID_CountryName }, - { "subject.CN", &CSSMOID_CommonName }, - { "subject.D", &CSSMOID_Description }, - { "subject.L", &CSSMOID_LocalityName }, + { "subject.C", &oidCountryName}, + { "subject.CN", &oidCommonName }, + { "subject.D", &oidDescription }, + { "subject.L", &oidLocalityName }, // { "subject.C-L", &CSSMOID_CollectiveLocalityName }, // missing from Security.framework headers - { "subject.O", &CSSMOID_OrganizationName }, - { "subject.C-O", &CSSMOID_CollectiveOrganizationName }, - { "subject.OU", &CSSMOID_OrganizationalUnitName }, - { "subject.C-OU", &CSSMOID_CollectiveOrganizationalUnitName }, - { "subject.ST", &CSSMOID_StateProvinceName }, - { "subject.C-ST", &CSSMOID_CollectiveStateProvinceName }, - { "subject.STREET", &CSSMOID_StreetAddress }, - { "subject.C-STREET", &CSSMOID_CollectiveStreetAddress }, - { "subject.UID", &CSSMOID_UserID }, + { "subject.O", &oidOrganizationName }, + { "subject.C-O", &oidCollectiveOrganizationName }, + { "subject.OU", &oidOrganizationalUnitName}, + { "subject.C-OU", &oidCollectiveOrganizationalUnitName}, + { "subject.ST", &oidStateOrProvinceName}, + { "subject.C-ST", &oidCollectiveStateOrProvinceName }, + { "subject.STREET", &oidStreetAddress }, + { "subject.C-STREET", &oidCollectiveStreetAddress }, + { "subject.UID", &oidUserId }, { NULL, NULL } }; // DN-component single-value match for (const CertField *cf = certFields; cf->name; cf++) if (cf->name == key) { - CFRef value; - OSStatus rc = SecCertificateCopySubjectComponent(cert, cf->oid, &value.aref()); - if (rc) { - secinfo("csinterp", "cert %p lookup for DN.%s failed rc=%d", cert, key.c_str(), (int)rc); + CFRef value(SecCertificateCopySubjectAttributeValue(cert, (DERItem *)cf->oid)); + if (!value.get()) { + secinfo("csinterp", "cert %p lookup for DN.%s failed", cert, key.c_str()); return false; } return match(value); @@ -403,14 +411,15 @@ CFArrayRef Requirement::Interpreter::getAdditionalTrustedAnchors() bool Requirement::Interpreter::appleLocalAnchored() { - static CFArrayRef additionalTrustedCertificates = NULL; + static CFArrayRef additionalTrustedCertificates = NULL; - if (csr_check(CSR_ALLOW_APPLE_INTERNAL)) + if (csr_check(CSR_ALLOW_APPLE_INTERNAL)) { return false; + } - if (mContext->forcePlatform) { - return true; - } + if (mContext->forcePlatform) { + return true; + } static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -430,18 +439,76 @@ bool Requirement::Interpreter::appleLocalAnchored() return false; } +#if WAITING_FOR_LIB_AMFI_INTERFACE +// These bits are here until we get get a new build alias for libamfi-interface. + +#define MAC_AMFI_POLICY_NAME "AMFI" + +#define AMFI_SYSCALL_CDHASH_IN_TRUSTCACHE 95 + +typedef struct amfi_cdhash_in_trustcache_ { + uint8_t cdhash[20]; + uint64_t result; +} amfi_cdhash_in_trustcache_t; + +static int +__amfi_interface_cdhash_in_trustcache(const uint8_t cdhash[], uint64_t* trustcache_result) +{ + amfi_cdhash_in_trustcache_t args; + static_assert(AMFI_INTF_CD_HASH_LEN == sizeof(args.cdhash), "Error: cdhash length mismatch"); + int err; + memcpy(args.cdhash, cdhash, sizeof(args.cdhash)); + args.result = 0; + err = __mac_syscall(MAC_AMFI_POLICY_NAME, AMFI_SYSCALL_CDHASH_IN_TRUSTCACHE, &args); + if (err) { + err = errno; + } + *trustcache_result = args.result; + return err; +} + +static int +amfi_interface_cdhash_in_trustcache(const uint8_t cdhash[], size_t cdhash_len, uint64_t* trustcache_result) +{ + int err = EINVAL; + + if (cdhash == nullptr || cdhash_len != AMFI_INTF_CD_HASH_LEN || trustcache_result == nullptr) { + goto lb_end; + } + *trustcache_result = 0; + + err = __amfi_interface_cdhash_in_trustcache(cdhash, trustcache_result); + +lb_end: + return err; +} +#endif + +bool Requirement::Interpreter::inTrustCache() +{ + uint64_t result = 0; + CFRef cdhashRef = mContext->directory->cdhash(true); + const uint8_t *cdhash = CFDataGetBytePtr(cdhashRef); + size_t cdhash_len = CFDataGetLength(cdhashRef); + int err = amfi_interface_cdhash_in_trustcache(cdhash, cdhash_len, &result); + return (err == 0) && (result != 0); +} + bool Requirement::Interpreter::appleSigned() { - if (appleAnchored()) { - if (SecCertificateRef intermed = mContext->cert(-2)) // first intermediate - // first intermediate common name match (exact) - if (certFieldValue("subject.CN", Match(appleIntermediateCN, matchEqual), intermed) - && certFieldValue("subject.O", Match(appleIntermediateO, matchEqual), intermed)) - return true; + if (inTrustCache()) { + return true; + } + else if (appleAnchored()) { + if (SecCertificateRef intermed = mContext->cert(-2)) // first intermediate + // first intermediate common name match (exact) + if (certFieldValue("subject.CN", Match(appleIntermediateCN, matchEqual), intermed) + && certFieldValue("subject.O", Match(appleIntermediateO, matchEqual), intermed)) + return true; } else if (appleLocalAnchored()) { return true; - } - return false; + } + return false; } @@ -453,15 +520,7 @@ bool Requirement::Interpreter::verifyAnchor(SecCertificateRef cert, const unsign // get certificate bytes if (cert) { SHA1 hasher; -#if TARGET_OS_OSX - CSSM_DATA certData; - MacOSError::check(SecCertificateGetData(cert, &certData)); - - // verify hash - hasher(certData.Data, certData.Length); -#else hasher(SecCertificateGetBytePtr(cert), SecCertificateGetLength(cert)); -#endif return hasher.verify(digest); } return false; diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.h b/OSX/libsecurity_codesigning/lib/reqinterp.h index 83b2fb02..7e828f5e 100644 --- a/OSX/libsecurity_codesigning/lib/reqinterp.h +++ b/OSX/libsecurity_codesigning/lib/reqinterp.h @@ -88,6 +88,7 @@ protected: bool verifyAnchor(SecCertificateRef cert, const unsigned char *digest); bool appleSigned(); bool appleAnchored(); + bool inTrustCache(); bool trustedCerts(); bool trustedCert(int slot); diff --git a/OSX/libsecurity_codesigning/lib/signer.cpp b/OSX/libsecurity_codesigning/lib/signer.cpp index eff950ab..576459c8 100644 --- a/OSX/libsecurity_codesigning/lib/signer.cpp +++ b/OSX/libsecurity_codesigning/lib/signer.cpp @@ -143,12 +143,17 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) if (CFRef infoData = rep->component(cdInfoSlot)) infoDict.take(makeCFDictionaryFrom(infoData)); - uint32_t inherit = code->isSigned() ? state.mPreserveMetadata : 0; + uint32_t inherit = 0; + + if (code->isSigned() && (code->codeDirectory(false)->flags & kSecCodeSignatureLinkerSigned) == 0) { + inherit = state.mPreserveMetadata; + } // work out the canonical identifier identifier = state.mIdentifier; - if (identifier.empty() && (inherit & kSecCodeSignerPreserveIdentifier)) + if (identifier.empty() && (inherit & kSecCodeSignerPreserveIdentifier)) { identifier = code->identifier(); + } if (identifier.empty()) { identifier = rep->recommendedIdentifier(*this); if (identifier.find('.') == string::npos) @@ -174,8 +179,6 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) entitlements = state.mEntitlementData; if (!entitlements && (inherit & kSecCodeSignerPreserveEntitlements)) entitlements = code->component(cdEntitlementSlot); - - generateEntitlementDER = signingFlags() & kSecCSSignGenerateEntitlementDER; // work out the CodeDirectory flags word bool haveCdFlags = false; @@ -409,12 +412,12 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase if (!(signingFlags() & kSecCSSignV1)) { CFCopyRef rules2 = cfget(rulesDict, "rules2"); if (!rules2) { - // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules, - // because the default weight, according to ResourceBuilder::addRule(), is 1). + // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules, + // because the default weight, according to ResourceBuilder::addRule(), is 1). // V1 rules typically do not cover these places so we'll prevail, but if they do, we defer to them. - rules2 = cfmake("{+%O" + rules2.take(cfmake("{+%O" "'^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/' = {nested=#T, weight=0}" // exclude dynamic repositories - "}", rules); + "}", rules)); } Dispatch::Group group; @@ -540,7 +543,7 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context if (state.mPreserveAFSC) writer->setPreserveAFSC(state.mPreserveAFSC); - auto_ptr editor(state.mDetached + unique_ptr editor(state.mDetached ? static_cast(new BlobEditor(*fat, *this)) : new MachOEditor(writer, *fat, this->digestAlgorithms(), rep->mainExecutablePath())); assert(editor->count() > 0); @@ -558,6 +561,22 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context MacOSError::throwMe(errSecCSBadLVArch); } } + + bool generateEntitlementDER = false; + if (signingFlags() & kSecCSSignGenerateEntitlementDER) { + generateEntitlementDER = true; + } else { + uint32_t platform = arch.source->platform(); + switch (platform) { + case PLATFORM_WATCHOS: + case PLATFORM_BRIDGEOS: + generateEntitlementDER = false; + break; + default: + generateEntitlementDER = true; + break; + } + } bool mainBinary = arch.source.get()->type() == MH_EXECUTE; @@ -581,7 +600,7 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context arch.source->offset(), arch.source->signingExtent(), mainBinary, rep->execSegBase(&(arch.architecture)), rep->execSegLimit(&(arch.architecture)), unsigned(digestAlgorithms().size()-1), - preEncryptHashMaps[arch.architecture], runtimeVersionToUse); + preEncryptHashMaps[arch.architecture], runtimeVersionToUse, generateEntitlementDER); }); } @@ -660,7 +679,8 @@ void SecCodeSigner::Signer::signArchitectureAgnostic(const Requirement::Context rep->execSegBase(NULL), rep->execSegLimit(NULL), unsigned(digestAlgorithms().size()-1), preEncryptHashMaps[preEncryptMainArch], // Only one map, the default. - (cdFlags & kSecCodeSignatureRuntime) ? state.mRuntimeVersionOverride : 0); + (cdFlags & kSecCodeSignatureRuntime) ? state.mRuntimeVersionOverride : 0, + signingFlags() & kSecCSSignGenerateEntitlementDER); CodeDirectory *cd = builder.build(); if (!state.mDryRun) @@ -708,7 +728,7 @@ void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::W bool mainBinary, size_t execSegBase, size_t execSegLimit, unsigned alternateDigestCount, PreEncryptHashMap const &preEncryptHashMap, - uint32_t runtimeVersion) + uint32_t runtimeVersion, bool generateEntitlementDER) { // fill the CodeDirectory builder.executable(rep->mainExecutablePath(), pagesize, offset, length); diff --git a/OSX/libsecurity_codesigning/lib/signer.h b/OSX/libsecurity_codesigning/lib/signer.h index 960cf796..346f51ef 100644 --- a/OSX/libsecurity_codesigning/lib/signer.h +++ b/OSX/libsecurity_codesigning/lib/signer.h @@ -96,7 +96,7 @@ protected: bool mainBinary, size_t execSegBase, size_t execSegLimit, unsigned alternateDigestCount, const PreEncryptHashMap& preEncryptHashMap, - uint32_t runtimeVersion); // per-architecture + uint32_t runtimeVersion, bool generateEntitlementDER); // per-architecture CFDataRef signCodeDirectory(const CodeDirectory *cd, CFDictionaryRef hashDict, CFArrayRef hashList); @@ -146,7 +146,6 @@ private: CFAbsoluteTime signingTime; // signing time for CMS signature (0 => now) bool emitSigningTime; // emit signing time as a signed CMS attribute bool strict; // strict validation - bool generateEntitlementDER; // generate entitlement DER // Signature Editing Architecture editMainArch; // main architecture for editing diff --git a/OSX/libsecurity_codesigning/lib/signerutils.h b/OSX/libsecurity_codesigning/lib/signerutils.h index 1bd01d8c..e40752a2 100644 --- a/OSX/libsecurity_codesigning/lib/signerutils.h +++ b/OSX/libsecurity_codesigning/lib/signerutils.h @@ -103,7 +103,7 @@ public: // struct Arch : public BlobWriter { Architecture architecture; // our architecture - auto_ptr source; // Mach-O object to be signed + unique_ptr source; // Mach-O object to be signed std::map > cdBuilders; InternalRequirements ireqs; // consolidated internal requirements size_t blobSize; // calculated SuperBlob size diff --git a/OSX/libsecurity_codesigning/lib/xpcengine.cpp b/OSX/libsecurity_codesigning/lib/xpcengine.cpp index d6e37ed9..8189f0c0 100644 --- a/OSX/libsecurity_codesigning/lib/xpcengine.cpp +++ b/OSX/libsecurity_codesigning/lib/xpcengine.cpp @@ -269,11 +269,13 @@ CFDictionaryRef xpcEngineUpdate(CFTypeRef target, SecAssessmentFlags flags, CFDi msg.send(); - if (localAuthorization) + if (localAuthorization) { AuthorizationFree(localAuthorization, kAuthorizationFlagDefaults); + } - if (int64_t error = xpc_dictionary_get_int64(msg, "error")) - MacOSError::throwMe((int)error); + if (int64_t error = xpc_dictionary_get_int64(msg, "error")) { + MacOSError::throwMe((int)error); + } size_t resultLength; const void *resultData = xpc_dictionary_get_data(msg, "result", &resultLength); diff --git a/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp b/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp index bb9db996..de3b8979 100644 --- a/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp +++ b/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp @@ -55,8 +55,8 @@ class feeException protected: feeException(feeReturn frtn, const char *op); public: - ~feeException() throw() {} - feeReturn frtn() const throw() { return mFrtn; } + ~feeException() _NOEXCEPT {} + feeReturn frtn() const _NOEXCEPT { return mFrtn; } static void throwMe(feeReturn frtn, const char *op = NULL) __attribute__((noreturn)); private: feeReturn mFrtn; diff --git a/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c b/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c index 8c950d38..a26d61bc 100644 --- a/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c +++ b/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c @@ -37,7 +37,6 @@ *************************************************************/ #include -#include #include #include #include "giants.h" diff --git a/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c b/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c index bf70b3ab..cf8ac154 100644 --- a/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c +++ b/OSX/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c @@ -31,7 +31,6 @@ *************************************************************/ #include -#include #include #include"giants.h" #include "tools.h" diff --git a/OSX/libsecurity_cryptkit/lib/feeFEED.c b/OSX/libsecurity_cryptkit/lib/feeFEED.c index 9c6ae1d3..ed0ac83c 100644 --- a/OSX/libsecurity_cryptkit/lib/feeFEED.c +++ b/OSX/libsecurity_cryptkit/lib/feeFEED.c @@ -924,14 +924,6 @@ feeReturn feeFEEDDecryptBlock(feeFEED feed, return FR_BadCipherText; } - /* - * we already know how long this should be... - */ - if(finst->initialRSSize != finst->initialRSSize) { - dbgLog(("feeFEEDDecryptBlock: initialRS sync error\n")); - return FR_BadCipherText; - } - /* * Set up clues */ diff --git a/OSX/libsecurity_cssm/lib/attachment.cpp b/OSX/libsecurity_cssm/lib/attachment.cpp index 59ab540c..f697dbb1 100644 --- a/OSX/libsecurity_cssm/lib/attachment.cpp +++ b/OSX/libsecurity_cssm/lib/attachment.cpp @@ -145,28 +145,28 @@ Attachment::~Attachment() // void *Attachment::upcallMalloc(CSSM_HANDLE handle, size_t size) { - BEGIN_API + BEGIN_API_NO_METRICS return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).malloc(size); END_API1(NULL) } void Attachment::upcallFree(CSSM_HANDLE handle, void *mem) { - BEGIN_API + BEGIN_API_NO_METRICS return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).free(mem); END_API0 } void *Attachment::upcallRealloc(CSSM_HANDLE handle, void *mem, size_t size) { - BEGIN_API + BEGIN_API_NO_METRICS return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).realloc(mem, size); END_API1(NULL) } void *Attachment::upcallCalloc(CSSM_HANDLE handle, size_t num, size_t size) { - BEGIN_API + BEGIN_API_NO_METRICS return HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).calloc(size, num); END_API1(NULL) } @@ -174,7 +174,7 @@ void *Attachment::upcallCalloc(CSSM_HANDLE handle, size_t num, size_t size) CSSM_RETURN Attachment::upcallCcToHandle(CSSM_CC_HANDLE handle, CSSM_MODULE_HANDLE *modHandle) { - BEGIN_API + BEGIN_API_NO_METRICS Required(modHandle) = HandleObject::find((CSSM_HANDLE)handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).attachment.handle(); END_API(CSP) } @@ -190,7 +190,7 @@ CSSM_RETURN Attachment::upcallGetModuleInfo(CSSM_MODULE_HANDLE handle, CSSM_FUNC_NAME_ADDR_PTR FunctionTable, uint32 NumFunctions) { - BEGIN_API + BEGIN_API_NO_METRICS Attachment &attachment = HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE); Required(guid) = attachment.myGuid(); Required(version) = attachment.mVersion; diff --git a/OSX/libsecurity_cssm/lib/cssm.cpp b/OSX/libsecurity_cssm/lib/cssm.cpp index 496d039c..c41afa38 100644 --- a/OSX/libsecurity_cssm/lib/cssm.cpp +++ b/OSX/libsecurity_cssm/lib/cssm.cpp @@ -31,7 +31,7 @@ #include "module.h" #include #include - +#include "LegacyAPICounts.h" // // We currently use exactly one instance of CssmManager. diff --git a/OSX/libsecurity_cssm/lib/cssmcontext.h b/OSX/libsecurity_cssm/lib/cssmcontext.h index 6f825019..4a5ae461 100644 --- a/OSX/libsecurity_cssm/lib/cssmcontext.h +++ b/OSX/libsecurity_cssm/lib/cssmcontext.h @@ -68,18 +68,18 @@ public: void mergeAttributes(const CSSM_CONTEXT_ATTRIBUTE *attributes, uint32 count); CSSM_RETURN validateChange(CSSM_CONTEXT_EVENT event); - void *operator new (size_t size, Allocator &alloc) throw(std::bad_alloc) + void *operator new (size_t size, Allocator &alloc) { return alloc.malloc(size); } - void operator delete (void *addr, size_t, Allocator &alloc) throw() + void operator delete (void *addr, size_t, Allocator &alloc) _NOEXCEPT { return alloc.free(addr); } - static void destroy(HandleContext *context, Allocator &alloc) throw() + static void destroy(HandleContext *context, Allocator &alloc) _NOEXCEPT { context->~HandleContext(); alloc.free(context); } class Maker; // deluxe builder #if __GNUC__ > 2 private: - void operator delete (void *addr) throw() { assert(0); } + void operator delete (void *addr) _NOEXCEPT { assert(0); } #endif protected: diff --git a/OSX/libsecurity_cssm/lib/cssmerr.h b/OSX/libsecurity_cssm/lib/cssmerr.h index 4465dbc0..3d8bd1c0 100644 --- a/OSX/libsecurity_cssm/lib/cssmerr.h +++ b/OSX/libsecurity_cssm/lib/cssmerr.h @@ -38,18 +38,6 @@ extern "C" { * (i.e. those with names like kSec...). */ - -/* Common error codes. */ -enum { - CSSM_BASE_ERROR = -0x7FFF0000 /* 0x80010000 */ -}; - -enum { - CSSM_ERRORCODE_MODULE_EXTENT = 0x00000800, - CSSM_ERRORCODE_CUSTOM_OFFSET = 0x00000400, - CSSM_ERRORCODE_COMMON_EXTENT = 0x100 -}; - /* Macros for convertible error code manipulation. */ #define CSSM_ERRCODE(CODE) \ (((CODE) - CSSM_BASE_ERROR) & (CSSM_ERRORCODE_MODULE_EXTENT - 1)) @@ -65,6 +53,12 @@ enum { /* Error Bases for different module types. */ enum { + CSSM_BASE_ERROR = -0x7FFF0000, /* 0x80010000 */ + + CSSM_ERRORCODE_MODULE_EXTENT = 0x00000800, + CSSM_ERRORCODE_CUSTOM_OFFSET = 0x00000400, + CSSM_ERRORCODE_COMMON_EXTENT = 0x100, + CSSM_CSSM_BASE_ERROR = CSSM_BASE_ERROR, CSSM_CSSM_PRIVATE_ERROR = CSSM_BASE_ERROR + CSSM_ERRORCODE_CUSTOM_OFFSET, CSSM_CSP_BASE_ERROR = CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_MODULE_EXTENT, diff --git a/OSX/libsecurity_cssm/lib/module.cpp b/OSX/libsecurity_cssm/lib/module.cpp index 7dce28fe..713a31dc 100644 --- a/OSX/libsecurity_cssm/lib/module.cpp +++ b/OSX/libsecurity_cssm/lib/module.cpp @@ -155,7 +155,7 @@ CSSM_RETURN Module::spiEventRelay(const CSSM_GUID *ModuleGuid, CSSM_SERVICE_TYPE ServiceType, CSSM_MODULE_EVENT EventType) { - BEGIN_API + BEGIN_API_NO_METRICS static_cast(Context)->spiEvent(EventType, Guid::required(ModuleGuid), SubserviceId, diff --git a/OSX/libsecurity_cssm/lib/transition.cpp b/OSX/libsecurity_cssm/lib/transition.cpp index 8f78be84..5e844f3f 100644 --- a/OSX/libsecurity_cssm/lib/transition.cpp +++ b/OSX/libsecurity_cssm/lib/transition.cpp @@ -46,6 +46,7 @@ #include #include #include +#include "LegacyAPICounts.h" // diff --git a/OSX/libsecurity_filedb/lib/AppleDatabase.cpp b/OSX/libsecurity_filedb/lib/AppleDatabase.cpp index 60b47123..7f37d472 100644 --- a/OSX/libsecurity_filedb/lib/AppleDatabase.cpp +++ b/OSX/libsecurity_filedb/lib/AppleDatabase.cpp @@ -110,7 +110,7 @@ Table::readIndexSection() uint32 indexOffset = mTableSection.at(indexSectionOffset + (i + 2) * AtomSize); ReadSection indexSection(mTableSection.subsection(indexOffset)); - auto_ptr index(new DbConstIndex(*this, indexSection)); + unique_ptr index(new DbConstIndex(*this, indexSection)); mIndexMap.insert(ConstIndexMap::value_type(index->indexId(), index.get())); index.release(); } @@ -289,7 +289,7 @@ ModifiedTable::insertRecord(uint32 inVersionId, { modifyTable(); - auto_ptr aWriteSection(new WriteSection()); + unique_ptr aWriteSection(new WriteSection()); getMetaRecord().packRecord(*aWriteSection, inAttributes, inData); uint32 aRecordNumber = nextRecordNumber(); @@ -341,7 +341,7 @@ ModifiedTable::updateRecord(const RecordId &inRecordId, #endif // Update the actual packed record. - auto_ptr aDbRecord(new WriteSection()); + unique_ptr aDbRecord(new WriteSection()); getMetaRecord().updateRecord(anOldDbRecord, *aDbRecord, CssmDbRecordAttributeData::overlay(inAttributes), inData, inModifyMode); @@ -507,7 +507,7 @@ ModifiedTable::createMutableIndexes() Table::ConstIndexMap::const_iterator it; for (it = mTable->mIndexMap.begin(); it != mTable->mIndexMap.end(); it++) { - auto_ptr mutableIndex(new DbMutableIndex(*it->second)); + unique_ptr mutableIndex(new DbMutableIndex(*it->second)); mIndexMap.insert(MutableIndexMap::value_type(it->first, mutableIndex.get())); mutableIndex.release(); } @@ -522,7 +522,7 @@ ModifiedTable::findIndex(uint32 indexId, const MetaRecord &metaRecord, bool isUn if (it == mIndexMap.end()) { // create the new index - auto_ptr index(new DbMutableIndex(metaRecord, indexId, isUniqueIndex)); + unique_ptr index(new DbMutableIndex(metaRecord, indexId, isUniqueIndex)); it = mIndexMap.insert(MutableIndexMap::value_type(indexId, index.get())).first; index.release(); } @@ -932,7 +932,7 @@ DbVersion::open() // XXX Set the size boundary on aTableSection. const ReadSection aTableSection = aSchemaSection.subsection(aTableOffset); - auto_ptr aTable(new Table(aTableSection)); + unique_ptr
aTable(new Table(aTableSection)); Table::Id aTableId = aTable->getMetaRecord().dataRecordType(); mTableMap.insert(TableMap::value_type(aTableId, aTable.get())); aTable.release(); @@ -1048,7 +1048,7 @@ DbVersion::open() uint32 anAttributeId = aRecordData[1]; uint32 anAttributeNameFormat = aRecordData[2]; uint32 anAttributeFormat = aRecordData[5]; - auto_ptr aName; + unique_ptr aName; const CssmData *aNameID = NULL; if (aRecordData[3].size() == 1) @@ -1056,8 +1056,8 @@ DbVersion::open() if (aRecordData[3].format() != CSSM_DB_ATTRIBUTE_FORMAT_STRING) CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); - auto_ptr aName2(new string(static_cast(aRecordData[3]))); - aName = aName2; + unique_ptr aName2(new string(static_cast(aRecordData[3]))); + aName = std::move(aName2); } if (aRecordData[4].size() == 1) @@ -1300,7 +1300,7 @@ IndexCursor::IndexCursor(DbQueryKey *queryKey, const DbVersion &inDbVersion, IndexCursor::~IndexCursor() { - // the query key will be deleted automatically, since it's an auto_ptr + // the query key will be deleted automatically, since it's an unique_ptr } bool @@ -1554,7 +1554,7 @@ DbModifier::modifyDatabase() mDbVersion->mTableMap.end(); for (; anIt != anEnd; ++anIt) { - auto_ptr aTable(new ModifiedTable(anIt->second)); + unique_ptr aTable(new ModifiedTable(anIt->second)); mModifiedTableMap.insert(ModifiedTableMap::value_type(anIt->first, aTable.get())); aTable.release(); @@ -1601,8 +1601,8 @@ DbModifier::updateRecord(Table::Id inTableId, const RecordId &inRecordId, ModifiedTable * DbModifier::createTable(MetaRecord *inMetaRecord) { - auto_ptr aMetaRecord(inMetaRecord); - auto_ptr aModifiedTable(new ModifiedTable(inMetaRecord)); + unique_ptr aMetaRecord(inMetaRecord); + unique_ptr aModifiedTable(new ModifiedTable(inMetaRecord)); // Now that aModifiedTable is fully constructed it owns inMetaRecord aMetaRecord.release(); @@ -1744,7 +1744,7 @@ DbModifier::commit() } void -DbModifier::rollback() throw() +DbModifier::rollback() _NOEXCEPT { // This will destroy the AtomicTempFile if we have one causing it to rollback. mAtomicTempFile = NULL; @@ -2367,7 +2367,7 @@ AppleDatabase::dataGetFirst(DbContext &inDbContext, { // XXX: register Cursor with DbContext and have DbContext call // dataAbortQuery for all outstanding Query objects on close. - auto_ptr aCursor(mDbModifier.createCursor(inQuery)); + unique_ptr aCursor(mDbModifier.createCursor(inQuery)); Table::Id aTableId; RecordId aRecordId; @@ -2387,7 +2387,7 @@ AppleDatabase::dataGetNext(DbContext &inDbContext, CssmData *inoutData, CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) { - auto_ptr aCursor(&HandleObject::find(inResultsHandle, CSSMERR_DL_INVALID_RESULTS_HANDLE)); + unique_ptr aCursor(&HandleObject::find(inResultsHandle, CSSMERR_DL_INVALID_RESULTS_HANDLE)); Table::Id aTableId; RecordId aRecordId; diff --git a/OSX/libsecurity_filedb/lib/AppleDatabase.h b/OSX/libsecurity_filedb/lib/AppleDatabase.h index 1ad330fd..bd341397 100644 --- a/OSX/libsecurity_filedb/lib/AppleDatabase.h +++ b/OSX/libsecurity_filedb/lib/AppleDatabase.h @@ -361,7 +361,7 @@ public: RecordId &recordId); private: - auto_ptr mQueryKey; + unique_ptr mQueryKey; const Table &mTable; const DbConstIndex *mIndex; @@ -383,10 +383,10 @@ public: Allocator &inAllocator, RecordId &recordId); private: - auto_ptr mQuery; + unique_ptr mQuery; DbVersion::const_iterator mTableIterator; - auto_ptr mCursor; + unique_ptr mCursor; }; // @@ -413,7 +413,7 @@ public: void deleteDatabase(); void commit(); - void rollback() throw(); + void rollback() _NOEXCEPT; // Record changing members void deleteRecord(Table::Id inTableId, const RecordId &inRecordId); diff --git a/OSX/libsecurity_filedb/lib/AtomicFile.cpp b/OSX/libsecurity_filedb/lib/AtomicFile.cpp index 6c21d12d..24ca9907 100644 --- a/OSX/libsecurity_filedb/lib/AtomicFile.cpp +++ b/OSX/libsecurity_filedb/lib/AtomicFile.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #define kAtomicFileMaxBlockSize INT_MAX @@ -391,8 +391,8 @@ AtomicBufferedFile::~AtomicBufferedFile() { if (mFileRef >= 0) { - // In release mode, the assert() is compiled out so rv may be unused. - __unused int rv = AtomicFile::rclose(mFileRef); + // In release mode, the assert() is compiled out so rv may be unused. + __unused int rv = AtomicFile::rclose(mFileRef); assert(rv == 0); secinfo("atomicfile", "%p closed %s", this, mPath.c_str()); } @@ -830,7 +830,7 @@ AtomicTempFile::commit() // Rollback the current create or write (happens automatically if commit() isn't called before the destructor is. void -AtomicTempFile::rollback() throw() +AtomicTempFile::rollback() _NOEXCEPT { if (mFileRef >= 0) { @@ -1240,7 +1240,7 @@ AtomicLockedFile::lock(mode_t mode) -void AtomicLockedFile::unlock() throw() +void AtomicLockedFile::unlock() _NOEXCEPT { mFileLocker->unlock(); } diff --git a/OSX/libsecurity_filedb/lib/AtomicFile.h b/OSX/libsecurity_filedb/lib/AtomicFile.h index 86be8bea..0662eedb 100644 --- a/OSX/libsecurity_filedb/lib/AtomicFile.h +++ b/OSX/libsecurity_filedb/lib/AtomicFile.h @@ -160,7 +160,7 @@ private: void close(); // Rollback the current create or write (happens automatically if commit() isn't called before the destructor is). - void rollback() throw(); + void rollback() _NOEXCEPT; private: // Our AtomicFile object. @@ -241,7 +241,7 @@ public: private: void lock(mode_t mode = (S_IRUSR|S_IRGRP|S_IROTH) /* === 0444 */); - void unlock() throw(); + void unlock() _NOEXCEPT; private: FileLocker* mFileLocker; diff --git a/OSX/libsecurity_filedb/lib/DbIndex.cpp b/OSX/libsecurity_filedb/lib/DbIndex.cpp index e95603b5..007b2f69 100644 --- a/OSX/libsecurity_filedb/lib/DbIndex.cpp +++ b/OSX/libsecurity_filedb/lib/DbIndex.cpp @@ -64,8 +64,8 @@ DbKeyComparator::operator () (uint32 offset1, uint32 offset2) const for (uint32 i = 0; i < mKey.mNumKeyValues; i++) { const MetaAttribute &metaAttribute = *mKey.mIndex.mAttributes[i]; - auto_ptr value1(metaAttribute.createValue(*key1, valueOffset1)); - auto_ptr value2(metaAttribute.createValue(*key2, valueOffset2)); + unique_ptr value1(metaAttribute.createValue(*key1, valueOffset1)); + unique_ptr value2(metaAttribute.createValue(*key2, valueOffset2)); if (metaAttribute.evaluate(value1.get(), value2.get(), CSSM_DB_LESS_THAN)) return true; @@ -92,9 +92,9 @@ DbIndexKey::operator < (const DbIndexKey &other) const for (uint32 i = 0; i < numAttributes; i++) { const MetaAttribute &metaAttribute = *mIndex.mAttributes[i]; - auto_ptr value1(metaAttribute.createValue(mKeySection.subsection(mKeyRange), + unique_ptr value1(metaAttribute.createValue(mKeySection.subsection(mKeyRange), valueOffset1)); - auto_ptr value2(metaAttribute.createValue(other.mKeySection.subsection(other.mKeyRange), + unique_ptr value2(metaAttribute.createValue(other.mKeySection.subsection(other.mKeyRange), valueOffset2)); if (metaAttribute.evaluate(value1.get(), value2.get(), CSSM_DB_LESS_THAN)) diff --git a/OSX/libsecurity_filedb/lib/ReadWriteSection.cpp b/OSX/libsecurity_filedb/lib/ReadWriteSection.cpp index 9fe1b489..c97dfdbf 100644 --- a/OSX/libsecurity_filedb/lib/ReadWriteSection.cpp +++ b/OSX/libsecurity_filedb/lib/ReadWriteSection.cpp @@ -49,9 +49,10 @@ void WriteSection::grow(size_t inNewCapacity) size_t aNewCapacity = max(n, inNewCapacity); mAddress = reinterpret_cast(mAllocator.realloc(mAddress, aNewCapacity)); - if (mAddress == NULL) + if (mAddress == NULL) { CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); + } - memset(mAddress + mCapacity, 0, aNewCapacity - mCapacity); - mCapacity = aNewCapacity; + memset(mAddress + mCapacity, 0, aNewCapacity - mCapacity); + mCapacity = aNewCapacity; } diff --git a/OSX/libsecurity_filedb/lib/ReadWriteSection.h b/OSX/libsecurity_filedb/lib/ReadWriteSection.h index f77e8c4c..7b2b5147 100644 --- a/OSX/libsecurity_filedb/lib/ReadWriteSection.h +++ b/OSX/libsecurity_filedb/lib/ReadWriteSection.h @@ -76,7 +76,7 @@ public: uint32 at(uint32 inOffset) const { - if (inOffset > mLength) + if (CheckUInt32Add(inOffset, AtomSize) > mLength) { CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); } diff --git a/OSX/libsecurity_keychain/Security b/OSX/libsecurity_keychain/Security deleted file mode 120000 index 945c9b46..00000000 --- a/OSX/libsecurity_keychain/Security +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/OSX/libsecurity_keychain/lib/CertificateValues.cpp b/OSX/libsecurity_keychain/lib/CertificateValues.cpp index a2f1ec1b..e20ee2cf 100644 --- a/OSX/libsecurity_keychain/lib/CertificateValues.cpp +++ b/OSX/libsecurity_keychain/lib/CertificateValues.cpp @@ -78,7 +78,7 @@ CertificateValues::CertificateValues(SecCertificateRef certificateRef) : mCertif CFRetain(mCertificateRef); } -CertificateValues::~CertificateValues() throw() +CertificateValues::~CertificateValues() _NOEXCEPT { if (mCertificateProperties) CFRelease(mCertificateProperties); diff --git a/OSX/libsecurity_keychain/lib/CertificateValues.h b/OSX/libsecurity_keychain/lib/CertificateValues.h index 41d17c3f..64150acb 100644 --- a/OSX/libsecurity_keychain/lib/CertificateValues.h +++ b/OSX/libsecurity_keychain/lib/CertificateValues.h @@ -43,7 +43,7 @@ class CertificateValues public: CertificateValues(SecCertificateRef certificateRef); - virtual ~CertificateValues() throw(); + virtual ~CertificateValues() _NOEXCEPT; static CFStringRef remapLabelToKey(CFStringRef label); CFArrayRef copyPropertyValues(CFErrorRef *error); diff --git a/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp b/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp index aa168bd8..14774788 100644 --- a/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp +++ b/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp @@ -415,13 +415,14 @@ DLDbListCFPref::resetCachedValues() void DLDbListCFPref::save() { - if (!hasChanged()) + if (!hasChanged()) { return; + } - // Resync from disc to make sure we don't clobber anyone elses changes. - // @@@ This is probably already done by the next layer up so we don't - // really need to do it here again. - loadPropertyList(true); + // Resync from disc to make sure we don't clobber anyone elses changes. + // @@@ This is probably already done by the next layer up so we don't + // really need to do it here again. + loadPropertyList(true); // Do the searchList first since it might end up invoking defaultDLDbIdentifier() which can set // mLoginDLDbIdentifierSet and mDefaultDLDbIdentifierSet to true. diff --git a/OSX/libsecurity_keychain/lib/ExtendedAttribute.cpp b/OSX/libsecurity_keychain/lib/ExtendedAttribute.cpp index 791c0cc2..d81650d3 100644 --- a/OSX/libsecurity_keychain/lib/ExtendedAttribute.cpp +++ b/OSX/libsecurity_keychain/lib/ExtendedAttribute.cpp @@ -116,7 +116,7 @@ ExtendedAttribute::ExtendedAttribute( setupAttrs(); } -ExtendedAttribute::~ExtendedAttribute() throw() +ExtendedAttribute::~ExtendedAttribute() _NOEXCEPT { } diff --git a/OSX/libsecurity_keychain/lib/ExtendedAttribute.h b/OSX/libsecurity_keychain/lib/ExtendedAttribute.h index ed2b1f75..2469fce6 100644 --- a/OSX/libsecurity_keychain/lib/ExtendedAttribute.h +++ b/OSX/libsecurity_keychain/lib/ExtendedAttribute.h @@ -69,7 +69,7 @@ public: ExtendedAttribute(ExtendedAttribute &extendedAttribute); - virtual ~ExtendedAttribute() throw(); + virtual ~ExtendedAttribute() _NOEXCEPT; virtual PrimaryKey add(Keychain &keychain); bool operator == (const ExtendedAttribute &other) const; diff --git a/OSX/libsecurity_keychain/lib/Identity.cpp b/OSX/libsecurity_keychain/lib/Identity.cpp index 85b0636d..6447eb9b 100644 --- a/OSX/libsecurity_keychain/lib/Identity.cpp +++ b/OSX/libsecurity_keychain/lib/Identity.cpp @@ -113,7 +113,7 @@ Identity::Identity(const StorageManager::KeychainList &keychains, const SecPoint } } -Identity::~Identity() throw() +Identity::~Identity() _NOEXCEPT { if (mPrivateKey) CFRelease(mPrivateKey); diff --git a/OSX/libsecurity_keychain/lib/Identity.h b/OSX/libsecurity_keychain/lib/Identity.h index 29170a27..e942f6a3 100644 --- a/OSX/libsecurity_keychain/lib/Identity.h +++ b/OSX/libsecurity_keychain/lib/Identity.h @@ -47,7 +47,7 @@ public: Identity(const SecKeyRef privateKey, const SecPointer &certificate); Identity(const StorageManager::KeychainList &keychains, const SecPointer &certificate); - virtual ~Identity() throw(); + virtual ~Identity() _NOEXCEPT; SecPointer privateKey() const; SecPointer certificate() const; diff --git a/OSX/libsecurity_keychain/lib/IdentityCursor.cpp b/OSX/libsecurity_keychain/lib/IdentityCursor.cpp index 519b47c2..773800c8 100644 --- a/OSX/libsecurity_keychain/lib/IdentityCursor.cpp +++ b/OSX/libsecurity_keychain/lib/IdentityCursor.cpp @@ -55,7 +55,7 @@ IdentityCursorPolicyAndID::IdentityCursorPolicyAndID(const StorageManager::Keych } } -IdentityCursorPolicyAndID::~IdentityCursorPolicyAndID() throw() +IdentityCursorPolicyAndID::~IdentityCursorPolicyAndID() _NOEXCEPT { if (mPolicy) { CFRelease(mPolicy); @@ -271,7 +271,7 @@ IdentityCursor::IdentityCursor(const StorageManager::KeychainList &searchList, C mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Unwrap, true); } -IdentityCursor::~IdentityCursor() throw() +IdentityCursor::~IdentityCursor() _NOEXCEPT { } @@ -281,7 +281,7 @@ IdentityCursor::pubKeyHashForSystemIdentity(CFStringRef domain) StLock_(mMutex); CFDataRef entryValue = nil; - auto_ptr identDict; + unique_ptr identDict; Dictionary* d = Dictionary::CreateDictionary("com.apple.security.systemidentities", Dictionary::US_System); if (d) { diff --git a/OSX/libsecurity_keychain/lib/IdentityCursor.h b/OSX/libsecurity_keychain/lib/IdentityCursor.h index aa9d7f58..1e0e275c 100644 --- a/OSX/libsecurity_keychain/lib/IdentityCursor.h +++ b/OSX/libsecurity_keychain/lib/IdentityCursor.h @@ -50,7 +50,7 @@ public: SECCFFUNCTIONS(IdentityCursor, SecIdentitySearchRef, errSecInvalidSearchRef, gTypes().IdentityCursor) IdentityCursor(const StorageManager::KeychainList &searchList, CSSM_KEYUSE keyUsage); - virtual ~IdentityCursor() throw(); + virtual ~IdentityCursor() _NOEXCEPT; virtual bool next(SecPointer &identity); CFDataRef pubKeyHashForSystemIdentity(CFStringRef domain); @@ -69,7 +69,7 @@ class IdentityCursorPolicyAndID : public IdentityCursor { public: IdentityCursorPolicyAndID(const StorageManager::KeychainList &searchList, CSSM_KEYUSE keyUsage, CFStringRef idString, SecPolicyRef policy, bool returnOnlyValidIdentities); - virtual ~IdentityCursorPolicyAndID() throw(); + virtual ~IdentityCursorPolicyAndID() _NOEXCEPT; virtual bool next(SecPointer &identity); virtual void findPreferredIdentity(); diff --git a/OSX/libsecurity_keychain/lib/Item.cpp b/OSX/libsecurity_keychain/lib/Item.cpp index 4d4dc772..f6720512 100644 --- a/OSX/libsecurity_keychain/lib/Item.cpp +++ b/OSX/libsecurity_keychain/lib/Item.cpp @@ -331,7 +331,7 @@ DbAttributes* ItemImpl::getCurrentAttributes() { void ItemImpl::encodeAttributes(CssmOwnedData &attributeBlob) { // Sometimes we don't have our attributes. Find them. - auto_ptr dbAttributes(getCurrentAttributes()); + unique_ptr dbAttributes(getCurrentAttributes()); encodeAttributesFromDictionary(attributeBlob, dbAttributes.get()); } @@ -456,7 +456,7 @@ void ItemImpl::encodeAttributesFromDictionary(CssmOwnedData &attributeBlob, DbAt } void ItemImpl::computeDigest(CssmOwnedData &sha2) { - auto_ptr dbAttributes(getCurrentAttributes()); + unique_ptr dbAttributes(getCurrentAttributes()); ItemImpl::computeDigestFromDictionary(sha2, dbAttributes.get()); } @@ -593,7 +593,7 @@ bool ItemImpl::checkIntegrity(AclBearer& aclBearer) { return true; } - auto_ptr dbAttributes(getCurrentAttributes()); + unique_ptr dbAttributes(getCurrentAttributes()); return checkIntegrityFromDictionary(aclBearer, dbAttributes.get()); } @@ -607,7 +607,7 @@ bool ItemImpl::checkIntegrityFromDictionary(AclBearer& aclBearer, DbAttributes* // them. AclEntryInfo &info = aclInfos.at(0); - auto_ptr acl(new ACL(info, Allocator::standard())); + unique_ptr acl(new ACL(info, Allocator::standard())); for(int i = 1; i < aclInfos.count(); i++) { secnotice("integrity", "*** DUPLICATE INTEGRITY ACL, something has gone wrong"); @@ -1073,7 +1073,7 @@ ItemImpl::doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryC } catch (CssmError cssme) { // If there's a "duplicate" of this item, it might be an item with corrupt/invalid attributes // Try to extract the item and check its attributes, then try again if necessary - auto_ptr primaryKeyAttrs; + unique_ptr primaryKeyAttrs; if(cssme.error == CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA) { secnotice("integrity", "possible duplicate, trying to delete invalid items"); @@ -1113,7 +1113,7 @@ ItemImpl::doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryC // The item on-disk might have more or different attributes than we do, since we're // only searching via primary key. Fetch all of its attributes. - auto_ptrdbDupAttributes (new DbAttributes(kc->database(), 1)); + unique_ptrdbDupAttributes (new DbAttributes(kc->database(), 1)); fillDbAttributesFromSchema(*dbDupAttributes, recordType, kc); // Occasionally this cursor won't return the item attributes (for an unknown reason). diff --git a/OSX/libsecurity_keychain/lib/Item.h b/OSX/libsecurity_keychain/lib/Item.h index 8e9460dd..bbcacb51 100644 --- a/OSX/libsecurity_keychain/lib/Item.h +++ b/OSX/libsecurity_keychain/lib/Item.h @@ -179,8 +179,8 @@ public: void postItemEvent (SecKeychainEvent theEvent); // Only call these functions while holding globals().apiLock. - bool inCache() const throw() { return mInCache; } - void inCache(bool inCache) throw() { mInCache = inCache; } + bool inCache() const _NOEXCEPT { return mInCache; } + void inCache(bool inCache) _NOEXCEPT { mInCache = inCache; } /* For binding to extended attributes. */ virtual const CssmData &itemID(); @@ -222,7 +222,7 @@ protected: // new item members RefPointer mData; - auto_ptr mDbAttributes; + unique_ptr mDbAttributes; SecPointer mAccess; // db item members diff --git a/OSX/libsecurity_keychain/lib/KCCursor.cpp b/OSX/libsecurity_keychain/lib/KCCursor.cpp index ad7039cf..41221977 100644 --- a/OSX/libsecurity_keychain/lib/KCCursor.cpp +++ b/OSX/libsecurity_keychain/lib/KCCursor.cpp @@ -172,7 +172,7 @@ KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, const } } -KCCursorImpl::~KCCursorImpl() throw() +KCCursorImpl::~KCCursorImpl() _NOEXCEPT { } diff --git a/OSX/libsecurity_keychain/lib/KCCursor.h b/OSX/libsecurity_keychain/lib/KCCursor.h index 91027f16..4ce190a1 100644 --- a/OSX/libsecurity_keychain/lib/KCCursor.h +++ b/OSX/libsecurity_keychain/lib/KCCursor.h @@ -47,7 +47,7 @@ protected: KCCursorImpl(const StorageManager::KeychainList &searchList, const SecKeychainAttributeList *attrList); public: - virtual ~KCCursorImpl() throw(); + virtual ~KCCursorImpl() _NOEXCEPT; bool next(Item &item); bool mayDelete(); diff --git a/OSX/libsecurity_keychain/lib/KeyItem.cpp b/OSX/libsecurity_keychain/lib/KeyItem.cpp index 6bec5672..1f079ff5 100644 --- a/OSX/libsecurity_keychain/lib/KeyItem.cpp +++ b/OSX/libsecurity_keychain/lib/KeyItem.cpp @@ -75,7 +75,7 @@ KeyItem *KeyItem::optional(SecKeyRef ptr) } } -KeyItem::operator CFTypeRef() const throw() +KeyItem::operator CFTypeRef() const _NOEXCEPT { StMaybeLock _(this->getMutexForObject()); @@ -758,8 +758,8 @@ KeyItem::createPair( pubKeyHash.set(*pubKeyHashData); passThrough.allocator().free(pubKeyHashData); - auto_ptr privDescription; - auto_ptr pubDescription; + unique_ptr privDescription; + unique_ptr pubDescription; try { privDescription.reset(new string(initialAccess->promptDescription())); pubDescription.reset(new string(initialAccess->promptDescription())); @@ -997,8 +997,8 @@ KeyItem::importPair( csp.allocator().free(cssmData->Data); csp.allocator().free(cssmData); - auto_ptrprivDescription; - auto_ptrpubDescription; + unique_ptrprivDescription; + unique_ptrpubDescription; try { privDescription.reset(new string(initialAccess->promptDescription())); pubDescription.reset(new string(initialAccess->promptDescription())); diff --git a/OSX/libsecurity_keychain/lib/KeyItem.h b/OSX/libsecurity_keychain/lib/KeyItem.h index 8f048f5c..326279d9 100644 --- a/OSX/libsecurity_keychain/lib/KeyItem.h +++ b/OSX/libsecurity_keychain/lib/KeyItem.h @@ -46,7 +46,7 @@ public: // SECCFUNCTIONS macro to retarget SecKeyRef to foreign object instead of normal way through SecCFObject. static KeyItem *required(SecKeyRef ptr); static KeyItem *optional(SecKeyRef ptr); - operator CFTypeRef() const throw(); + operator CFTypeRef() const _NOEXCEPT; static SecCFObject *fromSecKeyRef(CFTypeRef ref); void attachSecKeyRef() const; void initializeWithSecKeyRef(SecKeyRef ref); diff --git a/OSX/libsecurity_keychain/lib/Keychains.h b/OSX/libsecurity_keychain/lib/Keychains.h index 507b270c..b33ae6a4 100644 --- a/OSX/libsecurity_keychain/lib/Keychains.h +++ b/OSX/libsecurity_keychain/lib/Keychains.h @@ -218,8 +218,8 @@ public: const AccessCredentials *defaultCredentials(); // Only call these functions while holding globals().apiLock. - bool inCache() const throw() { return mInCache; } - void inCache(bool inCache) throw() { mInCache = inCache; } + bool inCache() const _NOEXCEPT { return mInCache; } + void inCache(bool inCache) _NOEXCEPT { mInCache = inCache; } void postEvent(SecKeychainEvent kcEvent, ItemImpl* item); void postEvent(SecKeychainEvent kcEvent, ItemImpl* item, PrimaryKey pk); diff --git a/OSX/utilities/SecADWrapper.h b/OSX/libsecurity_keychain/lib/LegacyAPICounts.h similarity index 65% rename from OSX/utilities/SecADWrapper.h rename to OSX/libsecurity_keychain/lib/LegacyAPICounts.h index 3ea457f0..578e59a9 100644 --- a/OSX/utilities/SecADWrapper.h +++ b/OSX/libsecurity_keychain/lib/LegacyAPICounts.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,15 +21,21 @@ * @APPLE_LICENSE_HEADER_END@ */ -#ifndef SecADWrapper_h -#define SecADWrapper_h +#ifndef LegacyAPICounts_h +#define LegacyAPICounts_h -#include -#include +#include +#include -extern void SecADClearScalarKey(CFStringRef key); -extern void SecADSetValueForScalarKey(CFStringRef key, int64_t value); -extern void SecADAddValueForScalarKey(CFStringRef key, int64_t value); -extern void SecADClientPushValueForDistributionKey(CFStringRef key, int64_t value); +#ifdef __cplusplus +extern "C" { +#endif -#endif /* SecADWrapper_h */ +void countLegacyAPI(dispatch_once_t* token, const char* api); +void setCountLegacyAPIEnabledForThread(bool value); + +#ifdef __cplusplus +} +#endif + +#endif /* LegacyAPICounts_h */ diff --git a/OSX/libsecurity_keychain/lib/LegacyAPICounts.m b/OSX/libsecurity_keychain/lib/LegacyAPICounts.m new file mode 100644 index 00000000..04cde0fd --- /dev/null +++ b/OSX/libsecurity_keychain/lib/LegacyAPICounts.m @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020 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@ + */ + +#import +#import + +#import "LegacyAPICounts.h" +#import "utilities/SecCoreAnalytics.h" +#import "SecEntitlements.h" +#import "debugging.h" +#import "SecInternalReleasePriv.h" + +#pragma mark - File-Private + +static NSString* applicationIdentifierForSelf() { + NSString* identifier = nil; + SecTaskRef task = SecTaskCreateFromSelf(kCFAllocatorDefault); + + if (task) { + CFStringRef val = (CFStringRef)SecTaskCopyValueForEntitlement(task, kSecEntitlementApplicationIdentifier, NULL); + if (val && CFGetTypeID(val) != CFStringGetTypeID()) { + CFRelease(val); + } else { + identifier = CFBridgingRelease(val); + } + + // security tool doesn't have entitlements, I wonder if there are more. + if (!identifier) { + identifier = CFBridgingRelease(SecTaskCopySigningIdentifier(task, NULL)); + } + + CFRelease(task); + } + + return identifier; +} + +static BOOL countLegacyAPIEnabledForThread() { + NSNumber* value = [[NSThread currentThread] threadDictionary][@"countLegacyAPIEnabled"]; + + // No value means not set at all, so not disabled by SecItem* + if (!value || (value && [value isKindOfClass:[NSNumber class]] && [value boolValue])) { + return YES; + } + return NO; +} + +#pragma mark - SPI + +void setCountLegacyAPIEnabledForThread(bool value) { + [[NSThread currentThread] threadDictionary][@"countLegacyAPIEnabled"] = value ? @YES : @NO; +} + +void countLegacyAPI(dispatch_once_t* token, const char* api) { + static NSString* identifier; + static BOOL shouldCount; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + identifier = applicationIdentifierForSelf() ?: @"unknown"; + shouldCount = os_feature_enabled(Security, LegacyAPICounts); + }); + + if (api == nil) { + secerror("LegacyAPICounts: Attempt to count API without name"); + return; + } + + if (!shouldCount || !countLegacyAPIEnabledForThread()) { + return; + } + + dispatch_once(token, ^{ + NSString* apiStringObject = [NSString stringWithCString:api encoding:NSUTF8StringEncoding]; + if (!apiStringObject) { + secerror("LegacyAPICounts: Surprisingly, char* for api name \"%s\" did not turn into NSString", api); + return; + } + + [SecCoreAnalytics sendEventLazy:@"com.apple.security.LegacyAPICounts" builder:^NSDictionary * _Nonnull{ + return @{ + @"app" : identifier, + @"api" : apiStringObject, + }; + }]; + }); +} diff --git a/OSX/libsecurity_keychain/lib/Password.cpp b/OSX/libsecurity_keychain/lib/Password.cpp index 68cdcce2..783e0152 100644 --- a/OSX/libsecurity_keychain/lib/Password.cpp +++ b/OSX/libsecurity_keychain/lib/Password.cpp @@ -64,7 +64,7 @@ PasswordImpl::PasswordImpl(PasswordImpl& existing) -PasswordImpl::~PasswordImpl() throw() +PasswordImpl::~PasswordImpl() _NOEXCEPT { } diff --git a/OSX/libsecurity_keychain/lib/Password.h b/OSX/libsecurity_keychain/lib/Password.h index f142a9a4..a633fa0a 100644 --- a/OSX/libsecurity_keychain/lib/Password.h +++ b/OSX/libsecurity_keychain/lib/Password.h @@ -44,7 +44,7 @@ public: PasswordImpl(SecItemClass itemClass, SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList); PasswordImpl(PasswordImpl& existing); - virtual ~PasswordImpl() throw(); + virtual ~PasswordImpl() _NOEXCEPT; bool getData(UInt32 *length, const void **data); void setData(UInt32 length,const void *data); diff --git a/OSX/libsecurity_keychain/lib/Policies.cpp b/OSX/libsecurity_keychain/lib/Policies.cpp index 4f0cd433..c78e5356 100644 --- a/OSX/libsecurity_keychain/lib/Policies.cpp +++ b/OSX/libsecurity_keychain/lib/Policies.cpp @@ -85,7 +85,7 @@ Policy::Policy(TP supportingTp, const CssmOid &policyOid) secinfo("policy", "Policy() this %p", this); } -Policy::~Policy() throw() +Policy::~Policy() _NOEXCEPT { secinfo("policy", "~Policy() this %p", this); } diff --git a/OSX/libsecurity_keychain/lib/Policies.h b/OSX/libsecurity_keychain/lib/Policies.h index f4331b4d..b2c934a0 100644 --- a/OSX/libsecurity_keychain/lib/Policies.h +++ b/OSX/libsecurity_keychain/lib/Policies.h @@ -55,7 +55,7 @@ public: Policy(TP supportingTp, const CssmOid &policyOid); public: - virtual ~Policy() throw(); + virtual ~Policy() _NOEXCEPT; TP &tp() { return mTp; } const TP &tp() const { return mTp; } diff --git a/OSX/libsecurity_keychain/lib/PolicyCursor.cpp b/OSX/libsecurity_keychain/lib/PolicyCursor.cpp index d8db218b..6c11e107 100644 --- a/OSX/libsecurity_keychain/lib/PolicyCursor.cpp +++ b/OSX/libsecurity_keychain/lib/PolicyCursor.cpp @@ -85,7 +85,7 @@ PolicyCursor::PolicyCursor(const CSSM_OID* oid, const CSSM_DATA* value) // // Destroy // -PolicyCursor::~PolicyCursor() throw() +PolicyCursor::~PolicyCursor() _NOEXCEPT { } diff --git a/OSX/libsecurity_keychain/lib/PolicyCursor.h b/OSX/libsecurity_keychain/lib/PolicyCursor.h index c7503b68..351b641a 100644 --- a/OSX/libsecurity_keychain/lib/PolicyCursor.h +++ b/OSX/libsecurity_keychain/lib/PolicyCursor.h @@ -49,7 +49,7 @@ public: SECCFFUNCTIONS(PolicyCursor, SecPolicySearchRef, errSecInvalidSearchRef, gTypes().PolicyCursor) PolicyCursor(const CSSM_OID* oid, const CSSM_DATA* value); - virtual ~PolicyCursor() throw(); + virtual ~PolicyCursor() _NOEXCEPT; bool next(SecPointer &policy); bool oidProvided() { return mOidGiven; } diff --git a/OSX/libsecurity_keychain/lib/SecACL.cpp b/OSX/libsecurity_keychain/lib/SecACL.cpp index 5e5dbb7b..23cb2413 100644 --- a/OSX/libsecurity_keychain/lib/SecACL.cpp +++ b/OSX/libsecurity_keychain/lib/SecACL.cpp @@ -30,6 +30,8 @@ #include "SecBridge.h" +#include "LegacyAPICounts.h" + // Forward reference /*! @function GetACLAuthorizationTagFromString @@ -89,6 +91,7 @@ OSStatus SecACLCreateWithSimpleContents(SecAccessRef access, SecKeychainPromptSelector promptSelector, SecACLRef *newAcl) { + COUNTLEGACYAPI CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; cdsaPromptSelector.version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION; cdsaPromptSelector.flags = promptSelector; @@ -156,6 +159,7 @@ OSStatus SecACLCopyContents(SecACLRef acl, CFStringRef *description, SecKeychainPromptSelector *promptSelector) { + COUNTLEGACYAPI CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector)); OSStatus err = errSecSuccess; @@ -208,6 +212,7 @@ OSStatus SecACLSetContents(SecACLRef acl, CFStringRef description, SecKeychainPromptSelector promptSelector) { + COUNTLEGACYAPI CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; cdsaPromptSelector.version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION; cdsaPromptSelector.flags = promptSelector; @@ -248,6 +253,7 @@ OSStatus SecACLGetAuthorizations(SecACLRef acl, CFArrayRef SecACLCopyAuthorizations(SecACLRef acl) { + COUNTLEGACYAPI CFArrayRef result = NULL; if (NULL == acl) { @@ -310,6 +316,7 @@ OSStatus SecACLSetAuthorizations(SecACLRef aclRef, OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations) { + COUNTLEGACYAPI if (NULL == acl || NULL == authorizations) { return errSecParam; diff --git a/OSX/libsecurity_keychain/lib/SecAccess.cpp b/OSX/libsecurity_keychain/lib/SecAccess.cpp index 91680d82..44368992 100644 --- a/OSX/libsecurity_keychain/lib/SecAccess.cpp +++ b/OSX/libsecurity_keychain/lib/SecAccess.cpp @@ -34,6 +34,7 @@ #include +#include "LegacyAPICounts.h" /* No restrictions. Permission to perform all operations on the resource or available to an ACL owner. */ @@ -289,6 +290,7 @@ OSStatus SecAccessCreateFromOwnerAndACL(const CSSM_ACL_OWNER_PROTOTYPE *owner, SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAccessOwnerType ownerType, CFArrayRef acls, CFErrorRef *error) { + COUNTLEGACYAPI SecAccessRef result = NULL; CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = @@ -416,6 +418,7 @@ OSStatus SecAccessGetOwnerAndACL(SecAccessRef accessRef, OSStatus SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t* userId, gid_t* groupId, SecAccessOwnerType* ownerType, CFArrayRef* aclList) { + COUNTLEGACYAPI CSSM_ACL_OWNER_PROTOTYPE_PTR owner = NULL; CSSM_ACL_ENTRY_INFO_PTR acls = NULL; uint32 aclCount = 0; @@ -532,6 +535,7 @@ OSStatus SecAccessCopySelectedACLList(SecAccessRef accessRef, CFArrayRef SecAccessCopyMatchingACLList(SecAccessRef accessRef, CFTypeRef authorizationTag) { + COUNTLEGACYAPI CFArrayRef result = NULL; CSSM_ACL_AUTHORIZATION_TAG tag = GetACLAuthorizationTagFromString((CFStringRef)authorizationTag); OSStatus err = SecAccessCopySelectedACLList(accessRef, tag, &result); @@ -564,8 +568,9 @@ CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trus // Make a bundle instance using the URLRef. secBundle = CFBundleCreate(kCFAllocatorDefault,bundleURL); - if (!secBundle) + if (!secBundle) { goto xit; + } trustedAppListFileNameWithoutExtension = CFStringCreateMutableCopy(NULL,CFStringGetLength(trustedAppListFileName),trustedAppListFileName); @@ -575,11 +580,13 @@ CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trus // Look for a resource in the bundle by name and type trustedAppsURL = CFBundleCopyResourceURL(secBundle,trustedAppListFileNameWithoutExtension,CFSTR("plist"),NULL); - if (!trustedAppsURL) + if (!trustedAppsURL) { goto xit; + } - if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,trustedAppsURL,&xmlDataRef,NULL,NULL,&errorCode)) + if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,trustedAppsURL,&xmlDataRef,NULL,NULL,&errorCode)) { goto xit; + } trustedAppsPlist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,xmlDataRef,kCFPropertyListImmutable,&errorString); trustedAppList = (CFArrayRef)trustedAppsPlist; @@ -602,6 +609,7 @@ xit: OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess) { + COUNTLEGACYAPI OSStatus err = errSecSuccess; SecAccessRef accessToReturn=nil; CFMutableArrayRef trustedApplications=nil; diff --git a/OSX/libsecurity_keychain/lib/SecAccess.h b/OSX/libsecurity_keychain/lib/SecAccess.h index d9e151ce..01946113 100644 --- a/OSX/libsecurity_keychain/lib/SecAccess.h +++ b/OSX/libsecurity_keychain/lib/SecAccess.h @@ -127,7 +127,7 @@ CFTypeID SecAccessGetTypeID(void); @param accessRef On return, a pointer to the new access reference. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef __nullable trustedlist, SecAccessRef * __nonnull CF_RETURNS_RETAINED accessRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef __nullable trustedlist, SecAccessRef * __nonnull CF_RETURNS_RETAINED accessRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecAccessCreateFromOwnerAndACL @@ -189,7 +189,7 @@ OSStatus SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t * __nullable use @param aclList On return, a pointer to a new created CFArray of SecACL instances. The caller is responsible for calling CFRelease on this array. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecAccessCopyACLList(SecAccessRef accessRef, CFArrayRef * __nonnull CF_RETURNS_RETAINED aclList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecAccessCopyACLList(SecAccessRef accessRef, CFArrayRef * __nonnull CF_RETURNS_RETAINED aclList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecAccessCopySelectedACLList diff --git a/OSX/libsecurity_keychain/lib/SecAccessPriv.h b/OSX/libsecurity_keychain/lib/SecAccessPriv.h index 9596f4fc..c9982afe 100644 --- a/OSX/libsecurity_keychain/lib/SecAccessPriv.h +++ b/OSX/libsecurity_keychain/lib/SecAccessPriv.h @@ -39,9 +39,6 @@ extern "C" { #endif -OSStatus SecKeychainAddIToolsPassword(SecKeychainRef keychain, UInt32 accountNameLength, const char *accountName, - UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) __deprecated_msg("iTools is no longer supported") API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); - /*! @function SecAccessCreateWithTrustedApplications @abstract Creates a SecAccess object with the specified trusted applications. @@ -53,7 +50,7 @@ OSStatus SecKeychainAddIToolsPassword(SecKeychainRef keychain, UInt32 accountNam @discussion The SecAccessCreateWithPList creates a SecAccess with the provided list of trusted applications. */ -OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if defined(__cplusplus) diff --git a/OSX/libsecurity_keychain/lib/SecBase.cpp b/OSX/libsecurity_keychain/lib/SecBase.cpp index 2d82dd36..cf69d48a 100644 --- a/OSX/libsecurity_keychain/lib/SecBase.cpp +++ b/OSX/libsecurity_keychain/lib/SecBase.cpp @@ -141,10 +141,11 @@ copyErrorMessageFromBundle(OSStatus status,CFStringRef tableName) // Convert status to Int32 string representation, e.g. "-25924" keyString = CFStringCreateWithFormat (kCFAllocatorDefault,NULL,CFSTR("%d"),(int)status); - if (!keyString) + if (!keyString) { goto xit; + } - errorString = CFCopyLocalizedStringFromTableInBundle(keyString,tableName,secBundle,NULL); + errorString = CFCopyLocalizedStringFromTableInBundle(keyString,tableName,secBundle,NULL); if (CFStringCompare(errorString, keyString, 0)==kCFCompareEqualTo) // no real error message { if (errorString) diff --git a/OSX/libsecurity_keychain/lib/SecBridge.h b/OSX/libsecurity_keychain/lib/SecBridge.h index c52a5b29..c9e39bf9 100644 --- a/OSX/libsecurity_keychain/lib/SecBridge.h +++ b/OSX/libsecurity_keychain/lib/SecBridge.h @@ -30,9 +30,13 @@ #include #include #include +#include "LegacyAPICounts.h" using namespace KeychainCore; +#define COUNTLEGACYAPI static dispatch_once_t countToken; \ + countLegacyAPI(&countToken, __FUNCTION__); + // // API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions. // Usage: @@ -46,6 +50,8 @@ using namespace KeychainCore; // #define BEGIN_SECAPI \ OSStatus __secapiresult = errSecSuccess; \ + static dispatch_once_t countToken; \ + countLegacyAPI(&countToken, __FUNCTION__); \ try { #define END_SECAPI }\ catch (const MacOSError &err) { __secapiresult=err.osStatus(); } \ @@ -73,6 +79,8 @@ using namespace KeychainCore; // #define BEGIN_SECKCITEMAPI \ OSStatus __secapiresult=errSecSuccess; \ + static dispatch_once_t countToken; \ + countLegacyAPI(&countToken, __FUNCTION__); \ SecKeychainItemRef __itemImplRef=NULL; \ bool __is_certificate=(itemRef && (CFGetTypeID(itemRef) == SecCertificateGetTypeID())); \ if (__is_certificate) { \ @@ -108,6 +116,8 @@ using namespace KeychainCore; // #define BEGIN_SECCERTAPI \ OSStatus __secapiresult=errSecSuccess; \ + static dispatch_once_t countToken; \ + countLegacyAPI(&countToken, __FUNCTION__); \ SecCertificateRef __itemImplRef=NULL; \ if (SecCertificateIsItemImplInstance(certificate)) { __itemImplRef=(SecCertificateRef)CFRetain(certificate); } \ if (!__itemImplRef && certificate) { __itemImplRef=(SecCertificateRef)SecCertificateCopyKeychainItem(certificate); } \ diff --git a/OSX/libsecurity_keychain/lib/SecCertificate.cpp b/OSX/libsecurity_keychain/lib/SecCertificate.cpp index ca154314..72086112 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificate.cpp +++ b/OSX/libsecurity_keychain/lib/SecCertificate.cpp @@ -45,6 +45,7 @@ #include #include #include "CertificateValues.h" +#include "LegacyAPICounts.h" OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle); extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); @@ -72,13 +73,6 @@ SecCertificateIsItemImplInstance(SecCertificateRef certificate) CFTypeID typeID = CFGetTypeID(certificate); -#if 0 /* debug code to verify type IDs */ - syslog(LOG_ERR, "SecCertificate typeID=%d [STU=%d, OSX=%d, SKI=%d]", - (int)typeID, - (int)SecCertificateGetTypeID(), - (int)SecCertificateGetTypeID_osx(), - (int)SecKeychainItemGetTypeID()); -#endif if (typeID == _kCFRuntimeNotATypeID) { return false; } @@ -622,12 +616,14 @@ SecCertificateCopyPreference( FourCharCode itemType = 'cprf'; cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + } - Item prefItem; - if (!cursor->next(prefItem)) - MacOSError::throwMe(errSecItemNotFound); + Item prefItem; + if (!cursor->next(prefItem)) { + MacOSError::throwMe(errSecItemNotFound); + } // get persistent certificate reference SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } }; @@ -707,8 +703,9 @@ SecCertificateFindPreferenceItemWithNameAndKeyUsage( CssmData service(const_cast(idUTF8), idUTF8Len); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf'); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + } Item item; if (!cursor->next(item)) @@ -814,12 +811,11 @@ OSStatus SecCertificateSetPreference( FourCharCode itemType = 'cprf'; cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); - if (date) - ; // %%%TBI + } - Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); + Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); bool add = (!cursor->next(item)); // at this point, we either have a new item to add or an existing item to update @@ -830,10 +826,6 @@ OSStatus SecCertificateSetPreference( item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); - // date - if (date) - ; // %%%TBI - // generic attribute (store persistent certificate reference) CFDataRef pItemRef = nil; Certificate::required(__itemImplRef)->copyPersistentReference(pItemRef); @@ -876,6 +868,7 @@ OSStatus SecCertificateSetPreferred( CFStringRef name, CFArrayRef keyUsage) { + COUNTLEGACYAPI CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); return SecCertificateSetPreference(certificate, name, keyUse, NULL); } diff --git a/OSX/libsecurity_keychain/lib/SecCertificateBundle.cpp b/OSX/libsecurity_keychain/lib/SecCertificateBundle.cpp deleted file mode 100644 index 5e60033d..00000000 --- a/OSX/libsecurity_keychain/lib/SecCertificateBundle.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2002-2004,2011,2013-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@ - */ - -#include - -#include "SecBridge.h" - -#if defined(__cplusplus) -extern "C" { -#endif -// misspelled function name is declared here so symbol won't be stripped -OSStatus SecCertifcateBundleExport( - CFArrayRef itemList, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data); -#if defined(__cplusplus) -} -#endif - - -OSStatus -SecCertificateBundleImport( - SecKeychainRef keychain, - const CSSM_CERT_BUNDLE* bundle, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CFArrayRef keychainListToSkipDuplicates) -{ - BEGIN_SECAPI - - MacOSError::throwMe(errSecUnimplemented);//%%%for now - - END_SECAPI -} - - -OSStatus -SecCertificateBundleExport( - CFArrayRef certificates, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data) -{ - BEGIN_SECAPI - - MacOSError::throwMe(errSecUnimplemented);//%%%for now - - END_SECAPI -} - -// note: misspelled function name is still exported as a precaution; -// can remove this after deprecation -OSStatus -SecCertifcateBundleExport( - CFArrayRef itemList, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data) -{ - return SecCertificateBundleExport(itemList, type, encodingType, data); -} diff --git a/OSX/libsecurity_keychain/lib/SecCertificateBundle.h b/OSX/libsecurity_keychain/lib/SecCertificateBundle.h deleted file mode 100644 index a20f1bc1..00000000 --- a/OSX/libsecurity_keychain/lib/SecCertificateBundle.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2002-2004,2011,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@ - */ - -/*! - @header SecCertificateBundle - The functions provided in SecCertificateBundle implement a way to issue a certificate request to a - certificate authority. -*/ - -#ifndef _SECURITY_SECCERTIFICATEBUNDLE_H_ -#define _SECURITY_SECCERTIFICATEBUNDLE_H_ - -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @function SecCertificateBundleImport - @abstract Imports one or more certificates into a keychain with the specified encoding and bundle type. - @param keychain The destination keychain for the import. Specify NULL for the default keychain. - @param bundle A pointer to the bundle data. - @param type The bundle type as defined in cssmtype.h. - @param encodingType The bundle encoding type as defined in cssmtype.h. - @param keychainListToSkipDuplicates A reference to an array of keychains. These keychains contain certificates that shouldn't be duplicated during the import. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecCertificateBundleImport( - SecKeychainRef keychain, - const CSSM_CERT_BUNDLE* bundle, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CFArrayRef keychainListToSkipDuplicates) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecCertificateBundleExport - @abstract Exports one or more certificates into a bundle with the specified encoding and bundle type. - @param certificates An array of certificate and keychain items used to help build the bundle. - @param type The bundle type as defined in cssmtype.h. If the bundle type is unknown, an attempt will be made to determine the type for you. - @param encodingType The encoding type as defined in cssmtype.h. - @param data A pointer to data. On return, this points to the bundle data. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecCertificateBundleExport( - CFArrayRef certificates, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* misspelled version of above */ -OSStatus SecCertifcateBundleExport( - CFArrayRef itemList, - CSSM_CERT_BUNDLE_TYPE type, - CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECCERTIFICATEBUNDLE_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecExport.cpp b/OSX/libsecurity_keychain/lib/SecExport.cpp index 6473cf15..da93a08a 100644 --- a/OSX/libsecurity_keychain/lib/SecExport.cpp +++ b/OSX/libsecurity_keychain/lib/SecExport.cpp @@ -33,6 +33,7 @@ #include #include #include +#include using namespace Security; using namespace KeychainCore; diff --git a/OSX/libsecurity_keychain/lib/SecIdentity.cpp b/OSX/libsecurity_keychain/lib/SecIdentity.cpp index 5d21959b..533ecabf 100644 --- a/OSX/libsecurity_keychain/lib/SecIdentity.cpp +++ b/OSX/libsecurity_keychain/lib/SecIdentity.cpp @@ -39,6 +39,7 @@ #include #include #include +#include "LegacyAPICounts.h" /* private function declarations */ OSStatus @@ -216,6 +217,7 @@ SecIdentityCreate( SecCertificateRef certificate, SecKeyRef privateKey) { + COUNTLEGACYAPI SecIdentityRef identityRef = NULL; OSStatus __secapiresult; SecCertificateRef __itemImplRef = NULL; @@ -244,38 +246,6 @@ SecIdentityCreate( return identityRef; } -CFComparisonResult -SecIdentityCompare( - SecIdentityRef identity1, - SecIdentityRef identity2, - CFOptionFlags compareOptions) -{ - if (!identity1 || !identity2) - { - if (identity1 == identity2) - return kCFCompareEqualTo; - else if (identity1 < identity2) - return kCFCompareLessThan; - else - return kCFCompareGreaterThan; - } - - try { - SecPointer id1(Identity::required(identity1)); - SecPointer id2(Identity::required(identity2)); - - if (id1 == id2) - return kCFCompareEqualTo; - else if (id1 < id2) - return kCFCompareLessThan; - else - return kCFCompareGreaterThan; - } catch(...) - {} - - return kCFCompareGreaterThan; -} - static CFArrayRef _SecIdentityCopyPossiblePaths( CFStringRef name) @@ -401,8 +371,9 @@ OSStatus _SecIdentityCopyPreferenceMatchingName( FourCharCode itemType = 'iprf'; cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + } Item prefItem; if (!cursor->next(prefItem)) @@ -681,50 +652,11 @@ OSStatus SecIdentitySetPreference( OSStatus SecIdentitySetPreferred(SecIdentityRef identity, CFStringRef name, CFArrayRef keyUsage) { + COUNTLEGACYAPI CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); return SecIdentitySetPreference(identity, name, keyUse); } -OSStatus -SecIdentityFindPreferenceItem( - CFTypeRef keychainOrArray, - CFStringRef idString, - SecKeychainItemRef *itemRef) -{ - BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecIdentityFindPreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); - os_activity_scope(activity); - os_release(activity); - - StorageManager::KeychainList keychains; - globals().storageManager.optionalSearchList(keychainOrArray, keychains); - KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); - - char idUTF8[MAXPATHLEN]; - idUTF8[0] = (char)'\0'; - if (idString) - { - if (!CFStringGetCString(idString, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8)) - idUTF8[0] = (char)'\0'; - } - size_t idUTF8Len = strlen(idUTF8); - if (!idUTF8Len) - MacOSError::throwMe(errSecParam); - - CssmData service(const_cast(idUTF8), idUTF8Len); - cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); - cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); - - Item item; - if (!cursor->next(item)) - MacOSError::throwMe(errSecItemNotFound); - - if (itemRef) - *itemRef=item->handle(); - - END_SECAPI -} - OSStatus SecIdentityFindPreferenceItemWithNameAndKeyUsage( CFTypeRef keychainOrArray, @@ -755,8 +687,9 @@ SecIdentityFindPreferenceItemWithNameAndKeyUsage( CssmData service(const_cast(idUTF8), idUTF8Len); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); - if (keyUsage) + if (keyUsage) { cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); + } Item item; if (!cursor->next(item)) @@ -773,6 +706,7 @@ OSStatus SecIdentityDeletePreferenceItemWithNameAndKeyUsage( CFStringRef name, int32_t keyUsage) { + COUNTLEGACYAPI // when a specific key usage is passed, we'll only match & delete that pref; // when a key usage of 0 is passed, all matching prefs should be deleted. // maxUsages represents the most matches there could theoretically be, so @@ -793,295 +727,6 @@ OSStatus SecIdentityDeletePreferenceItemWithNameAndKeyUsage( return (status == errSecItemNotFound) ? errSecSuccess : status; } - -static -OSStatus _SecIdentityAddPreferenceItemWithName( - SecKeychainRef keychainRef, - SecIdentityRef identityRef, - CFStringRef idString, - SecKeychainItemRef *itemRef) -{ - // this is NOT exported, and called only from SecIdentityAddPreferenceItem (below), so no BEGIN/END macros here; - // caller must handle exceptions - - if (!identityRef || !idString) - return errSecParam; - SecPointer cert(Identity::required(identityRef)->certificate()); - Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); - sint32 keyUsage = 0; - - // determine the account attribute - // - // This attribute must be synthesized from certificate label + pref item type + key usage, - // as only the account and service attributes can make a generic keychain item unique. - // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that - // we can save a certificate preference if an identity preference already exists for the - // given service name, and vice-versa. - // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. - // - CFStringRef labelStr = nil; - cert->inferLabel(false, &labelStr); - if (!labelStr) { - return errSecDataTooLarge; // data is "in a format which cannot be displayed" - } - CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; - const char *templateStr = "%s [key usage 0x%X]"; - const int keyUsageMaxStrLen = 8; - accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; - char *accountUTF8 = (char *)malloc(accountUTF8Len); - if (!accountUTF8) { - MacOSError::throwMe(errSecMemoryError); - } - if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) - accountUTF8[0] = (char)'\0'; - if (keyUsage) - snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); - snprintf(accountUTF8, accountUTF8Len-1, "%s ", accountUTF8); - CssmDataContainer account(const_cast(accountUTF8), strlen(accountUTF8)); - free(accountUTF8); - CFRelease(labelStr); - - // service attribute (name provided by the caller) - CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(idString), kCFStringEncodingUTF8) + 1;; - char *serviceUTF8 = (char *)malloc(serviceUTF8Len); - if (!serviceUTF8) { - MacOSError::throwMe(errSecMemoryError); - } - if (!CFStringGetCString(idString, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) - serviceUTF8[0] = (char)'\0'; - CssmDataContainer service(const_cast(serviceUTF8), strlen(serviceUTF8)); - free(serviceUTF8); - - // set item attribute values - item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service); - item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); - item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'iprf'); - item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); - item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), keyUsage); - - // generic attribute (store persistent certificate reference) - CFDataRef pItemRef = nil; - OSStatus status = SecKeychainItemCreatePersistentReference((SecKeychainItemRef)cert->handle(), &pItemRef); - if (!pItemRef) - status = errSecInvalidItemRef; - if (status) - return status; - const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); - CFIndex dataLen = CFDataGetLength(pItemRef); - CssmData pref(const_cast(reinterpret_cast(dataPtr)), dataLen); - item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); - CFRelease(pItemRef); - - Keychain keychain = nil; - try { - keychain = Keychain::optional(keychainRef); - if (!keychain->exists()) - MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. - } - catch(...) { - keychain = globals().storageManager.defaultKeychainUI(item); - } - - try { - keychain->add(item); - } - catch (const MacOSError &err) { - if (err.osStatus() != errSecDuplicateItem) - throw; // if item already exists, fall through to update - } - - item->update(); - - if (itemRef) - *itemRef = item->handle(); - - return status; -} - -OSStatus SecIdentityAddPreferenceItem( - SecKeychainRef keychainRef, - SecIdentityRef identityRef, - CFStringRef idString, - SecKeychainItemRef *itemRef) -{ - // The original implementation of SecIdentityAddPreferenceItem adds the exact string only. - // That implementation has been moved to _SecIdentityAddPreferenceItemWithName (above), - // and this function is a wrapper which calls it, so that existing clients will get the - // extended behavior of server domain matching for items that specify URLs. - // (Note that behavior is unchanged if the specified idString is not a URL.) - - BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecIdentityAddPreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); - os_activity_scope(activity); - os_release(activity); - - OSStatus status = errSecInternalComponent; - CFArrayRef names = _SecIdentityCopyPossiblePaths(idString); - if (!names) { - return status; - } - - CFIndex total = CFArrayGetCount(names); - if (total > 0) { - // add item for name (first element in array) - CFStringRef aName = (CFStringRef)CFArrayGetValueAtIndex(names, 0); - try { - status = _SecIdentityAddPreferenceItemWithName(keychainRef, identityRef, aName, itemRef); - } - catch (const MacOSError &err) { status=err.osStatus(); } - catch (const CommonError &err) { status=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { status=errSecAllocate; } - catch (...) { status=errSecInternalComponent; } - } - if (total > 2) { - Boolean setDomainDefaultIdentity = FALSE; - CFTypeRef val = (CFTypeRef)CFPreferencesCopyValue(CFSTR("SetDomainDefaultIdentity"), - CFSTR("com.apple.security.identities"), - kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); - if (val) { - if (CFGetTypeID(val) == CFBooleanGetTypeID()) - setDomainDefaultIdentity = CFBooleanGetValue((CFBooleanRef)val) ? TRUE : FALSE; - CFRelease(val); - } - if (setDomainDefaultIdentity) { - // add item for domain (second-to-last element in array, e.g. "*.apple.com") - OSStatus tmpStatus = errSecSuccess; - CFStringRef aName = (CFStringRef)CFArrayGetValueAtIndex(names, total-2); - try { - tmpStatus = _SecIdentityAddPreferenceItemWithName(keychainRef, identityRef, aName, itemRef); - } - catch (const MacOSError &err) { tmpStatus=err.osStatus(); } - catch (const CommonError &err) { tmpStatus=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { tmpStatus=errSecAllocate; } - catch (...) { tmpStatus=errSecInternalComponent; } - } - } - - CFRelease(names); - return status; - - END_SECAPI -} - -/* deprecated in 10.5 */ -OSStatus SecIdentityUpdatePreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef identityRef) -{ - BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecIdentityUpdatePreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); - os_activity_scope(activity); - os_release(activity); - - if (!itemRef || !identityRef) - MacOSError::throwMe(errSecParam); - SecPointer certificate(Identity::required(identityRef)->certificate()); - Item prefItem = ItemImpl::required(itemRef); - - // get the current key usage value for this item - sint32 keyUsage = 0; - UInt32 actLen = 0; - SecKeychainAttribute attr = { kSecScriptCodeItemAttr, sizeof(sint32), &keyUsage }; - try { - prefItem->getAttribute(attr, &actLen); - } - catch(...) { - keyUsage = 0; - }; - - // set the account attribute - // - // This attribute must be synthesized from certificate label + pref item type + key usage, - // as only the account and service attributes can make a generic keychain item unique. - // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that - // we can save a certificate preference if an identity preference already exists for the - // given service name, and vice-versa. - // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. - // - CFStringRef labelStr = nil; - certificate->inferLabel(false, &labelStr); - if (!labelStr) { - MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed" - } - CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; - const char *templateStr = "%s [key usage 0x%X]"; - const int keyUsageMaxStrLen = 8; - accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; - char *accountUTF8 = (char *)malloc(accountUTF8Len); - if (!accountUTF8) { - MacOSError::throwMe(errSecMemoryError); - } - if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) - accountUTF8[0] = (char)'\0'; - if (keyUsage) - snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); - snprintf(accountUTF8, accountUTF8Len-1, "%s ", accountUTF8); - CssmDataContainer account(const_cast(accountUTF8), strlen(accountUTF8)); - prefItem->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); - free(accountUTF8); - CFRelease(labelStr); - - // generic attribute (store persistent certificate reference) - CFDataRef pItemRef = nil; - OSStatus status = SecKeychainItemCreatePersistentReference((SecKeychainItemRef)certificate->handle(), &pItemRef); - if (!pItemRef) - status = errSecInvalidItemRef; - if (status) - MacOSError::throwMe(status); - const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); - CFIndex dataLen = CFDataGetLength(pItemRef); - CssmData pref(const_cast(reinterpret_cast(dataPtr)), dataLen); - prefItem->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); - CFRelease(pItemRef); - - prefItem->update(); - - END_SECAPI -} - -OSStatus SecIdentityCopyFromPreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef *identityRef) -{ - BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecIdentityCopyFromPreferenceItem", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); - os_activity_scope(activity); - os_release(activity); - - if (!itemRef || !identityRef) - MacOSError::throwMe(errSecParam); - Item prefItem = ItemImpl::required(itemRef); - - // get persistent certificate reference - SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } }; - SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs }; - prefItem->getContent(NULL, &itemAttrList, NULL, NULL); - - // find certificate, given persistent reference data - CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull); - SecKeychainItemRef certItemRef = nil; - OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl - prefItem->freeContent(&itemAttrList, NULL); - if (pItemRef) - CFRelease(pItemRef); - if (status) - return status; - - // create identity reference, given certificate - StorageManager::KeychainList keychains; - globals().storageManager.optionalSearchList((CFTypeRef)NULL, keychains); - Item certItem = ItemImpl::required(SecKeychainItemRef(certItemRef)); - SecPointer certificate(static_cast(certItem.get())); - SecPointer identity(new Identity(keychains, certificate)); - if (certItemRef) - CFRelease(certItemRef); - - Required(identityRef) = identity->handle(); - - END_SECAPI -} - /* * System Identity Support. */ @@ -1114,7 +759,7 @@ OSStatus SecIdentityCopySystemIdentity( os_release(activity); StLock _(systemIdentityLock()); - auto_ptr identDict; + unique_ptr identDict; /* get top-level dictionary - if not present, we're done */ Dictionary* d = Dictionary::CreateDictionary(IDENTITY_DOMAIN, Dictionary::US_System); @@ -1189,7 +834,7 @@ OSStatus SecIdentitySetSystemIdentity( MacOSError::throwMe(errSecAuthFailed); } - auto_ptr identDict; + unique_ptr identDict; MutableDictionary *d = MutableDictionary::CreateMutableDictionary(IDENTITY_DOMAIN, Dictionary::US_System); if (d) { diff --git a/OSX/libsecurity_keychain/lib/SecIdentitySearch.cpp b/OSX/libsecurity_keychain/lib/SecIdentitySearch.cpp index b3f58d60..d91069cc 100644 --- a/OSX/libsecurity_keychain/lib/SecIdentitySearch.cpp +++ b/OSX/libsecurity_keychain/lib/SecIdentitySearch.cpp @@ -29,7 +29,7 @@ #include #include "SecBridge.h" - +#include "LegacyAPICounts.h" CFTypeID SecIdentitySearchGetTypeID(void) diff --git a/OSX/libsecurity_keychain/lib/SecImportExportPem.cpp b/OSX/libsecurity_keychain/lib/SecImportExportPem.cpp index df675564..3a4fb9a0 100644 --- a/OSX/libsecurity_keychain/lib/SecImportExportPem.cpp +++ b/OSX/libsecurity_keychain/lib/SecImportExportPem.cpp @@ -32,6 +32,8 @@ #include #include +#include + /* * Text parsing routines. * diff --git a/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp b/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp index 165d567c..f0b988f4 100644 --- a/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp +++ b/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #define SecPkcs8Dbg(args...) secinfo("SecPkcs8", ## args) diff --git a/OSX/libsecurity_keychain/lib/SecItem.cpp b/OSX/libsecurity_keychain/lib/SecItem.cpp index 2cdb17f9..e5b078ad 100644 --- a/OSX/libsecurity_keychain/lib/SecItem.cpp +++ b/OSX/libsecurity_keychain/lib/SecItem.cpp @@ -42,6 +42,7 @@ #include #include "utilities/array_size.h" #include "utilities/SecCFWrappers.h" +#include "LegacyAPICounts.h" #include #include @@ -71,8 +72,6 @@ OSStatus SecItemAdd_ios(CFDictionaryRef attributes, CFTypeRef *result); OSStatus SecItemCopyMatching_ios(CFDictionaryRef query, CFTypeRef *result); OSStatus SecItemUpdate_ios(CFDictionaryRef query, CFDictionaryRef attributesToUpdate); OSStatus SecItemDelete_ios(CFDictionaryRef query); -OSStatus SecItemUpdateTokenItems_ios(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes); - OSStatus SecItemValidateAppleApplicationGroupAccess(CFStringRef group); CFDictionaryRef SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTypeRef itemClass, @@ -3827,6 +3826,8 @@ AddItemResults(SecKeychainItemRef item, // // Note that we allocate *items if needed. + CFTypeRef localResult = NULL; + if (!item || !itemParams || !result) return errSecParam; @@ -3855,7 +3856,8 @@ AddItemResults(SecKeychainItemRef item, CFArrayAppendValue(itemArray, itemRef); } else { - *result = CFRetain((CFTypeRef)itemRef); + CFReleaseNull(localResult); + localResult = CFRetain((CFTypeRef)itemRef); } } @@ -3874,7 +3876,8 @@ AddItemResults(SecKeychainItemRef item, CFArrayAppendValue(itemArray, persistentRef); } else { - *result = CFRetain(persistentRef); + CFReleaseNull(localResult); + localResult = CFRetain(persistentRef); } CFRelease(persistentRef); } @@ -3898,7 +3901,8 @@ AddItemResults(SecKeychainItemRef item, CFArrayAppendValue(itemArray, dataRef); } else { - *result = CFRetain(dataRef); + CFReleaseNull(localResult); + localResult = CFRetain(dataRef); } CFRelease(dataRef); status = errSecSuccess; @@ -3920,7 +3924,8 @@ AddItemResults(SecKeychainItemRef item, CFArrayAppendValue(itemArray, dataRef); } else { - *result = CFRetain(dataRef); + CFReleaseNull(localResult); + localResult = CFRetain(dataRef); } CFRelease(dataRef); (void) SecKeychainItemFreeContent(NULL, data); @@ -3949,7 +3954,8 @@ AddItemResults(SecKeychainItemRef item, CFArrayAppendValue(itemArray, attrsDict); } else { - *result = CFRetain(attrsDict); + CFReleaseNull(localResult); + localResult = CFRetain(attrsDict); } CFRelease(attrsDict); } @@ -3962,14 +3968,22 @@ AddItemResults(SecKeychainItemRef item, if (itemArray) { CFArrayAppendValue(itemArray, itemDict); CFRelease(itemDict); - *result = itemArray; + CFReleaseNull(localResult); + localResult = itemArray; } else { - *result = itemDict; + CFReleaseNull(localResult); + localResult = itemDict; } } else if (itemArray) { - *result = itemArray; + CFReleaseNull(localResult); + localResult = itemArray; + } + + if (localResult) { + *result = localResult; + localResult = NULL; } return status; @@ -5082,14 +5096,6 @@ SecItemDelete(CFDictionaryRef query) return status; } -OSStatus -SecItemUpdateTokenItems(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes) -{ - OSStatus status = SecItemUpdateTokenItems_ios(tokenID, tokenItemsAttributes); - secitemlog(LOG_NOTICE, "SecItemUpdateTokenItems_ios result: %d", status); - return status; -} - OSStatus SecItemCopyMatching_osx( CFDictionaryRef query, @@ -5100,6 +5106,8 @@ SecItemCopyMatching_osx( else *result = NULL; + setCountLegacyAPIEnabledForThread(false); + CFAllocatorRef allocator = CFGetAllocator(query); CFIndex matchCount = 0; CFMutableArrayRef itemArray = NULL; @@ -5144,20 +5152,9 @@ error_exit: } _FreeSecItemParams(itemParams); - return status; -} + setCountLegacyAPIEnabledForThread(true); -OSStatus -SecItemCopyDisplayNames( - CFArrayRef items, - CFArrayRef *displayNames) -{ - BEGIN_SECAPI - Required(items); - Required(displayNames); - //%%%TBI - return errSecUnimplemented; - END_SECAPI + return status; } OSStatus @@ -5170,6 +5167,8 @@ SecItemAdd_osx( else if (result) *result = NULL; + setCountLegacyAPIEnabledForThread(false); + CFAllocatorRef allocator = CFGetAllocator(attributes); CFMutableArrayRef itemArray = NULL; SecKeychainItemRef item = NULL; @@ -5303,6 +5302,7 @@ error_exit: *result = NULL; } _FreeSecItemParams(itemParams); + setCountLegacyAPIEnabledForThread(true); return status; } @@ -5330,6 +5330,8 @@ SecItemUpdate_osx( CFRelease(results); } + setCountLegacyAPIEnabledForThread(false); + OSStatus result = errSecSuccess; CFIndex ix, count = CFArrayGetCount(items); for (ix=0; ix < count; ix++) { @@ -5340,6 +5342,8 @@ SecItemUpdate_osx( } } + setCountLegacyAPIEnabledForThread(true); + if (items) { CFRelease(items); } @@ -5368,6 +5372,8 @@ SecItemDelete_osx( CFRelease(results); } + setCountLegacyAPIEnabledForThread(false); + OSStatus result = errSecSuccess; CFIndex ix, count = CFArrayGetCount(items); for (ix=0; ix < count; ix++) { @@ -5383,6 +5389,8 @@ SecItemDelete_osx( } } + setCountLegacyAPIEnabledForThread(true); + if (items) CFRelease(items); diff --git a/OSX/libsecurity_keychain/lib/SecItemConstants.c b/OSX/libsecurity_keychain/lib/SecItemConstants.c index 4f56a5c7..40552090 100644 --- a/OSX/libsecurity_keychain/lib/SecItemConstants.c +++ b/OSX/libsecurity_keychain/lib/SecItemConstants.c @@ -126,6 +126,13 @@ SEC_CONST_DECL (kSecAttrRounds, "rounds"); //SEC_CONST_DECL (kSecAttrPCSPlaintextPublicKey, "pcsk"); //SEC_CONST_DECL (kSecAttrPCSPlaintextPublicIdentity, "pcsi"); +//SEC_CONST_DECL (kSecDataInetExtraNotes, "binn"); +//SEC_CONST_DECL (kSecDataInetExtraHistory, "bini"); +//SEC_CONST_DECL (kSecDataInetExtraClientDefined0, "bin0"); +//SEC_CONST_DECL (kSecDataInetExtraClientDefined1, "bin1"); +//SEC_CONST_DECL (kSecDataInetExtraClientDefined2, "bin2"); +//SEC_CONST_DECL (kSecDataInetExtraClientDefined3, "bin3"); + /* Predefined access groups constants */ //SEC_CONST_DECL (kSecAttrAccessGroupToken, "com.apple.token"); diff --git a/OSX/libsecurity_keychain/lib/SecKey.cpp b/OSX/libsecurity_keychain/lib/SecKey.cpp index 7ef6027b..940caae2 100644 --- a/OSX/libsecurity_keychain/lib/SecKey.cpp +++ b/OSX/libsecurity_keychain/lib/SecKey.cpp @@ -804,20 +804,19 @@ static Boolean SecCDSAKeySetParameter(SecKeyRef key, CFStringRef name, CFPropert const SecKeyDescriptor kSecCDSAKeyDescriptor = { .version = kSecKeyDescriptorVersion, .name = "CDSAKey", + .extraBytes = (sizeof(class CDSASecKey) > sizeof(struct __SecKey) ? (sizeof(class CDSASecKey) - sizeof(struct __SecKey)) : 0), .init = SecCDSAKeyInit, .destroy = SecCDSAKeyDestroy, .blockSize = SecCDSAKeyGetBlockSize, - .getAlgorithmID = SecCDSAKeyGetAlgorithmId, .copyDictionary = SecCDSAKeyCopyAttributeDictionary, + .getAlgorithmID = SecCDSAKeyGetAlgorithmId, .copyPublic = SecCDSAKeyCopyPublicBytes, .copyExternalRepresentation = SecCDSAKeyCopyExternalRepresentation, .copyPublicKey = SecCDSAKeyCopyPublicKey, .copyOperationResult = SecCDSAKeyCopyOperationResult, .isEqual = SecCDSAKeyIsEqual, .setParameter = SecCDSAKeySetParameter, - - .extraBytes = (sizeof(class CDSASecKey) > sizeof(struct __SecKey) ? (sizeof(class CDSASecKey) - sizeof(struct __SecKey)) : 0), }; namespace Security { diff --git a/OSX/libsecurity_keychain/lib/SecKeychain.cpp b/OSX/libsecurity_keychain/lib/SecKeychain.cpp index 53265b95..ca80c80b 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychain.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychain.cpp @@ -39,12 +39,18 @@ #include #include #include "TokenLogin.h" +#include "LegacyAPICounts.h" + +extern "C" { +#include "ctkloginhelper.h" +} OSStatus SecKeychainMDSInstall() { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainMDSInstall", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainMDSInstall", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -68,6 +74,7 @@ SecKeychainGetTypeID(void) OSStatus SecKeychainGetVersion(UInt32 *returnVers) { + COUNTLEGACYAPI if (!returnVers) return errSecSuccess; @@ -80,47 +87,23 @@ OSStatus SecKeychainOpen(const char *pathName, SecKeychainRef *keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainOpen", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); - os_activity_scope(activity); - os_release(activity); - - RequiredParam(keychainRef)=globals().storageManager.make(pathName, false)->handle(); - - END_SECAPI -} - -OSStatus -SecKeychainOpenWithGuid(const CSSM_GUID *guid, uint32 subserviceId, uint32 subserviceType, const char* dbName, - const CSSM_NET_ADDRESS *dbLocation, SecKeychainRef *keychain) -{ - BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainOpenWithGuid", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + os_activity_t activity = os_activity_create("SecKeychainOpen", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); - // range check parameters - RequiredParam (guid); - RequiredParam (dbName); - - // create a DLDbIdentifier that describes what should be opened - const CSSM_VERSION *version = NULL; - const CssmSubserviceUid ssuid(*guid, version, subserviceId, subserviceType); - DLDbIdentifier dLDbIdentifier(ssuid, dbName, dbLocation); - - // make a keychain from the supplied info - RequiredParam(keychain) = globals().storageManager.makeKeychain(dLDbIdentifier, false, false)->handle (); + RequiredParam(keychainRef)=globals().storageManager.make(pathName, false)->handle(); END_SECAPI } - OSStatus SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void *password, Boolean promptUser, SecAccessRef initialAccess, SecKeychainRef *keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCreate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCreate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -147,7 +130,8 @@ OSStatus SecKeychainDelete(SecKeychainRef keychainOrArray) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -165,7 +149,8 @@ OSStatus SecKeychainSetSettings(SecKeychainRef keychainRef, const SecKeychainSettings *newSettings) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetSettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetSettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -185,7 +170,8 @@ OSStatus SecKeychainCopySettings(SecKeychainRef keychainRef, SecKeychainSettings *outSettings) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopySettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopySettings", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -208,7 +194,8 @@ OSStatus SecKeychainUnlock(SecKeychainRef keychainRef, UInt32 passwordLength, const void *password, Boolean usePassword) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainUnlock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainUnlock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -227,7 +214,8 @@ OSStatus SecKeychainLock(SecKeychainRef keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainLock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainLock", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -242,7 +230,8 @@ OSStatus SecKeychainLockAll(void) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainLockAll", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainLockAll", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -255,7 +244,8 @@ SecKeychainLockAll(void) OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Boolean resetSearchList) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainResetLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainResetLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); // @@ -322,7 +312,8 @@ OSStatus SecKeychainSetDefault(SecKeychainRef keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -334,7 +325,8 @@ SecKeychainSetDefault(SecKeychainRef keychainRef) OSStatus SecKeychainCopySearchList(CFArrayRef *searchList) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopySearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopySearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -350,7 +342,8 @@ OSStatus SecKeychainCopySearchList(CFArrayRef *searchList) OSStatus SecKeychainSetSearchList(CFArrayRef searchList) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -366,7 +359,8 @@ OSStatus SecKeychainSetSearchList(CFArrayRef searchList) OSStatus SecKeychainCopyDomainDefault(SecPreferencesDomain domain, SecKeychainRef *keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopyDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopyDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -378,7 +372,8 @@ OSStatus SecKeychainCopyDomainDefault(SecPreferencesDomain domain, SecKeychainRe OSStatus SecKeychainSetDomainDefault(SecPreferencesDomain domain, SecKeychainRef keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetDomainDefault", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -403,7 +398,8 @@ OSStatus SecKeychainCopyDomainSearchList(SecPreferencesDomain domain, CFArrayRef OSStatus SecKeychainSetDomainSearchList(SecPreferencesDomain domain, CFArrayRef searchList) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetDomainSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetDomainSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -419,7 +415,8 @@ OSStatus SecKeychainSetDomainSearchList(SecPreferencesDomain domain, CFArrayRef OSStatus SecKeychainSetPreferenceDomain(SecPreferencesDomain domain) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -431,7 +428,8 @@ OSStatus SecKeychainSetPreferenceDomain(SecPreferencesDomain domain) OSStatus SecKeychainGetPreferenceDomain(SecPreferencesDomain *domain) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainGetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainGetPreferenceDomain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -478,7 +476,7 @@ SecKeychainGetKeychainVersion(SecKeychainRef keychainRef, UInt32* version) { BEGIN_SECAPI - RequiredParam(version); + RequiredParam(version); *version = Keychain::optional(keychainRef)->database()->dbBlobVersion(); @@ -489,7 +487,8 @@ OSStatus SecKeychainAttemptMigrationWithMasterKey(SecKeychainRef keychain, UInt32 version, const char* masterKeyFilename) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainAttemptMigrationWithMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainAttemptMigrationWithMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -587,7 +586,8 @@ pascal OSStatus SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void* userContext) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainAddCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainAddCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -602,7 +602,8 @@ OSStatus SecKeychainRemoveCallback(SecKeychainCallback callbackFunction) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainRemoveCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainRemoveCallback", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -616,7 +617,8 @@ OSStatus SecKeychainAddInternetPassword(SecKeychainRef keychainRef, UInt32 serverNameLength, const char *serverName, UInt32 securityDomainLength, const char *securityDomain, UInt32 accountNameLength, const char *accountName, UInt32 pathLength, const char *path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainAddInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainAddInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -678,7 +680,8 @@ SecKeychainFindInternetPassword(CFTypeRef keychainOrArray, UInt32 serverNameLeng { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainFindInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainFindInternetPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -757,7 +760,8 @@ OSStatus SecKeychainAddGenericPassword(SecKeychainRef keychainRef, UInt32 serviceNameLength, const char *serviceName, UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainAddGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainAddGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -806,7 +810,8 @@ SecKeychainFindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLeng { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainFindGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainFindGenericPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -878,7 +883,8 @@ OSStatus SecKeychainGetDLDBHandle(SecKeychainRef keychainRef, CSSM_DL_DB_HANDLE *dldbHandle) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainGetDLDBHandle", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainGetDLDBHandle", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -944,7 +950,8 @@ OSStatus SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainChangePassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainChangePassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -959,7 +966,8 @@ OSStatus SecKeychainCopyLogin(SecKeychainRef *keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopyLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopyLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -973,7 +981,8 @@ OSStatus SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, const void* password) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainLogin", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1009,7 +1018,8 @@ SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, con OSStatus SecKeychainStash() { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainStash", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainStash", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1036,7 +1046,8 @@ OSStatus SecKeychainLogout() { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainLogout", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainLogout", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1059,7 +1070,8 @@ static Keychain make(const char *name) OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef) { BEGIN_SECAPI - RequiredParam(fullPathName); + + RequiredParam(fullPathName); RequiredParam(keychainRef)=make(fullPathName)->handle(); END_SECAPI } @@ -1070,7 +1082,8 @@ OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *k OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid) { BEGIN_SECAPI - *isValid = false; + + *isValid = false; if (KeychainImpl::optional(keychainRef)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL) *isValid = true; END_SECAPI @@ -1081,7 +1094,8 @@ OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid) OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainRemoveFromSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainRemoveFromSearchList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); StorageManager::KeychainList singleton; @@ -1095,7 +1109,8 @@ OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef) OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, const char* inPassword) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCreateNew", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCreateNew", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); RequiredParam(inPassword); @@ -1108,7 +1123,8 @@ OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlobArray, CFDataRef extraData) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainRecodeKeychain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainRecodeKeychain", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1186,7 +1202,8 @@ OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlob OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychainSignature) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopySignature", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopySignature", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1213,7 +1230,8 @@ OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychai OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCopyBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCopyBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1235,7 +1253,8 @@ OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob) OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, SecKeychainRef *kcRef) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainCreateWithBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainCreateWithBlob", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1262,7 +1281,8 @@ OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char const CSSM_GUID *guid, uint32 subServiceType) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainAddDBToKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainAddDBToKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1278,7 +1298,8 @@ OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char* const CSSM_GUID *guid, uint32 subServiceType) { BEGIN_SECAPI - RequiredParam(dbName); + + RequiredParam(dbName); StorageManager &smr = globals().storageManager; smr.isInDomainList(domain, dbName, *guid, subServiceType); END_SECAPI @@ -1289,7 +1310,8 @@ OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const const CSSM_GUID *guid, uint32 subServiceType) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainRemoveDBFromKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainRemoveDBFromKeychainList", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); RequiredParam(dbName); @@ -1310,7 +1332,8 @@ void SecKeychainSetServerMode() OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainSetBatchMode", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainSetBatchMode", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); RequiredParam(kcRef); @@ -1324,13 +1347,15 @@ OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean ro OSStatus SecKeychainCleanupHandles() { BEGIN_SECAPI - END_SECAPI // which causes the handle cache cleanup routine to run + + END_SECAPI // which causes the handle cache cleanup routine to run } OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainVerifyKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainVerifyKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); SecurityServer::ClientSession().verifyKeyStorePassphrase(retries); @@ -1340,7 +1365,8 @@ OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries) OSStatus SecKeychainChangeKeyStorePassphrase() { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainChangeKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainChangeKeyStorePassphrase", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); SecurityServer::ClientSession().changeKeyStorePassphrase(); @@ -1350,7 +1376,8 @@ OSStatus SecKeychainChangeKeyStorePassphrase() static OSStatus SecKeychainGetMasterKey(SecKeychainRef userKeychainRef, CFDataRef *masterKey, CFStringRef password) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecKeychainGetMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); + + os_activity_t activity = os_activity_create("SecKeychainGetMasterKey", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1468,6 +1495,7 @@ static bool _SASetAutologinPW(CFStringRef inAutologinPW) } OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) { + COUNTLEGACYAPI SecTrustedApplicationRef itemPath; SecAccessRef ourAccessRef = NULL; @@ -1568,6 +1596,7 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe OSStatus SecKeychainGetUserPromptAttempts(uint32_t * attempts) { BEGIN_SECAPI + os_activity_t activity = os_activity_create("SecKeychainGetUserPromptAttempts", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -1582,6 +1611,7 @@ OSStatus SecKeychainGetUserPromptAttempts(uint32_t * attempts) OSStatus SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash, CFStringRef tokenID, CFDataRef wrapPubKeyHash, SecKeychainRef userKeychain, CFStringRef password) { + COUNTLEGACYAPI CFRef pwd; OSStatus result; @@ -1667,15 +1697,32 @@ OSStatus SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash, CFStringR } secnotice("SecKeychain", "SecKeychainStoreUnlockKeyWithPubKeyHash result %d", (int) result); + + // create SC KEK + // this might fail if KC password is different from user's password + uid_t uid = geteuid(); + if (!uid) { + uid = getuid(); + } + struct passwd *passwd = getpwuid(uid); + if (passwd) { + CFRef username = CFStringCreateWithCString(kCFAllocatorDefault, passwd->pw_name, kCFStringEncodingUTF8); + OSStatus kekRes = TKAddSecureToken(username, pwd, tokenID, wrapPubKeyHash); + if (kekRes != noErr) { + secnotice("SecKeychain", "Failed to register SC token: %d", (int) kekRes); // do not fail because KC functionality be still OK + } + } else { + secnotice("SecKeychain", "Unable to get name for uid %d", uid); + } return result; } OSStatus SecKeychainEraseUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash) { + COUNTLEGACYAPI OSStatus result = TokenLoginDeleteUnlockData(pubKeyHash); if (result != errSecSuccess) { secnotice("SecKeychain", "Failed to erase stored wrapped unlock key: %d", (int) result); } return result; } - diff --git a/OSX/libsecurity_keychain/lib/SecKeychain.h b/OSX/libsecurity_keychain/lib/SecKeychain.h index b8329154..b95f2ec5 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychain.h +++ b/OSX/libsecurity_keychain/lib/SecKeychain.h @@ -250,14 +250,14 @@ typedef CF_OPTIONS(UInt32, SecKeychainEventMask) @field pid The id of the process that generated this event. @discussion The SecKeychainCallbackInfo type represents a structure that contains information about the keychain event for which your application is being notified. For information on how to write a keychain event callback function, see SecKeychainCallback. */ -struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) SecKeychainCallbackInfo +struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) SecKeychainCallbackInfo { UInt32 version; SecKeychainItemRef __nonnull item; SecKeychainRef __nonnull keychain; pid_t pid; }; -typedef struct SecKeychainCallbackInfo SecKeychainCallbackInfo API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct SecKeychainCallbackInfo SecKeychainCallbackInfo API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainGetTypeID @@ -297,7 +297,7 @@ OSStatus SecKeychainOpen(const char *pathName, SecKeychainRef * __nonnull CF_RET @param keychain On return, a pointer to a keychain reference. The memory that keychain occupies must be released by calling CFRelease when finished with it. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if the keychain parameter is invalid (NULL). */ -OSStatus SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void * __nullable password, Boolean promptUser, SecAccessRef __nullable initialAccess, SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void * __nullable password, Boolean promptUser, SecAccessRef __nullable initialAccess, SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainDelete @@ -305,7 +305,7 @@ OSStatus SecKeychainCreate(const char *pathName, UInt32 passwordLength, const vo @param keychainOrArray A single keychain reference or a reference to an array of keychains to delete. IMPORTANT: SecKeychainDelete does not dispose the memory occupied by keychain references; use the CFRelease function when you are completely finished with a keychain. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecInvalidKeychain (-25295) may be returned if the keychain parameter is invalid (NULL). */ -OSStatus SecKeychainDelete(SecKeychainRef __nullable keychainOrArray) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainDelete(SecKeychainRef __nullable keychainOrArray) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainSetSettings @@ -314,7 +314,7 @@ OSStatus SecKeychainDelete(SecKeychainRef __nullable keychainOrArray) API_UNAVAI @param newSettings A pointer to the new keychain settings. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainSetSettings(SecKeychainRef __nullable keychain, const SecKeychainSettings *newSettings) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainSetSettings(SecKeychainRef __nullable keychain, const SecKeychainSettings *newSettings) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainCopySettings @@ -323,7 +323,7 @@ OSStatus SecKeychainSetSettings(SecKeychainRef __nullable keychain, const SecKey @param outSettings A pointer to a keychain settings structure. Since this structure is versioned, you must preallocate it and fill in the version of the structure. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainCopySettings(SecKeychainRef __nullable keychain, SecKeychainSettings *outSettings) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainCopySettings(SecKeychainRef __nullable keychain, SecKeychainSettings *outSettings) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainUnlock @@ -335,7 +335,7 @@ OSStatus SecKeychainCopySettings(SecKeychainRef __nullable keychain, SecKeychain @result A result code. See "Security Error Codes" (SecBase.h). @discussion In most cases, your application does not need to call the SecKeychainUnlock function directly, since most Keychain Manager functions that require an unlocked keychain call SecKeychainUnlock automatically. If your application needs to verify that a keychain is unlocked, call the function SecKeychainGetStatus. */ -OSStatus SecKeychainUnlock(SecKeychainRef __nullable keychain, UInt32 passwordLength, const void * __nullable password, Boolean usePassword) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainUnlock(SecKeychainRef __nullable keychain, UInt32 passwordLength, const void * __nullable password, Boolean usePassword) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainLock @@ -343,14 +343,14 @@ OSStatus SecKeychainUnlock(SecKeychainRef __nullable keychain, UInt32 passwordLe @param keychain A reference to the keychain to lock. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainLock(SecKeychainRef __nullable keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainLock(SecKeychainRef __nullable keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainLockAll @abstract Locks all keychains belonging to the current user. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainLockAll(void) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainLockAll(void) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainCopyDefault @@ -358,7 +358,7 @@ OSStatus SecKeychainLockAll(void) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, @param keychain On return, a pointer to the default keychain reference. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainCopyDefault(SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainCopyDefault(SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainSetDefault @@ -366,7 +366,7 @@ OSStatus SecKeychainCopyDefault(SecKeychainRef * __nonnull CF_RETURNS_RETAINED k @param keychain A reference to the keychain to set as default. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if the keychain parameter is invalid (NULL). */ -OSStatus SecKeychainSetDefault(SecKeychainRef __nullable keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainSetDefault(SecKeychainRef __nullable keychain) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainCopySearchList @@ -374,7 +374,7 @@ OSStatus SecKeychainSetDefault(SecKeychainRef __nullable keychain) API_UNAVAILAB @param searchList The returned list of keychains to search. When finished with the array, you must call CFRelease() to release the memory. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if the keychain list is not specified (NULL). */ -OSStatus SecKeychainCopySearchList(CFArrayRef * __nonnull CF_RETURNS_RETAINED searchList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainCopySearchList(CFArrayRef * __nonnull CF_RETURNS_RETAINED searchList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainSetSearchList @@ -382,7 +382,7 @@ OSStatus SecKeychainCopySearchList(CFArrayRef * __nonnull CF_RETURNS_RETAINED se @param searchList The list of keychains to use in a search list when the SecKeychainCopySearchList function is called. An empty array clears the search list. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if the keychain list is not specified (NULL). */ -OSStatus SecKeychainSetSearchList(CFArrayRef searchList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainSetSearchList(CFArrayRef searchList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* @@ -411,7 +411,7 @@ OSStatus SecKeychainGetPreferenceDomain(SecPreferencesDomain *domain); @param keychainStatus On return, a pointer to the status of the specified keychain. See KeychainStatus for valid status constants. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainGetStatus(SecKeychainRef __nullable keychain, SecKeychainStatus *keychainStatus) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainGetStatus(SecKeychainRef __nullable keychain, SecKeychainStatus *keychainStatus) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainGetPath @@ -421,7 +421,7 @@ OSStatus SecKeychainGetStatus(SecKeychainRef __nullable keychain, SecKeychainSta @param pathName On return, the POSIX path to the keychain. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainGetPath(SecKeychainRef __nullable keychain, UInt32 *ioPathLength, char *pathName) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainGetPath(SecKeychainRef __nullable keychain, UInt32 *ioPathLength, char *pathName) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- Keychain Item Attribute Information ---- /*! @@ -433,7 +433,7 @@ OSStatus SecKeychainGetPath(SecKeychainRef __nullable keychain, UInt32 *ioPathLe @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters were supplied (NULL). @discussion Warning, this call returns more attributes than are support by the old style Keychain API and passing them into older calls will yield an invalid attribute error. The recommended call to retrieve the attribute values is the SecKeychainItemCopyAttributesAndData function. */ -OSStatus SecKeychainAttributeInfoForItemID(SecKeychainRef __nullable keychain, UInt32 itemID, SecKeychainAttributeInfo * __nullable * __nonnull info) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainAttributeInfoForItemID(SecKeychainRef __nullable keychain, UInt32 itemID, SecKeychainAttributeInfo * __nullable * __nonnull info) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainFreeAttributeInfo @@ -441,7 +441,7 @@ OSStatus SecKeychainAttributeInfoForItemID(SecKeychainRef __nullable keychain, @param info A pointer to the keychain attribute information to release. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters were supplied (NULL). */ -OSStatus SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- Keychain Manager Callbacks ---- @@ -460,7 +460,7 @@ OSStatus SecKeychainFreeAttributeInfo(SecKeychainAttributeInfo *info) API_UNAVAI To add your callback function, use the SecKeychainAddCallback function. To remove your callback function, use the SecKeychainRemoveCallback function. */ -typedef OSStatus (*SecKeychainCallback)(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, void * __nullable context) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef OSStatus (*SecKeychainCallback)(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, void * __nullable context) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainAddCallback @@ -470,7 +470,7 @@ typedef OSStatus (*SecKeychainCallback)(SecKeychainEvent keychainEvent, SecKeych @param userContext A pointer to application-defined storage that will be passed to your callback function. Your application can use this to associate any particular call of SecKeychainAddCallback with any particular call of your keychain event callback function. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void * __nullable userContext) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychainEventMask eventMask, void * __nullable userContext) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainRemoveCallback @@ -478,7 +478,7 @@ OSStatus SecKeychainAddCallback(SecKeychainCallback callbackFunction, SecKeychai @param callbackFunction The callback function pointer to remove @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainRemoveCallback(SecKeychainCallback callbackFunction) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainRemoveCallback(SecKeychainCallback callbackFunction) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- High Level Keychain Manager Calls ---- /*! @@ -502,7 +502,7 @@ OSStatus SecKeychainRemoveCallback(SecKeychainCallback callbackFunction) API_UNA @result A result code. See "Security Error Codes" (SecBase.h). @discussion The SecKeychainAddInternetPassword function adds a new Internet server password to the specified keychain. Required parameters to identify the password are serverName and accountName (you cannot pass NULL for both parameters). In addition, some protocols may require an optional securityDomain when authentication is requested. SecKeychainAddInternetPassword optionally returns a reference to the newly added item. */ -OSStatus SecKeychainAddInternetPassword(SecKeychainRef __nullable keychain, UInt32 serverNameLength, const char * __nullable serverName, UInt32 securityDomainLength, const char * __nullable securityDomain, UInt32 accountNameLength, const char * __nullable accountName, UInt32 pathLength, const char * __nullable path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainAddInternetPassword(SecKeychainRef __nullable keychain, UInt32 serverNameLength, const char * __nullable serverName, UInt32 securityDomainLength, const char * __nullable securityDomain, UInt32 accountNameLength, const char * __nullable accountName, UInt32 pathLength, const char * __nullable path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainFindInternetPassword @@ -525,7 +525,7 @@ OSStatus SecKeychainAddInternetPassword(SecKeychainRef __nullable keychain, UInt @result A result code. See "Security Error Codes" (SecBase.h). @discussion The SecKeychainFindInternetPassword function finds the first Internet password item which matches the attributes you provide. Most attributes are optional; you should pass only as many as you need to narrow the search sufficiently for your application's intended use. SecKeychainFindInternetPassword optionally returns a reference to the found item. */ -OSStatus SecKeychainFindInternetPassword(CFTypeRef __nullable keychainOrArray, UInt32 serverNameLength, const char * __nullable serverName, UInt32 securityDomainLength, const char * __nullable securityDomain, UInt32 accountNameLength, const char * __nullable accountName, UInt32 pathLength, const char * __nullable path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 * __nullable passwordLength, void * __nullable * __nullable passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainFindInternetPassword(CFTypeRef __nullable keychainOrArray, UInt32 serverNameLength, const char * __nullable serverName, UInt32 securityDomainLength, const char * __nullable securityDomain, UInt32 accountNameLength, const char * __nullable accountName, UInt32 pathLength, const char * __nullable path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType, UInt32 * __nullable passwordLength, void * __nullable * __nullable passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainAddGenericPassword @@ -541,7 +541,7 @@ OSStatus SecKeychainFindInternetPassword(CFTypeRef __nullable keychainOrArray, U @result A result code. See "Security Error Codes" (SecBase.h). @discussion The SecKeychainAddGenericPassword function adds a new generic password to the default keychain. Required parameters to identify the password are serviceName and accountName, which are application-defined strings. SecKeychainAddGenericPassword optionally returns a reference to the newly added item. */ -OSStatus SecKeychainAddGenericPassword(SecKeychainRef __nullable keychain, UInt32 serviceNameLength, const char * __nullable serviceName, UInt32 accountNameLength, const char * __nullable accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainAddGenericPassword(SecKeychainRef __nullable keychain, UInt32 serviceNameLength, const char * __nullable serviceName, UInt32 accountNameLength, const char * __nullable accountName, UInt32 passwordLength, const void *passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainFindGenericPassword @@ -557,7 +557,7 @@ OSStatus SecKeychainAddGenericPassword(SecKeychainRef __nullable keychain, UInt3 @result A result code. See "Security Error Codes" (SecBase.h). @discussion The SecKeychainFindGenericPassword function finds the first generic password item which matches the attributes you provide. Most attributes are optional; you should pass only as many as you need to narrow the search sufficiently for your application's intended use. SecKeychainFindGenericPassword optionally returns a reference to the found item. */ -OSStatus SecKeychainFindGenericPassword(CFTypeRef __nullable keychainOrArray, UInt32 serviceNameLength, const char * __nullable serviceName, UInt32 accountNameLength, const char * __nullable accountName, UInt32 * __nullable passwordLength, void * __nullable * __nullable passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainFindGenericPassword(CFTypeRef __nullable keychainOrArray, UInt32 serviceNameLength, const char * __nullable serviceName, UInt32 accountNameLength, const char * __nullable accountName, UInt32 * __nullable passwordLength, void * __nullable * __nullable passwordData, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- Managing User Interaction ---- /*! @@ -566,7 +566,7 @@ OSStatus SecKeychainFindGenericPassword(CFTypeRef __nullable keychainOrArray, U @param state A boolean representing the state of user interaction. You should pass TRUE to allow user interaction, and FALSE to disallow user interaction @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainSetUserInteractionAllowed(Boolean state) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainSetUserInteractionAllowed(Boolean state) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainGetUserInteractionAllowed @@ -574,7 +574,7 @@ OSStatus SecKeychainSetUserInteractionAllowed(Boolean state) API_UNAVAILABLE(ios @param state On return, a pointer to the current state of user interaction. If this is TRUE then user interaction is allowed, if it is FALSE, then user interaction is not allowed. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainGetUserInteractionAllowed(Boolean *state) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainGetUserInteractionAllowed(Boolean *state) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- CSSM Bridge Functions ---- /*! diff --git a/OSX/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp b/OSX/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp deleted file mode 100644 index db82b83a..00000000 --- a/OSX/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2003-2013 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@ - * - * SecKeychainAddIToolsPassword.c - * - * Based on Keychain item access control example - * -- added "always allow" ACL support - */ - -#include -#include -#include -#include -#include -#include -#include - - -OSStatus SecKeychainAddIToolsPassword(SecKeychainRef __unused keychain, - UInt32 __unused accountNameLength, - const char * __unused accountName, - UInt32 __unused passwordLength, - const void * __unused passwordData, - SecKeychainItemRef * __unused itemRef) -{ - return errSecParam; -} diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp b/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp index 6b31ddea..b5bd9748 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp @@ -44,6 +44,7 @@ #include "KCExceptions.h" #include "Access.h" #include "SecKeychainItemExtendedAttributes.h" +#include "LegacyAPICounts.h" extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref); @@ -79,7 +80,6 @@ CFTypeID SecKeychainItemGetTypeID(void) { BEGIN_SECAPI - return gTypes().ItemImpl.typeID; END_SECAPI1(_kCFRuntimeNotATypeID) @@ -127,7 +127,7 @@ SecKeychainItemCreateFromContent(SecItemClass itemClass, SecKeychainAttributeLis OSStatus SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeychainAttributeList *attrList, UInt32 length, const void *data) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI os_activity_t activity = os_activity_create("SecKeychainItemModifyContent", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -171,7 +171,7 @@ SecKeychainItemFreeContent(SecKeychainAttributeList *attrList, void *data) OSStatus SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, const SecKeychainAttributeList *attrList, UInt32 length, const void *data) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI os_activity_t activity = os_activity_create("SecKeychainItemModifyAttributesAndData", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -186,7 +186,7 @@ SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, const SecKeyc OSStatus SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo *info, SecItemClass *itemClass, SecKeychainAttributeList **attrList, UInt32 *length, void **outData) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI Item item = ItemImpl::required(__itemImplRef); item->getAttributesAndData(info, itemClass, attrList, length, outData); @@ -199,7 +199,6 @@ OSStatus SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList *attrList, void *data) { BEGIN_SECAPI - ItemImpl::freeAttributesAndData(attrList, data); END_SECAPI @@ -209,7 +208,7 @@ SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList *attrList, void *d OSStatus SecKeychainItemDelete(SecKeychainItemRef itemRef) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI os_activity_t activity = os_activity_create("SecKeychainItemDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -244,7 +243,7 @@ SecKeychainItemDelete(SecKeychainItemRef itemRef) OSStatus SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef* keychainRef) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI // make sure this item has a keychain Keychain kc = ItemImpl::required(__itemImplRef)->keychain(); @@ -263,7 +262,7 @@ OSStatus SecKeychainItemCreateCopy(SecKeychainItemRef itemRef, SecKeychainRef destKeychainRef, SecAccessRef initialAccess, SecKeychainItemRef *itemCopy) { - BEGIN_SECKCITEMAPI + BEGIN_SECKCITEMAPI os_activity_t activity = os_activity_create("SecKeychainItemCreateCopy", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); os_activity_scope(activity); os_release(activity); @@ -304,34 +303,6 @@ SecKeychainItemGetDLDBHandle(SecKeychainItemRef itemRef, CSSM_DL_DB_HANDLE* dldb END_SECKCITEMAPI } -#if 0 -static -OSStatus SecAccessCreateFromObject(CFTypeRef sourceRef, - SecAccessRef *accessRef) -{ - BEGIN_SECAPI - - Required(accessRef); // preflight - SecPointer access = new Access(*aclBearer(sourceRef)); - *accessRef = access->handle(); - - END_SECAPI -} - - -/*! - */ -static -OSStatus SecAccessModifyObject(SecAccessRef accessRef, CFTypeRef sourceRef) -{ - BEGIN_SECAPI - - Access::required(accessRef)->setAccess(*aclBearer(sourceRef), true); - - END_SECAPI -} -#endif - OSStatus SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef* accessRef) { @@ -567,6 +538,7 @@ OSStatus SecKeychainItemFindFirst(SecKeychainRef keychainRef, const SecKeychainA static OSStatus SecKeychainItemCreatePersistentReferenceFromCertificate(SecCertificateRef certRef, CFDataRef *persistentItemRef, Boolean isIdentity) { + COUNTLEGACYAPI OSStatus __secapiresult; if (!certRef || !persistentItemRef) { return errSecParam; diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItem.h b/OSX/libsecurity_keychain/lib/SecKeychainItem.h index 764cea36..ec6f0057 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItem.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainItem.h @@ -160,7 +160,7 @@ CFTypeID SecKeychainItemGetTypeID(void); @result A result code. See "Security Error Codes" (SecBase.h). @discussion The keychain item is written to the keychain's permanent data store. If the keychain item has not previously been added to a keychain, a call to the SecKeychainItemModifyContent function does nothing and returns errSecSuccess. */ -OSStatus SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, const SecKeychainAttributeList * __nullable attrList, UInt32 length, const void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, const SecKeychainAttributeList * __nullable attrList, UInt32 length, const void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCreateFromContent @@ -176,7 +176,7 @@ OSStatus SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, cons */ OSStatus SecKeychainItemCreateFromContent(SecItemClass itemClass, SecKeychainAttributeList *attrList, UInt32 length, const void * __nullable data, SecKeychainRef __nullable keychainRef, - SecAccessRef __nullable initialAccess, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecAccessRef __nullable initialAccess, SecKeychainItemRef * __nullable CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemModifyContent @@ -187,7 +187,7 @@ OSStatus SecKeychainItemCreateFromContent(SecItemClass itemClass, SecKeychainAtt @param data A pointer to a buffer containing the data to store. Pass NULL if you don't need to modify the data. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeychainAttributeList * __nullable attrList, UInt32 length, const void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeychainAttributeList * __nullable attrList, UInt32 length, const void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyContent @@ -199,7 +199,7 @@ OSStatus SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeych @param outData On return, a pointer to a buffer containing the data in this item. Pass NULL if you don't need to retrieve the data. You must call SecKeychainItemFreeContent when you no longer need the data. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters are supplied. */ -OSStatus SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass * __nullable itemClass, SecKeychainAttributeList * __nullable attrList, UInt32 * __nullable length, void * __nullable * __nullable outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass * __nullable itemClass, SecKeychainAttributeList * __nullable attrList, UInt32 * __nullable length, void * __nullable * __nullable outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemFreeContent @@ -207,7 +207,7 @@ OSStatus SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass * _ @param attrList A pointer to the attribute list to release. Pass NULL to ignore this parameter. @param data A pointer to the data buffer to release. Pass NULL to ignore this parameter. */ -OSStatus SecKeychainItemFreeContent(SecKeychainAttributeList * __nullable attrList, void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemFreeContent(SecKeychainAttributeList * __nullable attrList, void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyAttributesAndData @@ -220,7 +220,7 @@ OSStatus SecKeychainItemFreeContent(SecKeychainAttributeList * __nullable attrLi @param outData On return, a pointer to a buffer containing the data in this item. Pass NULL if you don't need to retrieve the data. You must call SecKeychainItemFreeAttributesAndData when you no longer need the data. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters are supplied. */ -OSStatus SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo * __nullable info, SecItemClass * __nullable itemClass, SecKeychainAttributeList * __nullable * __nullable attrList, UInt32 * __nullable length, void * __nullable * __nullable outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo * __nullable info, SecItemClass * __nullable itemClass, SecKeychainAttributeList * __nullable * __nullable attrList, UInt32 * __nullable length, void * __nullable * __nullable outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemFreeAttributesAndData @@ -229,7 +229,7 @@ OSStatus SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef, SecKey @param data A pointer to the data buffer to release. Pass NULL to ignore this parameter. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList * __nullable attrList, void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList * __nullable attrList, void * __nullable data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemDelete @@ -238,7 +238,7 @@ OSStatus SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList * __nulla @result A result code. See "Security Error Codes" (SecBase.h). @discussion If itemRef has not previously been added to the keychain, SecKeychainItemDelete does nothing and returns errSecSuccess. IMPORTANT: SecKeychainItemDelete does not dispose the memory occupied by the item reference itself; use the CFRelease function when you are completely finished with an item. */ -OSStatus SecKeychainItemDelete(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemDelete(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyKeychain @@ -247,7 +247,7 @@ OSStatus SecKeychainItemDelete(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, @param keychainRef On return, the keychain reference for the specified item. Release this reference by calling the CFRelease function. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychainRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychainRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCreateCopy @@ -259,7 +259,7 @@ OSStatus SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef @result A result code. See "Security Error Codes" (SecBase.h). */ OSStatus SecKeychainItemCreateCopy(SecKeychainItemRef itemRef, SecKeychainRef __nullable destKeychainRef, - SecAccessRef __nullable initialAccess, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemCopy) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecAccessRef __nullable initialAccess, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemCopy) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCreatePersistentReference @@ -268,7 +268,7 @@ OSStatus SecKeychainItemCreateCopy(SecKeychainItemRef itemRef, SecKeychainRef __ @param persistentItemRef On return, a CFDataRef containing a persistent reference. You must release this data reference by calling the CFRelease function. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef, CFDataRef * __nonnull CF_RETURNS_RETAINED persistentItemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef, CFDataRef * __nonnull CF_RETURNS_RETAINED persistentItemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @@ -278,7 +278,7 @@ OSStatus SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef, CF @param itemRef On return, a SecKeychainItemRef for the keychain item described by the persistent reference. You must release this item reference by calling the CFRelease function. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemCopyFromPersistentReference(CFDataRef persistentItemRef, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyFromPersistentReference(CFDataRef persistentItemRef, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #pragma mark ---- CSSM Bridge Functions ---- @@ -312,7 +312,7 @@ OSStatus SecKeychainItemGetUniqueRecordID(SecKeychainItemRef itemRef, const CSSM @param access On return, a reference to the keychain item's access. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef * __nonnull CF_RETURNS_RETAINED access) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef * __nonnull CF_RETURNS_RETAINED access) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemSetAccess @@ -321,7 +321,7 @@ OSStatus SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef * __ @param access A reference to an access to replace the keychain item's current access. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemSetAccess(SecKeychainItemRef itemRef, SecAccessRef access) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemSetAccess(SecKeychainItemRef itemRef, SecAccessRef access) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp b/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp index 60c98f31..3ae8d1bf 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp @@ -30,19 +30,7 @@ #include "KCCursor.h" #include -/* I'm not sure we need this */ -#if 0 -CFTypeID SecKeychainItemExtendedAttributesGetTypeID(void); - -static CFTypeID SecKeychainItemExtendedAttributesGetTypeID(void) -{ - BEGIN_SECAPI - - return gTypes().ExtendedAttribute.typeID; - - END_SECAPI1(_kCFRuntimeNotATypeID) -} -#endif +#include "LegacyAPICounts.h" extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref); diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h b/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h index 1bd1caea..9e925f2d 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h @@ -77,7 +77,7 @@ OSStatus SecKeychainItemSetExtendedAttribute( CFStringRef attrName, /* identifies the attribute */ CFDataRef attrValue) /* value to set; NULL means delete the * attribute */ - API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * SecKeychainItemCopyExtendedAttribute() - Obtain the value of an an extended attribute. @@ -91,7 +91,7 @@ OSStatus SecKeychainItemSetExtendedAttribute( OSStatus SecKeychainItemCopyExtendedAttribute( SecKeychainItemRef itemRef, CFStringRef attrName, - CFDataRef *attrValue) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); /* RETURNED */ + CFDataRef *attrValue) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* RETURNED */ /* * SecKeychainItemCopyAllExtendedAttributes() - obtain all of an item's extended attributes. @@ -119,7 +119,7 @@ OSStatus SecKeychainItemCopyAllExtendedAttributes( CFArrayRef *attrNames, /* RETURNED, each element is a CFStringRef */ CFArrayRef *attrValues) /* optional, RETURNED, each element is a * CFDataRef */ - API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h b/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h index 96e89d0e..d9b13b26 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h @@ -72,23 +72,23 @@ enum { /* also kSecModDateItemAttr from SecKeychainItem.h */ }; -OSStatus SecKeychainItemCreateNew(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, SecKeychainItemRef* itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCreateNew(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, SecKeychainItemRef* itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemGetData(SecKeychainItemRef itemRef, UInt32 maxLength, void* data, UInt32* actualLength) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemGetData(SecKeychainItemRef itemRef, UInt32 maxLength, void* data, UInt32* actualLength) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemGetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute, UInt32* actualLength) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemGetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute, UInt32* actualLength) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemSetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemSetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemAdd(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemAdd(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemAddNoUI(SecKeychainRef keychainRef, SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemAddNoUI(SecKeychainRef keychainRef, SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemUpdate(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemUpdate(SecKeychainItemRef itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemSetData(SecKeychainItemRef itemRef, UInt32 length, const void* data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemSetData(SecKeychainItemRef itemRef, UInt32 length, const void* data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -OSStatus SecKeychainItemFindFirst(SecKeychainRef keychainRef, const SecKeychainAttributeList *attrList, SecKeychainSearchRef *searchRef, SecKeychainItemRef *itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemFindFirst(SecKeychainRef keychainRef, const SecKeychainAttributeList *attrList, SecKeychainSearchRef *searchRef, SecKeychainItemRef *itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyRecordIdentifier @@ -98,7 +98,7 @@ OSStatus SecKeychainItemFindFirst(SecKeychainRef keychainRef, const SecKeychainA @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecKeychainItemCopyRecordIdentifier(SecKeychainItemRef itemRef, CFDataRef *recordIdentifier) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemCopyRecordIdentifier(SecKeychainItemRef itemRef, CFDataRef *recordIdentifier) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyFromRecordIdentifier @@ -111,7 +111,7 @@ OSStatus SecKeychainItemCopyRecordIdentifier(SecKeychainItemRef itemRef, CFDataR OSStatus SecKeychainItemCopyFromRecordIdentifier(SecKeychainRef keychain, SecKeychainItemRef *itemRef, - CFDataRef recordIdentifier) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + CFDataRef recordIdentifier) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCopyAttributesAndEncryptedData @@ -128,7 +128,7 @@ OSStatus SecKeychainItemCopyFromRecordIdentifier(SecKeychainRef keychain, */ OSStatus SecKeychainItemCopyAttributesAndEncryptedData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo *info, SecItemClass *itemClass, SecKeychainAttributeList **attrList, - UInt32 *length, void **outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + UInt32 *length, void **outData) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemModifyEncryptedData @@ -140,7 +140,7 @@ OSStatus SecKeychainItemCopyAttributesAndEncryptedData(SecKeychainItemRef itemRe @result A result code. See "Security Error Codes" (SecBase.h). @discussion The keychain item is written to the keychain's permanent data store. If the keychain item has not previously been added to a keychain, a call to the SecKeychainItemModifyContent function does nothing and returns errSecSuccess. */ -OSStatus SecKeychainItemModifyEncryptedData(SecKeychainItemRef itemRef, UInt32 length, const void *data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecKeychainItemModifyEncryptedData(SecKeychainItemRef itemRef, UInt32 length, const void *data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemCreateFromEncryptedContent @@ -156,7 +156,7 @@ OSStatus SecKeychainItemModifyEncryptedData(SecKeychainItemRef itemRef, UInt32 l */ OSStatus SecKeychainItemCreateFromEncryptedContent(SecItemClass itemClass, UInt32 length, const void *data, SecKeychainRef keychainRef, SecAccessRef initialAccess, - SecKeychainItemRef *itemRef, CFDataRef *itemLocalID) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecKeychainItemRef *itemRef, CFDataRef *itemLocalID) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainItemSetAccessWithPassword @@ -167,7 +167,7 @@ OSStatus SecKeychainItemCreateFromEncryptedContent(SecItemClass itemClass, UInt3 @param password A buffer containing the password for the keychain. if this password is incorrect, this call might fail---it will not prompt the user. @result A result code. See "Security Error Codes" (SecBase.h). */ - OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAccessRef accessRef, UInt32 passwordLength, const void * password) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAccessRef accessRef, UInt32 passwordLength, const void * password) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_keychain/lib/SecKeychainPriv.h b/OSX/libsecurity_keychain/lib/SecKeychainPriv.h index 2b035d94..7caaad33 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainPriv.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainPriv.h @@ -48,8 +48,6 @@ OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); OSStatus SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword) __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_NA); -OSStatus SecKeychainOpenWithGuid(const CSSM_GUID *guid, uint32 subserviceId, uint32 subserviceType, const char* dbName, const CSSM_NET_ADDRESS *dbLocation, SecKeychainRef *keychain) - API_DEPRECATED("CSSM_GUID/CSSM_NET_ADDRESS is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); @@ -98,11 +96,11 @@ OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, S /* Keychain list manipulation */ OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType) - API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType) - API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType) - API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("CSSM_GUID is deprecated", macos(10.4,10.14)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* server operation (keychain inhibit) */ void SecKeychainSetServerMode(void) diff --git a/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp b/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp index 5e94b58c..a84f0e3e 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp @@ -32,12 +32,12 @@ #include #include "SecBridge.h" +#include "LegacyAPICounts.h" CFTypeID SecKeychainSearchGetTypeID(void) { BEGIN_SECAPI - return gTypes().KCCursorImpl.typeID; END_SECAPI1(_kCFRuntimeNotATypeID) diff --git a/OSX/libsecurity_keychain/lib/SecKeychainSearch.h b/OSX/libsecurity_keychain/lib/SecKeychainSearch.h index fed709fa..3a85f485 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainSearch.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainSearch.h @@ -45,7 +45,7 @@ CF_ASSUME_NONNULL_BEGIN @discussion This API is deprecated in 10.7. The SecKeychainSearchRef type is no longer used. */ CFTypeID SecKeychainSearchGetTypeID(void) - API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainSearchCreateFromAttributes @@ -58,7 +58,7 @@ CFTypeID SecKeychainSearchGetTypeID(void) @discussion This function is deprecated in Mac OS X 10.7 and later; to find keychain items which match specified attributes, please use the SecItemCopyMatching API (see SecItem.h). */ OSStatus SecKeychainSearchCreateFromAttributes(CFTypeRef __nullable keychainOrArray, SecItemClass itemClass, const SecKeychainAttributeList * __nullable attrList, SecKeychainSearchRef * __nonnull CF_RETURNS_RETAINED searchRef) - API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeychainSearchCopyNext @@ -69,7 +69,7 @@ OSStatus SecKeychainSearchCreateFromAttributes(CFTypeRef __nullable keychainOrAr @discussion This function is deprecated in Mac OS X 10.7 and later; to find keychain items which match specified attributes, please use the SecItemCopyMatching API (see SecItem.h). */ OSStatus SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemRef) - API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED("SecKeychainSearch is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_keychain/lib/SecPassword.cpp b/OSX/libsecurity_keychain/lib/SecPassword.cpp index 6ac71ed4..f56197ae 100644 --- a/OSX/libsecurity_keychain/lib/SecPassword.cpp +++ b/OSX/libsecurity_keychain/lib/SecPassword.cpp @@ -32,17 +32,7 @@ #include -#if 0 -static CFTypeID -SecPasswordGetTypeID(void) -{ - BEGIN_SECAPI - - return gTypes().PasswordImpl.typeID; - - END_SECAPI1(_kCFRuntimeNotATypeID) -} -#endif +#include "LegacyAPICounts.h" OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList, SecPasswordRef *itemRef) @@ -254,7 +244,7 @@ SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt3 } - // If we're still here the use gave us his password, store it if keychain is in use + // If we're still here the user gave us their password, store it if keychain is in use if (passwordRef->useKeychain()) { if (passwordRef->rememberInKeychain()) { diff --git a/OSX/libsecurity_keychain/lib/SecPassword.h b/OSX/libsecurity_keychain/lib/SecPassword.h index 9be0a79d..7ffaaa69 100644 --- a/OSX/libsecurity_keychain/lib/SecPassword.h +++ b/OSX/libsecurity_keychain/lib/SecPassword.h @@ -65,7 +65,7 @@ enum { @param itemAttrList (in/opt) A list of attributes which will be used for item creation. @param itemRef (out) On return, a pointer to a password reference. Release this by calling the CFRelease function. */ -OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList, SecPasswordRef *itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList, SecPasswordRef *itemRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecPasswordAction @@ -80,13 +80,13 @@ OSStatus SecGenericPasswordCreate(SecKeychainAttributeList *searchAttrList, SecK @param data A pointer to a buffer containing the data to store. */ -OSStatus SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt32 *length, const void **data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt32 *length, const void **data) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecPasswordSetInitialAccess @abstract Set the initial access ref. Only used when a password is first added to the keychain. */ -OSStatus SecPasswordSetInitialAccess(SecPasswordRef itemRef, SecAccessRef accessRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +OSStatus SecPasswordSetInitialAccess(SecPasswordRef itemRef, SecAccessRef accessRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if defined(__cplusplus) } diff --git a/OSX/libsecurity_keychain/lib/SecPolicy.cpp b/OSX/libsecurity_keychain/lib/SecPolicy.cpp index 56aeaefd..7f20d626 100644 --- a/OSX/libsecurity_keychain/lib/SecPolicy.cpp +++ b/OSX/libsecurity_keychain/lib/SecPolicy.cpp @@ -435,54 +435,6 @@ SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE* tpHandle) return errSecServiceNotAvailable; } -/* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */ -OSStatus -SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef* policies) -{ - /* bridge to support old functionality */ -#if SECTRUST_DEPRECATION_WARNINGS - syslog(LOG_ERR, "WARNING: SecPolicyCopyAll was deprecated in 10.7. Please use SecPolicy creation functions instead."); -#endif - if (!policies) { - return errSecParam; - } - CFMutableArrayRef curPolicies = CFArrayCreateMutable(NULL, 0, NULL); - if (!curPolicies) { - return errSecAllocate; - } - /* build the subset of policies which were supported on OS X, - and which are also implemented on iOS */ - CFStringRef supportedPolicies[] = { - kSecPolicyAppleX509Basic, /* CSSMOID_APPLE_X509_BASIC */ - kSecPolicyAppleSSL, /* CSSMOID_APPLE_TP_SSL */ - kSecPolicyAppleSMIME, /* CSSMOID_APPLE_TP_SMIME */ - kSecPolicyAppleEAP, /*CSSMOID_APPLE_TP_EAP */ - kSecPolicyAppleSWUpdateSigning, /* CSSMOID_APPLE_TP_SW_UPDATE_SIGNING */ - kSecPolicyAppleIPsec, /* CSSMOID_APPLE_TP_IP_SEC */ - kSecPolicyAppleCodeSigning, /* CSSMOID_APPLE_TP_CODE_SIGNING */ - kSecPolicyMacAppStoreReceipt, /* CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT */ - kSecPolicyAppleIDValidation, /* CSSMOID_APPLE_TP_APPLEID_SHARING */ - kSecPolicyAppleTimeStamping, /* CSSMOID_APPLE_TP_TIMESTAMPING */ - kSecPolicyAppleRevocation, /* CSSMOID_APPLE_TP_REVOCATION_{CRL,OCSP} */ - NULL - }; - CFIndex ix = 0; - while (true) { - CFStringRef policyID = supportedPolicies[ix++]; - if (!policyID) { - break; - } - SecPolicyRef curPolicy = SecPolicyCreateWithProperties(policyID, NULL); - if (curPolicy) { - CFArrayAppendValue(curPolicies, curPolicy); - CFRelease(curPolicy); - } - } - *policies = CFArrayCreateCopy(NULL, curPolicies); - CFRelease(curPolicies); - return errSecSuccess; -} - /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA) */ OSStatus SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef* policy) diff --git a/OSX/libsecurity_keychain/lib/SecPolicySearch.cpp b/OSX/libsecurity_keychain/lib/SecPolicySearch.cpp index 6bde1086..9bb6dfd1 100644 --- a/OSX/libsecurity_keychain/lib/SecPolicySearch.cpp +++ b/OSX/libsecurity_keychain/lib/SecPolicySearch.cpp @@ -33,7 +33,6 @@ CFTypeID SecPolicySearchGetTypeID(void) { BEGIN_SECAPI - return gTypes().PolicyCursor.typeID; END_SECAPI1(_kCFRuntimeNotATypeID) @@ -67,7 +66,6 @@ SecPolicySearchCopyNext( SecPolicyRef* policyRef) { BEGIN_SECAPI - RequiredParam(policyRef); SecPointer policy; diff --git a/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp b/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp index 3d64c65d..9e17b255 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp +++ b/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp @@ -43,10 +43,11 @@ void SecTrustLegacySourcesListenForKeychainEvents(void) { notify_register_dispatch(kSecServerCertificateTrustNotification, &out_token, dispatch_get_main_queue(), ^(int token __unused) { - // Purge keychain parent cache - SecItemParentCachePurge(); - // Purge unrestricted roots cache - SecTrustSettingsPurgeUserAdminCertsCache(); - - }); + // Purge keychain parent cache + SecItemParentCachePurge(); + // Purge tust settings cert cache + SecTrustSettingsPurgeUserAdminCertsCache(); + // Purge the trust settings cache + SecTrustSettingsPurgeCache(); + }); } diff --git a/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp b/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp index f4ecc54e..c2a7e133 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp +++ b/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include #include @@ -108,7 +108,7 @@ static bool tsUserTrustSettingsDisabled() Dictionary* dictionary = Dictionary::CreateDictionary(kSecTrustSettingsPrefsDomain, Dictionary::US_System); if (dictionary) { - auto_ptr prefsDict(dictionary); + unique_ptr prefsDict(dictionary); /* this returns false if the pref isn't there, just like we want */ tsUserTrustDisable = prefsDict->getBoolValue(kSecTrustSettingsDisableUserTrustSettings); } @@ -348,7 +348,7 @@ static OSStatus tsCopyTrustSettings( return result; } - auto_ptr_(ts); // make sure this gets deleted just in case something throws underneath + unique_ptr_(ts); // make sure this gets deleted just in case something throws underneath if(trustSettings) { *trustSettings = ts->copyTrustSettings(cert); @@ -360,6 +360,59 @@ static OSStatus tsCopyTrustSettings( END_RCSAPI } +/* + * Common code for SecTrustSettingsCopyTrustSettings(), + * SecTrustSettingsCopyModificationDate(). + */ +static OSStatus tsCopyTrustSettings_cached( + SecCertificateRef cert, + SecTrustSettingsDomain domain, + CFArrayRef CF_RETURNS_RETAINED *trustSettings) +{ + BEGIN_RCSAPI + + TS_REQUIRED(cert) + + StLock _(sutCacheLock()); + TrustSettings* ts = tsGetGlobalTrustSettings(domain); + + // rather than throw these results, just return them because we are at the top level + if (ts == NULL) { + return errSecItemNotFound; + } + + if(trustSettings) { + *trustSettings = ts->copyTrustSettings(cert); + } + + END_RCSAPI +} + +static OSStatus tsContains( + SecCertificateRef cert, + SecTrustSettingsDomain domain) +{ + BEGIN_RCSAPI + + TS_REQUIRED(cert) + + StLock _(sutCacheLock()); + TrustSettings* ts = tsGetGlobalTrustSettings(domain); + + // rather than throw these results, just return them because we are at the top level + if (ts == NULL) { + return errSecItemNotFound; + } + + if (ts->contains(cert)) { + return errSecSuccess; + } else { + return errSecItemNotFound; + } + + END_RCSAPI +} + static void tsAddConditionalCerts(CFMutableArrayRef certArray); /* @@ -727,7 +780,7 @@ OSStatus SecTrustSettingsSetTrustSettingsExternal( return result; } - auto_ptr_(ts); + unique_ptr_(ts); if(certRef != NULL) { ts->setTrustSettings(certRef, trustSettingsDictOrArray); @@ -738,6 +791,25 @@ OSStatus SecTrustSettingsSetTrustSettingsExternal( END_RCSAPI } +void SecTrustSettingsPurgeCache(void) { + tsPurgeCache(); +} + +OSStatus SecTrustSettingsCopyTrustSettings_Cached( + SecCertificateRef certRef, + SecTrustSettingsDomain domain, + CFArrayRef CF_RETURNS_RETAINED *trustSettings) /* RETURNED */ +{ + TS_REQUIRED(certRef) + TS_REQUIRED(trustSettings) + + OSStatus result = tsCopyTrustSettings_cached(certRef, domain, trustSettings); + if (result == errSecSuccess && *trustSettings == NULL) { + result = errSecItemNotFound; /* documented result if no trust settings exist */ + } + return result; +} + #pragma mark --- API functions --- OSStatus SecTrustSettingsCopyTrustSettings( @@ -792,7 +864,7 @@ OSStatus SecTrustSettingsSetTrustSettings( return result; } - auto_ptr_(ts); + unique_ptr_(ts); ts->setTrustSettings(certRef, trustSettingsDictOrArray); ts->flushToDisk(); @@ -822,7 +894,7 @@ OSStatus SecTrustSettingsRemoveTrustSettings( return result; } - auto_ptr_(ts); + unique_ptr_(ts); /* deleteTrustSettings throws if record not found */ trustSettingsDbg("SecTrustSettingsRemoveTrustSettings: deleting from domain %d", @@ -854,7 +926,7 @@ OSStatus SecTrustSettingsCopyCertificates( return status; } - auto_ptr_(ts); + unique_ptr_(ts); CFMutableArrayRef outArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); @@ -1003,6 +1075,16 @@ OSStatus SecTrustSettingsCopyCertificatesForUserAdminDomains( return result; } +bool SecTrustSettingsUserAdminDomainsContain(SecCertificateRef certRef) +{ + TS_REQUIRED(certRef) + if (tsContains(certRef, kSecTrustSettingsDomainAdmin) == errSecSuccess || + tsContains(certRef, kSecTrustSettingsDomainUser) == errSecSuccess) { + return true; + } + return false; +} + /* * Obtain an external, portable representation of the specified * domain's TrustSettings. Caller must CFRelease the returned data. @@ -1023,7 +1105,7 @@ OSStatus SecTrustSettingsCreateExternalRepresentation( return result; } - auto_ptr_(ts); + unique_ptr_(ts); *trustSettings = ts->createExternal(); return errSecSuccess; @@ -1053,7 +1135,7 @@ OSStatus SecTrustSettingsImportExternalRepresentation( return result; } - auto_ptr_(ts); + unique_ptr_(ts); ts->flushToDisk(); tsTrustSettingsChanged(); diff --git a/OSX/libsecurity_keychain/lib/SecTrustedApplication.cpp b/OSX/libsecurity_keychain/lib/SecTrustedApplication.cpp index 5f9e0c78..6a240424 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustedApplication.cpp +++ b/OSX/libsecurity_keychain/lib/SecTrustedApplication.cpp @@ -44,7 +44,6 @@ CFTypeID SecTrustedApplicationGetTypeID(void) { BEGIN_SECAPI - return gTypes().TrustedApplication.typeID; END_SECAPI1(_kCFRuntimeNotATypeID) @@ -195,7 +194,6 @@ OSStatus SecTrustedApplicationCreateApplicationGroup(const char *groupName, SecCertificateRef anchor, SecTrustedApplicationRef *appRef) { BEGIN_SECAPI - CFRef req; MacOSError::check(SecRequirementCreateGroup(CFTempString(groupName), anchor, kSecCSDefaultFlags, &req.aref())); diff --git a/OSX/libsecurity_keychain/lib/SecTrustedApplication.h b/OSX/libsecurity_keychain/lib/SecTrustedApplication.h index b1f37a6e..286ce287 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustedApplication.h +++ b/OSX/libsecurity_keychain/lib/SecTrustedApplication.h @@ -58,7 +58,7 @@ CFTypeID SecTrustedApplicationGetTypeID(void); */ OSStatus SecTrustedApplicationCreateFromPath(const char * __nullable path, SecTrustedApplicationRef * __nonnull CF_RETURNS_RETAINED app) API_DEPRECATED("No longer supported", macos(10.0, 10.15)) - API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecTrustedApplicationCopyData @@ -69,7 +69,7 @@ OSStatus SecTrustedApplicationCreateFromPath(const char * __nullable path, SecTr */ OSStatus SecTrustedApplicationCopyData(SecTrustedApplicationRef appRef, CFDataRef * __nonnull CF_RETURNS_RETAINED data) API_DEPRECATED("No longer supported", macos(10.0, 10.15)) - API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecTrustedApplicationSetData @@ -80,7 +80,7 @@ OSStatus SecTrustedApplicationCopyData(SecTrustedApplicationRef appRef, CFDataRe */ OSStatus SecTrustedApplicationSetData(SecTrustedApplicationRef appRef, CFDataRef data) API_DEPRECATED("No longer supported", macos(10.0, 10.15)) - API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_keychain/lib/SecTrustedApplicationPriv.h b/OSX/libsecurity_keychain/lib/SecTrustedApplicationPriv.h index 1b9911ad..6c6badad 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustedApplicationPriv.h +++ b/OSX/libsecurity_keychain/lib/SecTrustedApplicationPriv.h @@ -42,7 +42,7 @@ extern "C" { * Determine whether the application at path satisfies the trust expressed in appRef. */ OSStatus -SecTrustedApplicationValidateWithPath(SecTrustedApplicationRef appRef, const char *path) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +SecTrustedApplicationValidateWithPath(SecTrustedApplicationRef appRef, const char *path) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecTrustedApplicationCreateFromRequirement @@ -60,7 +60,7 @@ SecTrustedApplicationValidateWithPath(SecTrustedApplicationRef appRef, const cha @result A result code. See SecBase.h and CSCommon.h. */ OSStatus SecTrustedApplicationCreateFromRequirement(const char *description, - SecRequirementRef requirement, SecTrustedApplicationRef *app) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecRequirementRef requirement, SecTrustedApplicationRef *app) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecTrustedApplicationCopyRequirement @@ -78,7 +78,7 @@ OSStatus SecTrustedApplicationCreateFromRequirement(const char *description, no SecRequirementRef could be obtained. */ OSStatus SecTrustedApplicationCopyRequirement(SecTrustedApplicationRef appRef, - SecRequirementRef *requirement) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecRequirementRef *requirement) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @@ -101,7 +101,7 @@ OSStatus SecTrustedApplicationCopyRequirement(SecTrustedApplicationRef appRef, @result A result code. See SecBase.h and CSCommon.h. */ OSStatus SecTrustedApplicationCreateApplicationGroup(const char *groupName, - SecCertificateRef anchor, SecTrustedApplicationRef *app) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecCertificateRef anchor, SecTrustedApplicationRef *app) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @@ -118,7 +118,7 @@ OSStatus SecTrustedApplicationCreateApplicationGroup(const char *groupName, */ OSStatus SecTrustedApplicationCopyExternalRepresentation( SecTrustedApplicationRef appRef, - CFDataRef *externalRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + CFDataRef *externalRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecTrustedApplicationCreateWithExternalRepresentation @@ -133,7 +133,7 @@ OSStatus SecTrustedApplicationCopyExternalRepresentation( */ OSStatus SecTrustedApplicationCreateWithExternalRepresentation( CFDataRef externalRef, - SecTrustedApplicationRef *appRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecTrustedApplicationRef *appRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* @@ -146,10 +146,10 @@ enum { OSStatus SecTrustedApplicationMakeEquivalent(SecTrustedApplicationRef oldRef, - SecTrustedApplicationRef newRef, UInt32 flags) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + SecTrustedApplicationRef newRef, UInt32 flags) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); OSStatus -SecTrustedApplicationRemoveEquivalence(SecTrustedApplicationRef appRef, UInt32 flags) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +SecTrustedApplicationRemoveEquivalence(SecTrustedApplicationRef appRef, UInt32 flags) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* @@ -157,7 +157,7 @@ SecTrustedApplicationRemoveEquivalence(SecTrustedApplicationRef appRef, UInt32 f * pre-emptive code equivalency establishment */ OSStatus -SecTrustedApplicationIsUpdateCandidate(const char *installroot, const char *path) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +SecTrustedApplicationIsUpdateCandidate(const char *installroot, const char *path) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* @@ -165,7 +165,7 @@ SecTrustedApplicationIsUpdateCandidate(const char *installroot, const char *path * This is for system update installers (only)! */ OSStatus -SecTrustedApplicationUseAlternateSystem(const char *systemRoot) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +SecTrustedApplicationUseAlternateSystem(const char *systemRoot) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if defined(__cplusplus) diff --git a/OSX/libsecurity_keychain/lib/SecWrappedKeys.cpp b/OSX/libsecurity_keychain/lib/SecWrappedKeys.cpp index 83b8db37..a438f948 100644 --- a/OSX/libsecurity_keychain/lib/SecWrappedKeys.cpp +++ b/OSX/libsecurity_keychain/lib/SecWrappedKeys.cpp @@ -34,7 +34,7 @@ #include #include -#include +#include using namespace Security; using namespace KeychainCore; diff --git a/OSX/libsecurity_keychain/lib/StorageManager.cpp b/OSX/libsecurity_keychain/lib/StorageManager.cpp index efab9b8b..e173e851 100644 --- a/OSX/libsecurity_keychain/lib/StorageManager.cpp +++ b/OSX/libsecurity_keychain/lib/StorageManager.cpp @@ -1356,10 +1356,11 @@ void StorageManager::login(ConstStringPtr name, ConstStringPtr password) { StLock_(mMutex); - if ( name == NULL || password == NULL ) + if ( name == NULL || password == NULL ) { MacOSError::throwMe(errSecParam); + } - login(name[0], name + 1, password[0], password + 1, false); + login(name[0], name + 1, password[0], password + 1, false); } void StorageManager::login(UInt32 nameLength, const void *name, diff --git a/OSX/libsecurity_keychain/lib/TrustAdditions.cpp b/OSX/libsecurity_keychain/lib/TrustAdditions.cpp index 3fa9aabb..0710cadb 100644 --- a/OSX/libsecurity_keychain/lib/TrustAdditions.cpp +++ b/OSX/libsecurity_keychain/lib/TrustAdditions.cpp @@ -377,10 +377,11 @@ CFArrayRef potentialEVChainWithCertificates(CFArrayRef certificates) // static SecCertificateRef _rootCertificateWithSubjectOfCertificate(SecCertificateRef certificate) { - if (!certificate) + if (!certificate) { return NULL; + } - StLock _(SecTrustKeychainsGetMutex()); + StLock _(SecTrustKeychainsGetMutex()); // get data+length for the provided certificate CSSM_CL_HANDLE clHandle = 0; @@ -519,8 +520,9 @@ static SecCertificateRef _rootCertificateWithSubjectKeyIDOfCertificate(SecCertif SecCertificateRef resultCert = NULL; OSStatus status = errSecSuccess; - if (!certificate) + if (!certificate) { return NULL; + } StLock _(SecTrustKeychainsGetMutex()); @@ -557,8 +559,9 @@ CFArrayRef CF_RETURNS_RETAINED _possibleRootCertificatesForOidString(CFStringRef { StLock _(SecTrustKeychainsGetMutex()); - if (!oidString) + if (!oidString) { return NULL; + } CFDictionaryRef evOidDict = _evCAOidDict(); if (!evOidDict) return NULL; diff --git a/OSX/libsecurity_keychain/lib/TrustRevocation.cpp b/OSX/libsecurity_keychain/lib/TrustRevocation.cpp index 6338d1c0..8cd49615 100644 --- a/OSX/libsecurity_keychain/lib/TrustRevocation.cpp +++ b/OSX/libsecurity_keychain/lib/TrustRevocation.cpp @@ -261,7 +261,7 @@ CFMutableArrayRef Trust::addPreferenceRevocationPolicies( pd = new Dictionary(tempDict); CFRelease(tempDict); - auto_ptr prefsDict(pd); + unique_ptr prefsDict(pd); bool doOcsp = false; bool doCrl = false; diff --git a/OSX/libsecurity_keychain/lib/TrustSettings.cpp b/OSX/libsecurity_keychain/lib/TrustSettings.cpp index 7474aca6..c834712c 100644 --- a/OSX/libsecurity_keychain/lib/TrustSettings.cpp +++ b/OSX/libsecurity_keychain/lib/TrustSettings.cpp @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include #include @@ -1019,6 +1019,14 @@ CFDateRef TrustSettings::copyModDate( return modDate; } +bool TrustSettings::contains(SecCertificateRef certRef) +{ + if(findDictionaryForCert(certRef) != NULL) { + return true; + } + return false; +} + /* * Modify cert's trust settings, or add a new cert to the record. */ diff --git a/OSX/libsecurity_keychain/lib/TrustSettings.h b/OSX/libsecurity_keychain/lib/TrustSettings.h index d1362d53..c98d1a26 100644 --- a/OSX/libsecurity_keychain/lib/TrustSettings.h +++ b/OSX/libsecurity_keychain/lib/TrustSettings.h @@ -177,6 +177,11 @@ public: */ CFDataRef createExternal(); + /* + * Indicates whether the trust settings contain any settings for this cert. + */ + bool contains(SecCertificateRef certRef); + private: /* common code to init mPropList from raw data */ void initFromData( diff --git a/OSX/libsecurity_keychain/lib/TrustSettingsUtils.cpp b/OSX/libsecurity_keychain/lib/TrustSettingsUtils.cpp index e001afd0..934449a6 100644 --- a/OSX/libsecurity_keychain/lib/TrustSettingsUtils.cpp +++ b/OSX/libsecurity_keychain/lib/TrustSettingsUtils.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/OSX/libsecurity_keychain/regressions/kc-key-helpers.h b/OSX/libsecurity_keychain/regressions/kc-key-helpers.h index a3508aa5..8cc1201a 100644 --- a/OSX/libsecurity_keychain/regressions/kc-key-helpers.h +++ b/OSX/libsecurity_keychain/regressions/kc-key-helpers.h @@ -227,16 +227,19 @@ static void checkKeyUse(SecKeyRef key, OSStatus expectedStatus) { CFErrorRef error = NULL; CFDataRef ciphertextData = SecTransformExecute(transform, &error); + CFDataRef roundtripData = NULL; if(error) { - is(CFErrorGetCode(error), expectedStatus, "%s: Encrypting data failed: %d %s (and expected %d)", testName, (int) CFErrorGetCode(error), CFStringGetCStringPtr(CFErrorCopyDescription(error), kCFStringEncodingUTF8), (int) expectedStatus); + CFStringRef errorStr = CFErrorCopyDescription(error); + is(CFErrorGetCode(error), expectedStatus, "%s: Encrypting data failed: %d %s (and expected %d)", testName, (int) CFErrorGetCode(error), CFStringGetCStringPtr(errorStr, kCFStringEncodingUTF8), (int) expectedStatus); + CFReleaseSafe(errorStr); if(expectedStatus != errSecSuccess) { // make test numbers match and quit for(int i = 1; i < checkKeyUseTests; i++) { pass("test numbers match"); } - return; + goto cleanup; } } else { @@ -251,21 +254,21 @@ static void checkKeyUse(SecKeyRef key, OSStatus expectedStatus) { SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, NULL); SecTransformSetAttribute(transform, kSecTransformInputAttributeName, ciphertextData, NULL); - CFDataRef roundtripData = SecTransformExecute(transform, &error); + roundtripData = SecTransformExecute(transform, &error); is(error, NULL, "%s: checkKeyUse: SecTransformExecute (decrypt)", testName); if(error) { CFStringRef errorStr = CFErrorCopyDescription(error); fail("%s: Decrypting data failed: %d %s", testName, (int) CFErrorGetCode(error), CFStringGetCStringPtr(errorStr, kCFStringEncodingUTF8)); - CFRelease(errorStr); + CFReleaseSafe(errorStr); } else { pass("%s: make test numbers match", testName); } - CFReleaseSafe(transform); - eq_cf(plaintextData, roundtripData, "%s: checkKeyUse: roundtripped data is input data", testName); + cleanup: + CFReleaseSafe(transform); CFReleaseSafe(plaintext); CFReleaseSafe(plaintextData); CFReleaseSafe(ciphertextData); diff --git a/OSX/libsecurity_keychain/xpc-tsa/timestampclient.m b/OSX/libsecurity_keychain/xpc-tsa/timestampclient.m index 148be634..180950ac 100644 --- a/OSX/libsecurity_keychain/xpc-tsa/timestampclient.m +++ b/OSX/libsecurity_keychain/xpc-tsa/timestampclient.m @@ -48,7 +48,8 @@ void sendTSARequest(CFDataRef tsaReq, const char *tsaURL, TSARequestCompletionBl - (id)init { - self = [super init]; + if ((self = [super init])) { + } return self; } diff --git a/OSX/libsecurity_manifest/lib/AppleManifest.cpp b/OSX/libsecurity_manifest/lib/AppleManifest.cpp index c7d3429f..d181e1ef 100644 --- a/OSX/libsecurity_manifest/lib/AppleManifest.cpp +++ b/OSX/libsecurity_manifest/lib/AppleManifest.cpp @@ -584,12 +584,13 @@ void AppleManifest::ReconstructOther (uint32& finger, const uint8* data, Manifes void AppleManifest::ReconstructManifestItemList (uint32 &finger, const uint8* data, ManifestItemList &itemList) { - uint32 start = finger; - uint64_t length = ReconstructUInt64 (finger, data); + uint32 start = finger; + uint64_t length = ReconstructUInt64 (finger, data); uint32 end = (uint32)(start + length); - if (length > UINT32_MAX || (length + (uint64_t)start) > (uint64_t)UINT32_MAX) + if (length > UINT32_MAX || (length + (uint64_t)start) > (uint64_t)UINT32_MAX) { MacOSError::throwMe (errSecManifestDamaged); + } while (finger < end) { diff --git a/OSX/libsecurity_manifest/lib/Manifest.cpp b/OSX/libsecurity_manifest/lib/Manifest.cpp index 42b75c6a..b8d9d835 100644 --- a/OSX/libsecurity_manifest/lib/Manifest.cpp +++ b/OSX/libsecurity_manifest/lib/Manifest.cpp @@ -35,7 +35,7 @@ Manifest::Manifest () : mManifestSigner (NULL) -Manifest::~Manifest () throw () +Manifest::~Manifest () _NOEXCEPT { delete mManifestSigner; } diff --git a/OSX/libsecurity_manifest/lib/Manifest.h b/OSX/libsecurity_manifest/lib/Manifest.h index 27ebff42..8e0e223f 100644 --- a/OSX/libsecurity_manifest/lib/Manifest.h +++ b/OSX/libsecurity_manifest/lib/Manifest.h @@ -49,7 +49,7 @@ public: Manifest (); - virtual ~Manifest () throw (); + virtual ~Manifest () _NOEXCEPT; ManifestInternal& GetManifestInternal () {return mManifestInternal;} ManifestSigner* GetSigner () {return mManifestSigner;} diff --git a/OSX/libsecurity_manifest/lib/SecureDownloadInternal.c b/OSX/libsecurity_manifest/lib/SecureDownloadInternal.c index e035ca50..7e5a4921 100644 --- a/OSX/libsecurity_manifest/lib/SecureDownloadInternal.c +++ b/OSX/libsecurity_manifest/lib/SecureDownloadInternal.c @@ -3,6 +3,8 @@ #include "SecureDownloadInternal.h" #include "SecCFRelease.h" +#include "simulatecrash_assert.h" + // // SecureDownloadXML: SecureDownloadXML.c // cc -g -framework CoreFoundation -o $@ $^ diff --git a/OSX/libsecurity_mds/lib/MDSSession.cpp b/OSX/libsecurity_mds/lib/MDSSession.cpp index f11949ef..42c421f0 100644 --- a/OSX/libsecurity_mds/lib/MDSSession.cpp +++ b/OSX/libsecurity_mds/lib/MDSSession.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_mds/lib/MDSSession.h b/OSX/libsecurity_mds/lib/MDSSession.h index 0c8718da..078652cc 100644 --- a/OSX/libsecurity_mds/lib/MDSSession.h +++ b/OSX/libsecurity_mds/lib/MDSSession.h @@ -71,11 +71,11 @@ public: void removeSubservice(const char *guid, uint32 ssid); // implement CssmHeap::Allocator - void *malloc(size_t size) throw(std::bad_alloc) + void *malloc(size_t size) { return mCssmMemoryFunctions.malloc(size); } - void free(void *addr) throw() + void free(void *addr) _NOEXCEPT { mCssmMemoryFunctions.free(addr); } - void *realloc(void *addr, size_t size) throw(std::bad_alloc) + void *realloc(void *addr, size_t size) { return mCssmMemoryFunctions.realloc(addr, size); } MDSModule &module() { return mModule; } diff --git a/OSX/libsecurity_mds/lib/mdsapi.cpp b/OSX/libsecurity_mds/lib/mdsapi.cpp index 2f18194a..3ab20d1d 100644 --- a/OSX/libsecurity_mds/lib/mdsapi.cpp +++ b/OSX/libsecurity_mds/lib/mdsapi.cpp @@ -36,6 +36,7 @@ #include #include #include +#include "LegacyAPICounts.h" #define MSApiDebug(args...) secinfo("MDS_API", ## args) @@ -286,7 +287,7 @@ CSSM_RETURN CSSMAPI MDS_Terminate (MDS_HANDLE inMDSHandle) { BEGIN_API - auto_ptr aMDSSession (&HandleObject::findAndKill (inMDSHandle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE)); + unique_ptr aMDSSession (&HandleObject::findAndKill (inMDSHandle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE)); aMDSSession->terminate (); // Even if terminate throws the MDSSession object will be deleted. END_API(MDS) } diff --git a/OSX/libsecurity_ocspd/client/ocspdClient.cpp b/OSX/libsecurity_ocspd/client/ocspdClient.cpp index 01db7249..be931ce6 100644 --- a/OSX/libsecurity_ocspd/client/ocspdClient.cpp +++ b/OSX/libsecurity_ocspd/client/ocspdClient.cpp @@ -313,10 +313,11 @@ CSSM_RETURN ocspdCRLStatus( issuers.Data, (mach_msg_type_number_t)issuers.Length, crlIssuer ? crlIssuer->Data : NULL, crlIssuer ? (mach_msg_type_number_t)crlIssuer->Length : 0, crlURL ? crlURL->Data : NULL, crlURL ? (mach_msg_type_number_t)crlURL->Length : 0); - if (krtn == MACH_SEND_INVALID_DEST) + if (krtn == MACH_SEND_INVALID_DEST) { OcspdGlobals().resetServerPort(); + } - return krtn; + return krtn; } /* diff --git a/OSX/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp b/OSX/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp index a1e93fd2..b1902a05 100644 --- a/OSX/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp +++ b/OSX/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp @@ -31,7 +31,7 @@ #include "pkcs12BagAttrs.h" #include "pkcs12Utils.h" #include -#include +#include #include /* * Copying constructor used by P12SafeBag during encoding diff --git a/OSX/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp b/OSX/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp index f2e068bc..4620c438 100644 --- a/OSX/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp +++ b/OSX/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp @@ -29,7 +29,7 @@ #include "pkcs12Debug.h" #include "pkcs12Utils.h" #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp b/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp index b72e2e52..802f98e6 100644 --- a/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp +++ b/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp @@ -360,9 +360,9 @@ SDCSPSession::FreeKey(const AccessCredentials *accessCred, // that! // Find the key in the map. Tell tell the key to free itself - // (when the auto_ptr deletes the key it removes itself from the map). + // (when the unique_ptr deletes the key it removes itself from the map). secinfo("freeKey", "CSPDL FreeKey"); - auto_ptr ssKey(&mSDCSPDLSession.find(ioKey)); + unique_ptr ssKey(&mSDCSPDLSession.find(ioKey)); ssKey->free(accessCred, ioKey, deleteKey); } else diff --git a/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp b/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp index 1717eaf5..788b0b3f 100644 --- a/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp +++ b/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp @@ -486,7 +486,7 @@ SDCryptContext::final(CssmData &out) if(!inSize) return; const CssmData in(const_cast(mNullDigest.digestPtr()), inSize); - IFDEBUG(size_t origOutSize = out.length()); + size_t origOutSize = out.length(); if (encoding()) { clientSession().encrypt(*mContext, mKeyHandle, in, out); } diff --git a/OSX/libsecurity_smime/lib/cert.c b/OSX/libsecurity_smime/lib/cert.c index 8c99fef3..dd737709 100644 --- a/OSX/libsecurity_smime/lib/cert.c +++ b/OSX/libsecurity_smime/lib/cert.c @@ -39,6 +39,7 @@ #include #include #include +#include #include /* for errKCDuplicateItem */ @@ -51,10 +52,6 @@ #define dprintf(args...) #endif -/* @@@ Remove this once it's back in the appropriate header. */ -static const uint8 X509V1IssuerNameStd[] = {INTEL_X509V3_CERT_R08, 23}; -static const CSSM_OID OID_X509V1IssuerNameStd = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1IssuerNameStd}; - /* * Normalize a Printable String. Per RFC2459 (4.1.2.4), printable strings are case * insensitive and we're supposed to ignore leading and trailing @@ -579,100 +576,59 @@ SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert, SECItem *retIt // Extract the issuer and serial number from a certificate SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert) { - OSStatus status; SecCmsIssuerAndSN *certIssuerAndSN; - SecCertificateRef certRef; - SecCertificateRef itemImplRef = NULL; - CSSM_CL_HANDLE clHandle = 0; - CSSM_DATA_PTR serialNumber = 0; - CSSM_DATA_PTR issuer = 0; - CSSM_DATA certData = {}; - CSSM_HANDLE resultsHandle = 0; - uint32 numberOfFields = 0; - CSSM_RETURN result; - void *mark; + void *mark; mark = PORT_ArenaMark(pl); - - /* Retain input cert and get pointer to its data */ - certRef = (SecCertificateRef)((cert) ? CFRetain(cert) : NULL); - if (!certRef || SecCertificateGetData(certRef, &certData)) { + CFDataRef issuer_data = SecCertificateCopyIssuerSequence(cert); + CFDataRef serial_data = SecCertificateCopySerialNumberData(cert, NULL); + if (!issuer_data || !serial_data) { goto loser; } -#if 1 - // Convert unified input certRef to itemImpl instance. - // note: must not release this instance while we're using its CL handle! - itemImplRef = SecCertificateCreateItemImplInstance(cert); - status = SecCertificateGetCLHandle_legacy(itemImplRef, &clHandle); -#else - status = SecCertificateGetCLHandle(certRef, &clHandle); -#endif - if (status) - goto loser; - - /* Get the issuer from the cert. */ - result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, - &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer); - if (result || numberOfFields < 1) - goto loser; - result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); - if (result) - goto loser; - - /* Get the serialNumber from the cert. */ - result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, - &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber); - if (result || numberOfFields < 1) - goto loser; - result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); - if (result) - goto loser; + SecAsn1Item serialNumber = { + .Length = CFDataGetLength(serial_data), + .Data = (uint8_t *)CFDataGetBytePtr(serial_data) + }; + SecAsn1Item issuer = { + .Length = CFDataGetLength(issuer_data), + .Data = (uint8_t *)CFDataGetBytePtr(issuer_data) + }; /* Allocate the SecCmsIssuerAndSN struct. */ certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN)); - if (certIssuerAndSN == NULL) + if (certIssuerAndSN == NULL) { goto loser; + } /* Copy the issuer. */ - certIssuerAndSN->derIssuer.Data = (uint8 *) PORT_ArenaAlloc(pl, issuer->Length); - if (!certIssuerAndSN->derIssuer.Data) + certIssuerAndSN->derIssuer.Data = (uint8_t *) PORT_ArenaAlloc(pl, issuer.Length); + if (!certIssuerAndSN->derIssuer.Data) { goto loser; - PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer->Data, issuer->Length); - certIssuerAndSN->derIssuer.Length = issuer->Length; + } + PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer.Data, issuer.Length); + certIssuerAndSN->derIssuer.Length = issuer.Length; /* Copy the serialNumber. */ - certIssuerAndSN->serialNumber.Data = (uint8 *) PORT_ArenaAlloc(pl, serialNumber->Length); - if (!certIssuerAndSN->serialNumber.Data) + certIssuerAndSN->serialNumber.Data = (uint8_t *) PORT_ArenaAlloc(pl, serialNumber.Length); + if (!certIssuerAndSN->serialNumber.Data) { goto loser; - PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber->Data, serialNumber->Length); - certIssuerAndSN->serialNumber.Length = serialNumber->Length; - - PORT_ArenaUnmark(pl, mark); - - CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); - CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); + } + PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber.Data, serialNumber.Length); + certIssuerAndSN->serialNumber.Length = serialNumber.Length; - if (itemImplRef) - CFRelease(itemImplRef); - if (certRef) - CFRelease(certRef); + CFRelease(serial_data); + CFRelease(issuer_data); + PORT_ArenaUnmark(pl, mark); return certIssuerAndSN; loser: + CFReleaseNull(serial_data); + CFReleaseNull(issuer_data); PORT_ArenaRelease(pl, mark); - - if (serialNumber) - CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); - if (issuer) - CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); - if (itemImplRef) - CFRelease(itemImplRef); - if (certRef) - CFRelease(certRef); - PORT_SetError(SEC_INTERNAL_ONLY); + return NULL; } diff --git a/OSX/libsecurity_smime/lib/cmsdigest.c b/OSX/libsecurity_smime/lib/cmsdigest.c index 102b8a4f..42d5ae51 100644 --- a/OSX/libsecurity_smime/lib/cmsdigest.c +++ b/OSX/libsecurity_smime/lib/cmsdigest.c @@ -34,7 +34,7 @@ /* * CMS digesting. */ -#include +#include #include "cmslocal.h" diff --git a/OSX/libsecurity_smime/lib/cmssiginfo.c b/OSX/libsecurity_smime/lib/cmssiginfo.c index 3a83746d..c3cd380b 100644 --- a/OSX/libsecurity_smime/lib/cmssiginfo.c +++ b/OSX/libsecurity_smime/lib/cmssiginfo.c @@ -456,24 +456,22 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_ SECITEM_FreeItem(&signature, PR_FALSE); - if(pubkAlgTag == SEC_OID_EC_PUBLIC_KEY) { - /* - * RFC 3278 section section 2.1.1 states that the signatureAlgorithm - * field contains the full ecdsa-with-SHA1 OID, not plain old ecPublicKey - * as would appear in other forms of signed datas. However Microsoft doesn't - * do this, it puts ecPublicKey there, and if we put ecdsa-with-SHA1 there, - * MS can't verify - presumably because it takes the digest of the digest - * before feeding it to ECDSA. - * We handle this with a preference; default if it's not there is - * "Microsoft compatibility mode". - */ - if(!SecCmsMsEcdsaCompatMode()) { - pubkAlgTag = SEC_OID_ECDSA_WithSHA1; - } - /* else violating the spec for compatibility */ - } - - if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), pubkAlgTag, + SECOidTag sigAlgTag = SecCmsUtilMakeSignatureAlgorithm(digestalgtag, pubkAlgTag); + if(pubkAlgTag == SEC_OID_EC_PUBLIC_KEY && SecCmsMsEcdsaCompatMode()) { + /* + * RFC 3278 section section 2.1.1 states that the signatureAlgorithm + * field contains the full ecdsa-with-SHA1 OID, not plain old ecPublicKey + * as would appear in other forms of signed datas. However Microsoft doesn't + * do this, it puts ecPublicKey there, and if we put ecdsa-with-SHA1 there, + * MS can't verify - presumably because it takes the digest of the digest + * before feeding it to ECDSA. + * We handle this with a preference; default if it's not there is + * "Microsoft compatibility mode". + */ + sigAlgTag = SEC_OID_EC_PUBLIC_KEY; + } + + if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), sigAlgTag, NULL) != SECSuccess) goto loser; @@ -599,16 +597,6 @@ SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeSt digestAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestAlg)); digestEncAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)); - /* - * Gross hack necessitated by RFC 3278 section 2.1.1, which states - * that the signature algorithm (here, digestEncAlg) contains ecdsa_with-SHA1, - * *not* (as in all other algorithms) the raw signature algorithm, e.g. - * pkcs1RSAEncryption. - */ - if(digestEncAlgTag == SEC_OID_ECDSA_WithSHA1) { - digestEncAlgTag = SEC_OID_EC_PUBLIC_KEY; - } - if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr)) { if (contentType) { /* @@ -1182,12 +1170,19 @@ SecCmsSignerInfoGetSignerEmailAddress(SecCmsSignerInfoRef sinfo) SecCertificateRef signercert; CFStringRef emailAddress = NULL; - if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) - return NULL; - - SecCertificateGetEmailAddress(signercert, &emailAddress); + if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) { + return NULL; + } - return CFRetainSafe(emailAddress); + CFArrayRef names = SecCertificateCopyRFC822Names(signercert); + if (names) { + if (CFArrayGetCount(names) > 0) { + emailAddress = (CFStringRef)CFArrayGetValueAtIndex(names, 0); + } + CFRetainSafe(emailAddress); + CFRelease(names); + } + return emailAddress; } diff --git a/OSX/libsecurity_smime/lib/tsaSupport.c b/OSX/libsecurity_smime/lib/tsaSupport.c index 9718426c..85711fd1 100644 --- a/OSX/libsecurity_smime/lib/tsaSupport.c +++ b/OSX/libsecurity_smime/lib/tsaSupport.c @@ -1158,9 +1158,10 @@ static OSStatus impExpImportCertUnCommon( } xit: - if (certRef) + if (certRef) { CFRelease(certRef); - return status; + } + return status; } static void saveTSACertificates(CSSM_DATA **signingCerts, CFMutableArrayRef outArray) diff --git a/OSX/libsecurity_smime/lib/tsaTemplates.c b/OSX/libsecurity_smime/lib/tsaTemplates.c index 342d0341..6e627be2 100644 --- a/OSX/libsecurity_smime/lib/tsaTemplates.c +++ b/OSX/libsecurity_smime/lib/tsaTemplates.c @@ -26,7 +26,6 @@ #include /* for kSecAsn1AlgorithmIDTemplate */ #include #include -#include #include "tsaTemplates.h" #include "cmslocal.h" diff --git a/OSX/libsecurity_smime/regressions/cms-01-basic.c b/OSX/libsecurity_smime/regressions/cms-01-basic.c index 7af821b7..79816473 100644 --- a/OSX/libsecurity_smime/regressions/cms-01-basic.c +++ b/OSX/libsecurity_smime/regressions/cms-01-basic.c @@ -102,12 +102,12 @@ out: } #define kNumberCleanupTests 1 -static void cleanup_keychain(SecKeychainRef keychain, SecIdentityRef identity, SecCertificateRef cert) { +static void cleanup_keychain(SecKeychainRef* keychain, SecIdentityRef* identity, SecCertificateRef* cert) { /* Delete keychain - from the search list and from disk */ - ok_status(SecKeychainDelete(keychain), "Delete temporary keychain"); - CFReleaseNull(keychain); - CFReleaseNull(cert); - CFReleaseNull(identity); + ok_status(SecKeychainDelete(*keychain), "Delete temporary keychain"); + CFReleaseNull(*keychain); + CFReleaseNull(*cert); + CFReleaseNull(*identity); } static OSStatus sign_please(SecIdentityRef identity, SECOidTag digestAlgTag, bool withAttrs, uint8_t *expected_output, size_t expected_len) { @@ -370,7 +370,7 @@ static void sign_tests(SecIdentityRef identity, bool isRSA) { is(sign_please(identity, SEC_OID_SHA1, false, (isRSA) ? rsa_sha1 : NULL, (isRSA) ? sizeof(rsa_sha1) : 0), errSecSuccess, "Signed with SHA-1"); - is(sign_please(identity, SEC_OID_SHA256, false, (isRSA) ? rsa_sha256 : NULL, + is(sign_please(identity, SEC_OID_SHA256, false, (isRSA) ? new_sig_alg_rsa_sha256 : NULL, (isRSA) ? sizeof(rsa_sha256) : 0), errSecSuccess, "Signed with SHA-256"); is(sign_please(identity, SEC_OID_SHA384, false, NULL, 0), errSecSuccess, "Signed with SHA-384"); @@ -494,7 +494,7 @@ int cms_01_basic(int argc, char *const *argv) verify_tests(kc, true); encrypt_tests(certificate); decrypt_tests(true); - cleanup_keychain(kc, identity, certificate); + cleanup_keychain(&kc, &identity, &certificate); /* EC tests */ kc = setup_keychain(_ec_identity, sizeof(_ec_identity), &identity, &certificate); @@ -502,7 +502,7 @@ int cms_01_basic(int argc, char *const *argv) verify_tests(kc, false); encrypt_tests(certificate); decrypt_tests(false); - cleanup_keychain(kc, identity, certificate); + cleanup_keychain(&kc, &identity, &certificate); return 0; } diff --git a/OSX/libsecurity_smime/regressions/cms-01-basic.h b/OSX/libsecurity_smime/regressions/cms-01-basic.h index 371b8f69..c7ad36b9 100644 --- a/OSX/libsecurity_smime/regressions/cms-01-basic.h +++ b/OSX/libsecurity_smime/regressions/cms-01-basic.h @@ -465,7 +465,7 @@ unsigned char rsa_sha1[] = { 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, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, - 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, + 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x29, 0xbb, 0xc2, 0xc1, 0x17, 0xb9, 0x7d, 0x8b, 0x43, 0xc6, 0x25, 0xad, 0xf1, 0xae, 0xb6, 0x26, 0x78, 0x9c, 0x92, 0x47, 0x77, 0xf8, 0xac, 0x53, 0xca, 0x17, 0x58, 0x4a, 0x8d, 0x66, 0x44, 0x99, 0x14, 0x3f, 0x63, 0x98, 0x3a, 0x7c, 0xe6, 0x65, 0xf0, 0x2a, 0x5e, 0x49, 0xbe, 0xdd, 0x40, 0x6e, 0x21, 0x43, 0xe1, 0xb9, 0x13, 0xa8, 0x31, 0xbf, 0x12, 0xb2, 0x78, 0x97, @@ -565,6 +565,89 @@ unsigned char rsa_sha256[] = { 0x45, 0xc2, 0x99, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +unsigned char new_sig_alg_rsa_sha256[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 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, 0xdc, 0x30, 0x82, 0x01, 0xd8, 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, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x0b, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xc9, 0x25, 0xbe, 0xb8, 0xf2, 0x2c, 0x7f, 0xc8, 0x3a, 0xc3, 0xc2, 0x4b, + 0xac, 0x54, 0xcf, 0xa6, 0x75, 0xaa, 0xeb, 0x40, 0x68, 0xee, 0xe2, 0xb1, 0xa8, 0x70, 0x9e, 0xe9, 0x8b, 0xf1, 0x0a, 0x85, + 0x88, 0x40, 0xef, 0xb8, 0xa5, 0x04, 0x87, 0x63, 0x03, 0xf5, 0x41, 0x81, 0x29, 0x42, 0x7f, 0x31, 0x8f, 0x5b, 0xde, 0xe8, + 0x15, 0xc1, 0xa3, 0x45, 0xf1, 0xbc, 0xff, 0x81, 0x58, 0xbd, 0xac, 0x4c, 0xa5, 0xb3, 0x30, 0x9a, 0xb8, 0x9e, 0x69, 0x10, + 0xad, 0x44, 0x7b, 0x93, 0x28, 0xba, 0xca, 0x6f, 0x2e, 0xf8, 0x1b, 0x03, 0xc2, 0x0a, 0x4a, 0x06, 0x32, 0x4d, 0x30, 0x50, + 0xb7, 0x9c, 0x57, 0x4d, 0x4b, 0x6c, 0x34, 0x53, 0xd8, 0xf5, 0xca, 0x91, 0xa5, 0xdf, 0xa6, 0x67, 0x0a, 0x2e, 0x02, 0x47, + 0x1c, 0x1c, 0xd6, 0x2b, 0xe2, 0x85, 0xc1, 0xda, 0x79, 0xa2, 0xe2, 0x1e, 0xf8, 0x5e, 0xf9, 0x76, 0x55, 0xaf, 0x61, 0xaf, + 0xde, 0x0a, 0x7b, 0xeb, 0xa1, 0xa8, 0xc6, 0xef, 0x76, 0x2f, 0x50, 0xd1, 0x0a, 0xce, 0xdb, 0x14, 0xc3, 0x13, 0x72, 0xe5, + 0x26, 0x67, 0x90, 0x19, 0x15, 0x7b, 0x79, 0x05, 0xeb, 0x20, 0xb3, 0x5a, 0x4e, 0x78, 0xae, 0x2d, 0x9c, 0xd1, 0x31, 0xfd, + 0x2e, 0xcb, 0x84, 0xb9, 0x67, 0xea, 0xaf, 0xb3, 0xc2, 0x5f, 0xf5, 0xcd, 0x7b, 0x66, 0x3f, 0xdf, 0xf7, 0xe7, 0x76, 0x46, + 0x57, 0xd9, 0xee, 0x4b, 0xb2, 0xc8, 0x7b, 0xf9, 0x88, 0xab, 0x8e, 0xca, 0xfc, 0x39, 0xd1, 0x8e, 0x1c, 0xba, 0x3e, 0x63, + 0xb7, 0xe8, 0x0e, 0x2f, 0xde, 0x6b, 0x76, 0x81, 0xbf, 0x78, 0x26, 0x0c, 0xa0, 0x2c, 0x35, 0x21, 0xde, 0xb4, 0x45, 0x0a, + 0x84, 0xea, 0x68, 0xa5, 0x37, 0xe8, 0x4a, 0xbc, 0xa6, 0xcf, 0x24, 0x85, 0x46, 0x33, 0x9e, 0xd9, 0xba, 0x58, 0x75, 0xd7, + 0x45, 0xc2, 0x99, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + /* * MARK: RSA-signed messages (with attributes) */ @@ -726,7 +809,7 @@ unsigned char rsa_sha1_attr[] = { 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x38, 0x31, 0x33, 0x32, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0xef, 0x53, 0x0b, 0xfa, 0xcf, 0x34, 0x18, 0xb3, 0x30, 0xff, 0xf8, 0x9e, 0x09, 0xb3, 0xb6, 0x21, 0xd6, 0x83, 0xb9, 0xe9, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x52, 0xbd, 0xa1, 0x0a, 0x41, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x52, 0xbd, 0xa1, 0x0a, 0x41, 0xce, 0xc1, 0xe8, 0xe8, 0x2f, 0x2e, 0x1f, 0x73, 0xd1, 0x2f, 0x2e, 0x53, 0x53, 0x21, 0xec, 0x88, 0x30, 0x6a, 0x9d, 0x58, 0x64, 0x95, 0xef, 0xf2, 0x20, 0x55, 0xb0, 0x15, 0x64, 0x02, 0x1d, 0xf9, 0x44, 0xdd, 0xcb, 0x7a, 0x9c, 0x50, 0x10, 0xea, 0xfa, 0x6f, 0x07, 0x64, 0xaf, 0x30, 0x6e, 0xe2, 0xc1, 0x34, 0x55, 0xd0, 0x6a, 0x6e, 0xe1, 0x09, 0x91, 0xb7, 0xe3, 0x7b, @@ -814,7 +897,7 @@ unsigned char rsa_sha256_attr[] = { 0x31, 0x33, 0x32, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x33, 0x1f, 0x3a, 0xc4, 0x95, 0x97, 0x64, 0x1c, 0x99, 0x9b, 0x37, 0xc8, 0xf2, 0xba, 0xd0, 0xb4, 0x38, 0xa5, 0x9c, 0x3a, 0xa3, 0x78, 0xf9, 0xfb, 0x66, 0x28, 0x4e, 0x6a, 0x90, 0xcc, 0x0e, 0x4c, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xae, 0x6d, 0xa9, 0xa7, 0xee, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xae, 0x6d, 0xa9, 0xa7, 0xee, 0x0c, 0x94, 0x1b, 0xf3, 0x93, 0x40, 0x43, 0x11, 0x41, 0x20, 0x11, 0x60, 0xd9, 0x4e, 0xb6, 0x2d, 0x3e, 0x98, 0xfe, 0x06, 0xd2, 0xc4, 0xe4, 0x0a, 0x66, 0xdc, 0xbb, 0xbd, 0x4d, 0x8e, 0xcb, 0xe1, 0x87, 0x39, 0x3f, 0xb3, 0x4b, 0xf8, 0xe7, 0x18, 0x6f, 0x39, 0xad, 0x01, 0xd4, 0xe8, 0x85, 0x8c, 0x84, 0x96, 0x2c, 0x3a, 0xd4, 0xcf, 0x3c, 0xe5, 0x05, 0xdd, 0xc7, 0xc0, diff --git a/OSX/libsecurity_ssl/Security b/OSX/libsecurity_ssl/Security deleted file mode 120000 index 945c9b46..00000000 --- a/OSX/libsecurity_ssl/Security +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/OSX/libsecurity_ssl/lib/CipherSuite.h b/OSX/libsecurity_ssl/lib/CipherSuite.h index 0a4ac115..a4e737ff 100644 --- a/OSX/libsecurity_ssl/lib/CipherSuite.h +++ b/OSX/libsecurity_ssl/lib/CipherSuite.h @@ -36,7 +36,7 @@ * Defined as enum for debugging, but in the protocol * it is actually exactly two bytes */ -#if TARGET_OS_IPHONE && !TARGET_OS_IOSMAC +#if ((TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST) || (TARGET_OS_OSX && TARGET_CPU_ARM64)) /* 16-bit value on iOS */ typedef uint16_t SSLCipherSuite; #else diff --git a/OSX/libsecurity_ssl/lib/SSLRecordInternal.c b/OSX/libsecurity_ssl/lib/SSLRecordInternal.c index 8da7af2a..28cf1a6b 100644 --- a/OSX/libsecurity_ssl/lib/SSLRecordInternal.c +++ b/OSX/libsecurity_ssl/lib/SSLRecordInternal.c @@ -330,8 +330,8 @@ SSLRecordSetOption(SSLRecordContextRef ref, SSLRecordOption option, bool value) /***** Internal Record Layer APIs *****/ -#include -#define CCRNGSTATE ccDRBGGetRngState() +#include +#define CCRNGSTATE ccrng(NULL) SSLRecordContextRef SSLCreateInternalRecordLayer(SSLContextRef sslCtx) diff --git a/OSX/libsecurity_ssl/lib/SecureTransportPriv.h b/OSX/libsecurity_ssl/lib/SecureTransportPriv.h index f7a6c5f9..34e7521a 100644 --- a/OSX/libsecurity_ssl/lib/SecureTransportPriv.h +++ b/OSX/libsecurity_ssl/lib/SecureTransportPriv.h @@ -516,7 +516,7 @@ OSStatus SSLGetDHEEnabled(SSLContextRef ctx, bool *enabled); OSStatus _SSLSetProtocolVersionEnabled (SSLContextRef context, SSLProtocol protocol, - Boolean enable) API_UNAVAILABLE(iosmac); + Boolean enable) API_UNAVAILABLE(macCatalyst); /* * Obtain a value specified in SSLSetProtocolVersionEnabled. @@ -526,7 +526,7 @@ _SSLSetProtocolVersionEnabled (SSLContextRef context, OSStatus _SSLGetProtocolVersionEnabled(SSLContextRef context, SSLProtocol protocol, - Boolean *enable) API_UNAVAILABLE(iosmac); /* RETURNED */ + Boolean *enable) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Get/set SSL protocol version; optional. Default is kSSLProtocolUnknown, @@ -541,7 +541,7 @@ _SSLGetProtocolVersionEnabled(SSLContextRef context, */ OSStatus _SSLSetProtocolVersion (SSLContextRef context, - SSLProtocol version) API_UNAVAILABLE(iosmac); + SSLProtocol version) API_UNAVAILABLE(macCatalyst); /* * Obtain the protocol version specified in SSLSetProtocolVersion. @@ -555,7 +555,7 @@ _SSLSetProtocolVersion (SSLContextRef context, */ OSStatus _SSLGetProtocolVersion (SSLContextRef context, - SSLProtocol *protocol) API_UNAVAILABLE(iosmac); /* RETURNED */ + SSLProtocol *protocol) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* API REVIEW: The following 15 calls were used to change the behaviour of the trust @@ -573,11 +573,11 @@ _SSLGetProtocolVersion (SSLContextRef context, */ OSStatus _SSLSetEnableCertVerify (SSLContextRef context, - Boolean enableVerify) API_UNAVAILABLE(iosmac); + Boolean enableVerify) API_UNAVAILABLE(macCatalyst); OSStatus _SSLGetEnableCertVerify (SSLContextRef context, - Boolean *enableVerify) API_UNAVAILABLE(iosmac); /* RETURNED */ + Boolean *enableVerify) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Specify the option of ignoring certificates' "expired" times. @@ -587,14 +587,14 @@ _SSLGetEnableCertVerify (SSLContextRef context, */ OSStatus _SSLSetAllowsExpiredCerts (SSLContextRef context, - Boolean allowsExpired) API_UNAVAILABLE(iosmac); + Boolean allowsExpired) API_UNAVAILABLE(macCatalyst); /* * Obtain the current value of an SSLContext's "allowExpiredCerts" flag. */ OSStatus _SSLGetAllowsExpiredCerts (SSLContextRef context, - Boolean *allowsExpired) API_UNAVAILABLE(iosmac); /* RETURNED */ + Boolean *allowsExpired) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Similar to SSLSetAllowsExpiredCerts(), this function allows the @@ -604,11 +604,11 @@ _SSLGetAllowsExpiredCerts (SSLContextRef context, */ OSStatus _SSLSetAllowsExpiredRoots (SSLContextRef context, - Boolean allowsExpired) API_UNAVAILABLE(iosmac); + Boolean allowsExpired) API_UNAVAILABLE(macCatalyst); OSStatus _SSLGetAllowsExpiredRoots (SSLContextRef context, - Boolean *allowsExpired) API_UNAVAILABLE(iosmac); /* RETURNED */ + Boolean *allowsExpired) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Specify option of allowing for an unknown root cert, i.e., one which @@ -627,14 +627,14 @@ _SSLGetAllowsExpiredRoots (SSLContextRef context, */ OSStatus _SSLSetAllowsAnyRoot (SSLContextRef context, - Boolean anyRoot) API_UNAVAILABLE(iosmac); + Boolean anyRoot) API_UNAVAILABLE(macCatalyst); /* * Obtain the current value of an SSLContext's "allow any root" flag. */ OSStatus _SSLGetAllowsAnyRoot (SSLContextRef context, - Boolean *anyRoot) API_UNAVAILABLE(iosmac); /* RETURNED */ + Boolean *anyRoot) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Augment or replace the system's default trusted root certificate set @@ -651,7 +651,7 @@ _SSLGetAllowsAnyRoot (SSLContextRef context, OSStatus _SSLSetTrustedRoots (SSLContextRef context, CFArrayRef trustedRoots, - Boolean replaceExisting) API_UNAVAILABLE(iosmac); + Boolean replaceExisting) API_UNAVAILABLE(macCatalyst); /* * Obtain an array of SecCertificateRefs representing the current @@ -662,7 +662,7 @@ _SSLSetTrustedRoots (SSLContextRef context, */ OSStatus _SSLCopyTrustedRoots (SSLContextRef context, - CFArrayRef *trustedRoots) API_UNAVAILABLE(iosmac); /* RETURNED */ + CFArrayRef *trustedRoots) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Add a SecCertificateRef, or a CFArray of them, to a server's list @@ -680,7 +680,7 @@ _SSLCopyTrustedRoots (SSLContextRef context, OSStatus _SSLSetCertificateAuthorities(SSLContextRef context, CFTypeRef certificateOrArray, - Boolean replaceExisting) API_UNAVAILABLE(iosmac); + Boolean replaceExisting) API_UNAVAILABLE(macCatalyst); /* * Obtain the certificates specified in SSLSetCertificateAuthorities(), @@ -691,7 +691,7 @@ _SSLSetCertificateAuthorities(SSLContextRef context, OSStatus _SSLCopyCertificateAuthorities(SSLContextRef context, - CFArrayRef *certificates) API_UNAVAILABLE(iosmac); /* RETURNED */ + CFArrayRef *certificates) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Request peer certificates. Valid anytime, subsequent to @@ -716,7 +716,7 @@ _SSLCopyCertificateAuthorities(SSLContextRef context, */ OSStatus _SSLCopyPeerCertificates (SSLContextRef context, - CFArrayRef *certs) API_UNAVAILABLE(iosmac); /* RETURNED */ + CFArrayRef *certs) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Specify Diffie-Hellman parameters. Optional; if we are configured to allow @@ -726,7 +726,7 @@ _SSLCopyPeerCertificates (SSLContextRef context, */ OSStatus _SSLSetDiffieHellmanParams (SSLContextRef context, const void *dhParams, - size_t dhParamsLen) API_UNAVAILABLE(iosmac); + size_t dhParamsLen) API_UNAVAILABLE(macCatalyst); /* * Return parameter block specified in SSLSetDiffieHellmanParams. @@ -734,7 +734,7 @@ OSStatus _SSLSetDiffieHellmanParams (SSLContextRef context, */ OSStatus _SSLGetDiffieHellmanParams (SSLContextRef context, const void **dhParams, - size_t *dhParamsLen) API_UNAVAILABLE(iosmac); + size_t *dhParamsLen) API_UNAVAILABLE(macCatalyst); /* * Enable/Disable RSA blinding. This feature thwarts a known timing @@ -743,10 +743,10 @@ OSStatus _SSLGetDiffieHellmanParams (SSLContextRef context, * enabled. */ OSStatus _SSLSetRsaBlinding (SSLContextRef context, - Boolean blinding) API_UNAVAILABLE(iosmac); + Boolean blinding) API_UNAVAILABLE(macCatalyst); OSStatus _SSLGetRsaBlinding (SSLContextRef context, - Boolean *blinding) API_UNAVAILABLE(iosmac); + Boolean *blinding) API_UNAVAILABLE(macCatalyst); /* * Create a new SSL/TLS session context. @@ -754,14 +754,14 @@ OSStatus _SSLGetRsaBlinding (SSLContextRef context, */ OSStatus _SSLNewContext (Boolean isServer, - SSLContextRef *tlsContextPtr) API_UNAVAILABLE(iosmac); /* RETURNED */ + SSLContextRef *tlsContextPtr) API_UNAVAILABLE(macCatalyst); /* RETURNED */ /* * Dispose of an SSLContextRef. This is effectivly a CFRelease. * Deprecated. */ OSStatus -_SSLDisposeContext (SSLContextRef context) API_UNAVAILABLE(iosmac); +_SSLDisposeContext (SSLContextRef context) API_UNAVAILABLE(macCatalyst); /* We redefine the names of all SPIs to avoid collision with unavailable APIs */ #define SSLSetProtocolVersionEnabled _SSLSetProtocolVersionEnabled @@ -807,7 +807,7 @@ _SSLProtocolVersionToWireFormatValue (SSLProtocol protocol); */ OSStatus SSLNewDatagramContext (Boolean isServer, - SSLContextRef *dtlsContextPtr) API_UNAVAILABLE(iosmac); /* RETURNED */ + SSLContextRef *dtlsContextPtr) API_UNAVAILABLE(macCatalyst); /* RETURNED */ diff --git a/OSX/libsecurity_ssl/lib/sslCipherSpecs.c b/OSX/libsecurity_ssl/lib/sslCipherSpecs.c index 47588641..8633fbef 100644 --- a/OSX/libsecurity_ssl/lib/sslCipherSpecs.c +++ b/OSX/libsecurity_ssl/lib/sslCipherSpecs.c @@ -36,7 +36,6 @@ #include #include -#include #include #include diff --git a/OSX/libsecurity_ssl/lib/sslContext.c b/OSX/libsecurity_ssl/lib/sslContext.c index fc1826fe..26e01a85 100644 --- a/OSX/libsecurity_ssl/lib/sslContext.c +++ b/OSX/libsecurity_ssl/lib/sslContext.c @@ -2246,21 +2246,23 @@ SSLCopyPeerTrust( SSLContextRef ctx, SecTrustRef *trust) /* RETURNED */ { - OSStatus status = errSecSuccess; - if (ctx == NULL || trust == NULL) - return errSecParam; + OSStatus status = errSecSuccess; + if (ctx == NULL || trust == NULL) { + return errSecParam; + } - /* Create a SecTrustRef if this was a resumed session and we - didn't have one yet. */ - if (!ctx->peerSecTrust) { - status = sslCreateSecTrust(ctx, &ctx->peerSecTrust); + /* Create a SecTrustRef if this was a resumed session and we + didn't have one yet. */ + if (!ctx->peerSecTrust) { + status = sslCreateSecTrust(ctx, &ctx->peerSecTrust); } - *trust = ctx->peerSecTrust; - if (ctx->peerSecTrust) + *trust = ctx->peerSecTrust; + if (ctx->peerSecTrust) { CFRetain(ctx->peerSecTrust); + } - return status; + return status; } OSStatus SSLGetPeerSecTrust( diff --git a/OSX/libsecurity_ssl/lib/sslCrypto.c b/OSX/libsecurity_ssl/lib/sslCrypto.c index e26fff2f..bd4c071c 100644 --- a/OSX/libsecurity_ssl/lib/sslCrypto.c +++ b/OSX/libsecurity_ssl/lib/sslCrypto.c @@ -32,7 +32,7 @@ #include #include -#include +#include "utilities/simulatecrash_assert.h" #include #include diff --git a/OSX/libsecurity_ssl/lib/sslKeychain.c b/OSX/libsecurity_ssl/lib/sslKeychain.c index 387c34ab..9c4c997c 100644 --- a/OSX/libsecurity_ssl/lib/sslKeychain.c +++ b/OSX/libsecurity_ssl/lib/sslKeychain.c @@ -41,7 +41,7 @@ #include "sslDebug.h" #include "sslKeychain.h" #include -#include +#include "utilities/simulatecrash_assert.h" #include diff --git a/OSX/libsecurity_ssl/lib/sslRecord.c b/OSX/libsecurity_ssl/lib/sslRecord.c index d5ec8974..564b3614 100644 --- a/OSX/libsecurity_ssl/lib/sslRecord.c +++ b/OSX/libsecurity_ssl/lib/sslRecord.c @@ -34,7 +34,6 @@ #include "SSLRecordInternal.h" #include -#include #include diff --git a/OSX/libsecurity_ssl/lib/sslTransport.c b/OSX/libsecurity_ssl/lib/sslTransport.c index c22cf500..a56d10d7 100644 --- a/OSX/libsecurity_ssl/lib/sslTransport.c +++ b/OSX/libsecurity_ssl/lib/sslTransport.c @@ -32,11 +32,12 @@ #include "sslDebug.h" #include "sslCipherSpecs.h" -#include +#include #include #include #include +#import #include #include @@ -476,14 +477,12 @@ SSLHandshake(SSLContext *ctx) #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) -#include "SecADWrapper.h" - static void ad_log_SecureTransport_early_fail(long signature) { CFStringRef key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("com.apple.SecureTransport.early_fail.%ld"), signature); if (key) { - SecADAddValueForScalarKey(key, 1); + SecCoreAnalyticsSendValue(key, 1); CFRelease(key); } } diff --git a/OSX/libsecurity_ssl/lib/tlsCallbacks.c b/OSX/libsecurity_ssl/lib/tlsCallbacks.c index d17e73d4..13a2c8c7 100644 --- a/OSX/libsecurity_ssl/lib/tlsCallbacks.c +++ b/OSX/libsecurity_ssl/lib/tlsCallbacks.c @@ -35,6 +35,8 @@ #include #include +#include "utilities/simulatecrash_assert.h" + static int tls_handshake_write_callback(tls_handshake_ctx_t ctx, const SSLBuffer data, uint8_t content_type) { diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+falsestart.m b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+falsestart.m index 9eaa1ff7..11cd1447 100644 --- a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+falsestart.m +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+falsestart.m @@ -86,6 +86,7 @@ static int SocketConnect(const char *hostName, int port) int sock; int err; struct hostent *ent; + char **h_addr_list = NULL; if (hostName[0] >= '0' && hostName[0] <= '9') { host.s_addr = inet_addr(hostName); @@ -95,11 +96,14 @@ static int SocketConnect(const char *hostName, int port) printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno)); return -2; } - memcpy(&host, ent->h_addr, sizeof(struct in_addr)); + h_addr_list = malloc(sizeof(char *)); + memcpy(h_addr_list, ent->h_addr_list, sizeof(char *)); + memcpy(&host, h_addr_list[0], sizeof(struct in_addr)); } sock = socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr = host; + addr.sin_addr.s_addr = host.s_addr; + free(h_addr_list); addr.sin_port = htons((u_short)port); addr.sin_family = AF_INET; @@ -113,7 +117,6 @@ static int SocketConnect(const char *hostName, int port) /* make non blocking */ fcntl(sock, F_SETFL, O_NONBLOCK); - return sock; } diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+sessionstate.m b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+sessionstate.m index 441ae283..657402e8 100644 --- a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+sessionstate.m +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+sessionstate.m @@ -46,9 +46,8 @@ #define test_printf(x...) -/* extern struct ccrng_state *ccDRBGGetRngState(); */ -#include -#define CCRNGSTATE ccDRBGGetRngState() +#include +#define CCRNGSTATE ccrng(NULL) struct RecQueueItem { STAILQ_ENTRY(RecQueueItem) next; /* link to next queued entry or NULL */ diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+tls12.m b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+tls12.m index adaa8a98..9c20b57c 100644 --- a/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+tls12.m +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+tls12.m @@ -100,6 +100,7 @@ static int SocketConnect(const char *hostName, int port) int sock; int err; struct hostent *ent; + char **h_addr_list = NULL; if (hostName[0] >= '0' && hostName[0] <= '9') { host.s_addr = inet_addr(hostName); @@ -109,11 +110,14 @@ static int SocketConnect(const char *hostName, int port) printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno)); return -2; } - memcpy(&host, ent->h_addr, sizeof(struct in_addr)); + h_addr_list = malloc(sizeof(char *)); + memcpy(h_addr_list, ent->h_addr_list, sizeof(char *)); + memcpy(&host, h_addr_list[0], sizeof(struct in_addr)); } sock = socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr = host; + addr.sin_addr.s_addr = host.s_addr; + free(h_addr_list); addr.sin_port = htons((u_short)port); addr.sin_family = AF_INET; diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan new file mode 100644 index 00000000..9b1a6a27 --- /dev/null +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan @@ -0,0 +1,24 @@ +{ + "configurations" : [ + { + "id" : "5A402836-E1DD-4825-904B-BFAEC12C977B", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Security.xcodeproj", + "identifier" : "3DD1FFAC201FDB1D0086D049", + "name" : "SecureTransportTests_ios" + } + } + ], + "version" : 1 +} diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_macos.xctestplan b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_macos.xctestplan new file mode 100644 index 00000000..ec8f30de --- /dev/null +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_macos.xctestplan @@ -0,0 +1,24 @@ +{ + "configurations" : [ + { + "id" : "C4B1D35D-6AAD-4F4E-A674-0453730B68EB", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Security.xcodeproj", + "identifier" : "3DD1FEF5201C07F30086D049", + "name" : "SecureTransportTests_macos" + } + } + ], + "version" : 1 +} diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_iosTests.plist b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_iosTests.plist index ef1755a2..539e4876 100644 --- a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_iosTests.plist +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_iosTests.plist @@ -13,7 +13,14 @@ /AppleInternal/XCTests/com.apple.security/ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest Self SecureTransport_ios_tests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + Self + SecureTransport_ios_tests.xctest diff --git a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_macosTests.plist b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_macosTests.plist index 64a927ab..266c4f56 100644 --- a/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_macosTests.plist +++ b/OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransport_macosTests.plist @@ -13,7 +13,14 @@ /AppleInternal/XCTests/com.apple.security/ Command - BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest Self SecureTransport_macos_tests.xctest + BATS_XCTEST_CMD + -NSTreatUnknownArgumentsAsOpen + NO + -ApplePersistenceIgnoreState + YES + -XCTest + Self + SecureTransport_macos_tests.xctest diff --git a/OSX/libsecurity_ssl/regressions/ssl-50-server.c b/OSX/libsecurity_ssl/regressions/ssl-50-server.c index b20a9b02..bc766e70 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-50-server.c +++ b/OSX/libsecurity_ssl/regressions/ssl-50-server.c @@ -185,7 +185,7 @@ ssl_test_handle_create(int comm, CFArrayRef certs) static void *securetransport_ssl_thread(void *arg) { OSStatus ortn; - int sock = (int)arg; + int sock = *((int*)arg); int socket = accept(sock, NULL, NULL); @@ -244,7 +244,7 @@ tests(void) } //fprintf(stderr, "session_id: %d\n", session_id); - pthread_create(&server_thread, NULL, securetransport_ssl_thread, (void*)socket); + pthread_create(&server_thread, NULL, securetransport_ssl_thread, (void*)&socket); system("/usr/bin/openssl s_client -msg -debug -connect localhost:4443"); diff --git a/OSX/libsecurity_ssl/regressions/ssl-51-state.c b/OSX/libsecurity_ssl/regressions/ssl-51-state.c index 91a48385..f5840500 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-51-state.c +++ b/OSX/libsecurity_ssl/regressions/ssl-51-state.c @@ -46,9 +46,8 @@ #define test_printf(x...) -/* extern struct ccrng_state *ccDRBGGetRngState(); */ -#include -#define CCRNGSTATE ccDRBGGetRngState() +#include +#define CCRNGSTATE ccrng(NULL) struct RecQueueItem { STAILQ_ENTRY(RecQueueItem) next; /* link to next queued entry or NULL */ diff --git a/OSX/libsecurity_ssl/security_ssl b/OSX/libsecurity_ssl/security_ssl deleted file mode 120000 index 945c9b46..00000000 --- a/OSX/libsecurity_ssl/security_ssl +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/OSX/libsecurity_transform/lib/SecDecodeTransform.h b/OSX/libsecurity_transform/lib/SecDecodeTransform.h index 28e10484..1327a2e8 100644 --- a/OSX/libsecurity_transform/lib/SecDecodeTransform.h +++ b/OSX/libsecurity_transform/lib/SecDecodeTransform.h @@ -24,7 +24,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include "SecEncodeTransform.h" +#include #ifdef __cplusplus extern "C" { diff --git a/OSX/libsecurity_transform/lib/SecDigestTransform.h b/OSX/libsecurity_transform/lib/SecDigestTransform.h index d61f6e2d..00e0a9e1 100644 --- a/OSX/libsecurity_transform/lib/SecDigestTransform.h +++ b/OSX/libsecurity_transform/lib/SecDigestTransform.h @@ -25,7 +25,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include "SecTransform.h" +#include #ifdef __cplusplus extern "C" { diff --git a/OSX/libsecurity_transform/lib/SecEncodeTransform.h b/OSX/libsecurity_transform/lib/SecEncodeTransform.h index 499b242f..169bbf79 100644 --- a/OSX/libsecurity_transform/lib/SecEncodeTransform.h +++ b/OSX/libsecurity_transform/lib/SecEncodeTransform.h @@ -24,7 +24,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include "SecTransform.h" +#include #ifdef __cplusplus extern "C" { diff --git a/OSX/libsecurity_transform/lib/SecEncryptTransform.h b/OSX/libsecurity_transform/lib/SecEncryptTransform.h index 0a744fcf..541d1ce1 100644 --- a/OSX/libsecurity_transform/lib/SecEncryptTransform.h +++ b/OSX/libsecurity_transform/lib/SecEncryptTransform.h @@ -36,7 +36,7 @@ #include #include -#include "SecTransform.h" +#include #ifdef __cplusplus extern "C" { diff --git a/OSX/libsecurity_transform/lib/SecSignVerifyTransform.c b/OSX/libsecurity_transform/lib/SecSignVerifyTransform.c index a4665279..00f5cbed 100644 --- a/OSX/libsecurity_transform/lib/SecSignVerifyTransform.c +++ b/OSX/libsecurity_transform/lib/SecSignVerifyTransform.c @@ -27,7 +27,9 @@ #include "Utilities.h" #include #include "misc.h" -#include // for dyld_get_program_sdk_version +#include + +#include "simulatecrash_assert.h" const static CFStringRef SignName = CFSTR("com.apple.security.Sign"), VerifyName = CFSTR("com.apple.security.Verify"); const CFStringRef __nonnull kSecKeyAttributeName = CFSTR("KEY"), kSecSignatureAttributeName = CFSTR("Signature"), kSecInputIsAttributeName = CFSTR("InputIs"); @@ -410,8 +412,8 @@ static SecTransformInstanceBlock SignTransform(CFStringRef name, OSStatus rc = SecKeyGetCSSMKey(key, &cssm_key); SEC_FAIL(rc); - if (((!cssm_key->KeyHeader.KeyUsage) & CSSM_KEYUSE_SIGN) // Keep the previous test to be compatible with existing apps - || ((dyld_get_program_sdk_version() >= DYLD_MACOSX_VERSION_10_13) // Better check for newly compiled apps + if (((!cssm_key->KeyHeader.KeyUsage) & CSSM_KEYUSE_SIGN) + || (dyld_program_sdk_at_least(dyld_platform_version_macOS_10_13) // Keep the previous test to be compatible with existing apps && !(cssm_key->KeyHeader.KeyUsage & (CSSM_KEYUSE_SIGN|CSSM_KEYUSE_ANY)))) { key = NULL; // This key cannot sign! @@ -539,8 +541,8 @@ static SecTransformInstanceBlock VerifyTransform(CFStringRef name, rc = SecKeyGetCSSMKey((SecKeyRef)value, &cssm_key); SEC_FAIL(rc); - if (((!cssm_key->KeyHeader.KeyUsage) & CSSM_KEYUSE_SIGN) // Keep the previous test to be compatible with existing apps - || ((dyld_get_program_sdk_version() >= DYLD_MACOSX_VERSION_10_13) // Better check for newly compiled apps + if (((!cssm_key->KeyHeader.KeyUsage) & CSSM_KEYUSE_SIGN) + || (dyld_program_sdk_at_least(dyld_platform_version_macOS_10_13) // Keep the previous test to be compatible with existing apps && !(cssm_key->KeyHeader.KeyUsage & (CSSM_KEYUSE_VERIFY|CSSM_KEYUSE_ANY)))) { key = NULL; // This key cannot verify! diff --git a/OSX/libsecurity_transform/lib/SecSignVerifyTransform.h b/OSX/libsecurity_transform/lib/SecSignVerifyTransform.h index 0753aad0..073ff69e 100644 --- a/OSX/libsecurity_transform/lib/SecSignVerifyTransform.h +++ b/OSX/libsecurity_transform/lib/SecSignVerifyTransform.h @@ -25,7 +25,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include "SecTransform.h" +#include #include diff --git a/OSX/libsecurity_transform/lib/Transform.cpp b/OSX/libsecurity_transform/lib/Transform.cpp index a9d1fc7c..6a1e6406 100644 --- a/OSX/libsecurity_transform/lib/Transform.cpp +++ b/OSX/libsecurity_transform/lib/Transform.cpp @@ -156,9 +156,11 @@ SecTransformAttributeRef Transform::getAH(SecTransformStringOrAttributeRef attri SecTransformAttributeRef search_for = pthread_getspecific(ah_search_key_slot); if (!search_for) { - search_for = makeAH((transform_attribute*)malloc(sizeof(transform_attribute))); + transform_attribute* ta = (transform_attribute*)malloc(sizeof(transform_attribute)); + search_for = makeAH(ta); if (!search_for) { + free(ta); return NULL; } @@ -185,12 +187,14 @@ SecTransformAttributeRef Transform::getAH(SecTransformStringOrAttributeRef attri ah = makeAH(ta); if (!ah) { + free(ta); return NULL; } ta->name = CFStringCreateCopy(NULL, label); if (!ta->name) { + CFRelease(ah); free(ta); return NULL; } @@ -200,6 +204,7 @@ SecTransformAttributeRef Transform::getAH(SecTransformStringOrAttributeRef attri { CFReleaseNull(ta->name); free(ta); + CFRelease(ah); return NULL; } @@ -265,7 +270,7 @@ bool Transform::HasNoOutboundConnections() { // make an array big enough to hold all of the attributes CFIndex numAttributes = CFSetGetCount(mAttributes); - transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute)); + transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute*)); if (attributes == NULL) { // No more memory, we assume it's orphaned @@ -296,7 +301,7 @@ bool Transform::HasNoInboundConnections() { // make an array big enough to hold all of the attributes CFIndex numAttributes = CFSetGetCount(mAttributes); - transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute)); + transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute*)); if (attributes == NULL) { // No more memory, we assume it's orphaned @@ -1622,7 +1627,7 @@ CFDictionaryRef Transform::GetAHDictForSaveState(SecTransformStringOrAttributeRe CFDictionaryRef Transform::CopyState() { CFIndex i, j, cnt = CFSetGetCount(mAttributes); - transform_attribute **attrs = (transform_attribute**)malloc(cnt*sizeof(transform_attribute)); + transform_attribute **attrs = (transform_attribute**)malloc(cnt*sizeof(transform_attribute*)); CFStringRef *names = (CFStringRef*)malloc(cnt*sizeof(CFStringRef)); CFDictionaryRef *values = (CFDictionaryRef*)malloc(sizeof(CFDictionaryRef) * cnt); @@ -1819,7 +1824,7 @@ CFErrorRef Transform::ProcessExternalize(CFMutableArrayRef transforms, CFMutable // now walk the attribute list CFIndex numAttributes = CFSetGetCount(mAttributes); - transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute)); + transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute*)); if (attributes == NULL) { return GetNoMemoryErrorAndRetain(); diff --git a/OSX/libsecurity_transform/misc/speed-test.mm b/OSX/libsecurity_transform/misc/speed-test.mm index b33aea64..1e8e9cff 100644 --- a/OSX/libsecurity_transform/misc/speed-test.mm +++ b/OSX/libsecurity_transform/misc/speed-test.mm @@ -26,7 +26,7 @@ #include "SecTransform.h" #include "SecExternalSourceTransform.h" #include "SecNullTransform.h" -#include +#include @implementation speed_test diff --git a/OSX/libsecurity_translocate/lib/SecTranslocate.cpp b/OSX/libsecurity_translocate/lib/SecTranslocate.cpp index a86aa4c8..64a48631 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocate.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocate.cpp @@ -255,7 +255,7 @@ CFURLRef __nullable SecTranslocateCreateSecureDirectoryForURL (CFURLRef pathToTr { string sourcePath = cfString(pathToTranslocate); // returns an absolute path - Security::SecTranslocate::TranslocationPath toTranslocatePath(sourcePath); + Security::SecTranslocate::TranslocationPath toTranslocatePath(sourcePath, Security::SecTranslocate::TranslocationOptions::Default); if(!toTranslocatePath.shouldTranslocate()) { @@ -337,6 +337,49 @@ end: return result; } +CFURLRef __nullable SecTranslocateCreateGeneric (CFURLRef pathToTranslocate, + CFURLRef destinationPath, + CFErrorRef* __nullable error) +{ + CFURLRef result = NULL; + CFIndex errorCode = 0; + + try + { + string sourcePath = cfString(pathToTranslocate); + Security::SecTranslocate::GenericTranslocationPath path{sourcePath, Security::SecTranslocate::TranslocationOptions::Unveil}; + + string dpath = cfString(destinationPath); + string out_path = Security::SecTranslocate::getTranslocator()->translocatePathForUser(path, dpath); + + if(!out_path.empty()) + { + result = makeCFURL(out_path, true); + } + else + { + Syslog::error("SecTranslocateCreateGeneric: No mountpoint and no prior exception. Shouldn't be here"); + UnixError::throwMe(EINVAL); + } + + } + catch (Security::UnixError err) + { + errorCode = err.unixError(); + } + catch(...) + { + Syslog::critical("SecTranslocateCreateGeneric: uncaught exception during mountpoint creation"); + errorCode = EACCES; + } + + if (error && errorCode) + { + *error = SecTranslocateMakePosixError(errorCode); + } + return result; +} + /* Decide whether we need to translocate */ Boolean SecTranslocateURLShouldRunTranslocated(CFURLRef path, bool* shouldTranslocate, CFErrorRef* __nullable error) { @@ -352,7 +395,7 @@ Boolean SecTranslocateURLShouldRunTranslocated(CFURLRef path, bool* shouldTransl try { string pathToCheck = cfString(path); - Security::SecTranslocate::TranslocationPath tPath(pathToCheck); + Security::SecTranslocate::TranslocationPath tPath(pathToCheck, Security::SecTranslocate::TranslocationOptions::Default); *shouldTranslocate = tPath.shouldTranslocate(); result = true; } diff --git a/OSX/libsecurity_translocate/lib/SecTranslocate.h b/OSX/libsecurity_translocate/lib/SecTranslocate.h index c01e4127..ce31fb1f 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocate.h +++ b/OSX/libsecurity_translocate/lib/SecTranslocate.h @@ -98,6 +98,33 @@ __OSX_AVAILABLE(10.12); CFURLRef __nullable SecTranslocateCreateSecureDirectoryForURL (CFURLRef pathToTranslocate, CFURLRef __nullable destinationPath, CFErrorRef* __nullable error) __OSX_AVAILABLE(10.12); +/*! + @function SecTranslocateCreateGeneric + + @abstract Create a CFURL pointing to a translocated location from which to access the directory specified by pathToTranslocate. + + @param pathToTranslocate URL of the directory to be accessed from a translocated location. + @param destinationPath URL where the directory of interest should be translocated + @param error On error will be populated with an error object describing the failure (a posix domain error such as EINVAL) + + @result A CFURL pointing to the translocated location of the directory. + + @discussion + Calls to this function, and the others dealng with creation / deletion of mounts are serialized to ensure only one call to either + is operating at a time. + Translocations will be created in specified destinationPath + + pathToTranslocated is expected to be a folder + + If pathToTranslocate is in a quarantined mountpoint, the quarantine attributes will be propagated to the + translocated location. + + pathToTranslocate will cause a failure if it doesn't resolve to a path that exists, or it exceeds MAXPATHLEN + This function can be run from any process. If the process is not the xpc server, then an xpc call is made. + */ +CFURLRef __nullable SecTranslocateCreateGeneric (CFURLRef pathToTranslocate, CFURLRef destinationPath, CFErrorRef* __nullable error) +__OSX_AVAILABLE(10.16); + /*! @function SecTranslocateAppLaunchCheckin diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp index 99095aa3..3f15bcab 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp @@ -91,15 +91,12 @@ TranslocatorClient::~TranslocatorClient() dispatch_release(syncQ); } -string TranslocatorClient::translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) +string TranslocatorClient::requestTranslocation(const string& source, + const string& destination, + const TranslocationOptions flags) { string outPath; - - if (!originalPath.shouldTranslocate()) - { - return originalPath.getOriginalRealPath(); //return original path if we shouldn't translocate - } - + //We should run translocated, so get a translocation point xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0); @@ -111,10 +108,11 @@ string TranslocatorClient::translocatePathForUser(const TranslocationPath &origi xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageFunction, kSecTranslocateXPCFuncCreate); /* send the original real path rather than the calculated path to let the server do all the work */ - xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageOriginalPath, originalPath.getOriginalRealPath().c_str()); - if(!destPath.empty()) + xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageOriginalPath, source.c_str()); + xpc_dictionary_set_int64(msg, kSecTranslocateXPCMessageOptions, static_cast(flags)); + if(!destination.empty()) { - xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageDestinationPath, destPath.c_str()); + xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageDestinationPath, destination.c_str()); } xpc_object_t reply = xpc_connection_send_message_with_reply_sync(service, msg); @@ -166,6 +164,26 @@ string TranslocatorClient::translocatePathForUser(const TranslocationPath &origi return outPath; } +string TranslocatorClient::translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) +{ + if (!originalPath.shouldTranslocate()) + { + return originalPath.getOriginalRealPath(); //return original path if we shouldn't translocate + } + + return requestTranslocation(originalPath.getOriginalRealPath(), destPath, TranslocationOptions::Default); +} + +string TranslocatorClient::translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath) +{ + if (!originalPath.shouldTranslocate()) + { + return originalPath.getOriginalRealPath(); //return original path if we shouldn't translocate + } + + return requestTranslocation(originalPath.getOriginalRealPath(), destPath, TranslocationOptions::Generic); +} + void TranslocatorClient::appLaunchCheckin(pid_t pid) { xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0); diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp index bff27ef0..240acf1c 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp @@ -47,12 +47,16 @@ public: ~TranslocatorClient(); string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) override; + string translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath) override; bool destroyTranslocatedPathForUser(const string &translocatedPath) override; void appLaunchCheckin(pid_t pid) override; private: TranslocatorClient() = delete; TranslocatorClient(const TranslocatorClient &that) = delete; + + string requestTranslocation(const string& source, const string& destination, const TranslocationOptions flags); + dispatch_queue_t syncQ; xpc_connection_t service; }; diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateEnumUtils.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateEnumUtils.hpp new file mode 100644 index 00000000..fba90b9f --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateEnumUtils.hpp @@ -0,0 +1,40 @@ +// +// SecTranslocateEnumUtils.h +// Security +// +// + +#ifndef SecTranslocateEnumUtils_h +#define SecTranslocateEnumUtils_h + +#include + +template +Enum operator |(Enum lhs, Enum rhs) +{ + static_assert(std::is_enum::value, + "template parameter is not an enum type"); + + using underlying = typename std::underlying_type::type; + + return static_cast ( + static_cast(lhs) | + static_cast(rhs) + ); +} + +template +Enum operator &(Enum lhs, Enum rhs) +{ + static_assert(std::is_enum::value, + "template parameter is not an enum type"); + + using underlying = typename std::underlying_type::type; + + return static_cast ( + static_cast(lhs) & + static_cast(rhs) + ); +} + +#endif /* SecTranslocateEnumUtils_h */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp index 8ed15544..7c187b0e 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp @@ -45,6 +45,7 @@ class Translocator public: virtual ~Translocator() {}; virtual string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) = 0; + virtual string translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath) = 0; virtual bool destroyTranslocatedPathForUser(const string &translocatedPath) = 0; virtual void appLaunchCheckin(pid_t pid) = 0; }; diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp index a515ba69..8d93fe2c 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp @@ -103,6 +103,28 @@ string TranslocatorServer::translocatePathForUser(const TranslocationPath &origi return newPath; } +string TranslocatorServer::translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath) +{ + __block string newPath; + __block exception_ptr exception(0); + + dispatch_sync(syncQ, ^{ + try + { + newPath = Security::SecTranslocate::translocatePathForUser(originalPath,destPath); + } + catch (...) + { + exception = current_exception(); + } + }); + if (exception) + { + rethrow_exception(exception); + } + return newPath; +} + // This is intended for use by the host process of the server if necessary // Destroy the translocation mount at translocatedPath if allowed bool TranslocatorServer::destroyTranslocatedPathForUser(const string &translocatedPath) diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp index b8cf62ec..b0044314 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp @@ -52,6 +52,7 @@ public: ~TranslocatorServer(); string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) override; + string translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath) override; bool destroyTranslocatedPathForUser(const string &translocatedPath) override; void appLaunchCheckin(pid_t pid) override; diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp index 9c1595ae..b217d343 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,12 @@ #include "SecTranslocateShared.hpp" #include "SecTranslocateUtilities.hpp" +#include "SecTranslocateEnumUtils.hpp" + +#define NULLM_UNVEIL 0x1ULL << 2 +struct null_mount_conf { + uint64_t flags; +}; namespace Security { @@ -62,6 +69,7 @@ const char* kSecTranslocateXPCFuncCheckIn = "check-in"; const char* kSecTranslocateXPCMessageFunction = "function"; const char* kSecTranslocateXPCMessageOriginalPath = "original"; const char* kSecTranslocateXPCMessageDestinationPath = "dest"; +const char* kSecTranslocateXPCMessageOptions= "opts"; const char* kSecTranslocateXPCMessagePid = "pid"; /*XPC message reply keys */ @@ -83,7 +91,7 @@ static void cleanupTranslocationDirForUser(const string &userDir); static int removeMountPoint(const string &mountpoint, bool force = false); /* calculate whether a translocation should occur and where from */ -TranslocationPath::TranslocationPath(string originalPath) +TranslocationPath::TranslocationPath(string originalPath, TranslocationOptions opts) { /* To support testing of translocation the policy is as follows: @@ -114,7 +122,8 @@ TranslocationPath::TranslocationPath(string originalPath) */ ExtendedAutoFileDesc fd(originalPath); - + + options = opts; should = false; realOriginalPath = fd.getRealPath(); @@ -252,8 +261,25 @@ ExtendedAutoFileDesc TranslocationPath::findOuterMostCodeBundleForFD(ExtendedAut return ExtendedAutoFileDesc(joinPathUpTo(path, lastGoodIndex)); } +GenericTranslocationPath::GenericTranslocationPath(const string& path, TranslocationOptions opts) { + ExtendedAutoFileDesc fd(path); + realOriginalPath = fd.getRealPath(); + should = false; + options = opts; + + /* don't translocate if it already is */ + /* Nullfs can't translocate other mount's roots so abort if its a mountpoint */ + if(fd.isFileSystemType(NULLFS_FSTYPE) || fd.isMountPoint()) { + return; + } + + componentNameToTranslocate = splitPath(path).back(); + + should = true; +} + /* Given an fd to a translocated file, build the path to the original file - Throws if the fd isn't in a nullfs mount for the calling user. */ + Throws if the fd isn't in a nullfs mount. */ string getOriginalPath(const ExtendedAutoFileDesc& fd, bool* isDir) { if (!fd.isFileSystemType(NULLFS_FSTYPE) || @@ -268,16 +294,6 @@ string getOriginalPath(const ExtendedAutoFileDesc& fd, bool* isDir) UnixError::throwMe(EINVAL); } - string translocationBaseDir = translocationDirForUser(); - - if(!fd.isInPrefixDir(translocationBaseDir)) - { - Syslog::error("SecTranslocate::getOriginal path called with path (%s) that doesn't belong to user (%d)", - fd.getRealPath().c_str(), - getuid()); - UnixError::throwMe(EPERM); - } - *isDir = fd.isA(S_IFDIR); vector mountFromPath = splitPath(fd.getMountFromPath()); @@ -456,6 +472,61 @@ static vector getMountTableSnapshot() return mntInfo; } +static bool pathExistsInMountTable(const GenericTranslocationPath& path, const string& mountpoint) +{ + vector mntbuf = getMountTableSnapshot(); + + /* Save the untranslocated inode number*/ + ExtendedAutoFileDesc::UnixStat untranslocatedStat; + + if (stat(path.getOriginalRealPath().c_str(), &untranslocatedStat)) + { + errno_t err = errno; + Syslog::warning("SecTranslocate: failed to stat original path (%d): %s", + err, + path.getOriginalRealPath().c_str()); + UnixError::throwMe(err); + } + + for (auto &i : mntbuf) + { + string mountOnName = i.f_mntonname; + + if (path.getOriginalRealPath() == i.f_mntfromname && //mount is for the requested path + mountpoint == mountOnName && //mount to is the same + strcmp(i.f_fstypename, NULLFS_FSTYPE) == 0 // mount is a nullfs mount + ) + { + /* + find the inode number for mountOnName + */ + string pathToTranslocatedApp = mountOnName+"/d/"+path.getComponentNameToTranslocate(); + + ExtendedAutoFileDesc::UnixStat oldTranslocatedStat; + + if (stat(pathToTranslocatedApp.c_str(), &oldTranslocatedStat)) + { + /* We should have access to this path and it should be real so complain if thats not true. */ + errno_t err = errno; + Syslog::warning("SecTranslocate: expected app not inside mountpoint: %s (error: %d)", pathToTranslocatedApp.c_str(), err); + UnixError::throwMe(err); + } + + if(untranslocatedStat.st_ino != oldTranslocatedStat.st_ino) + { + /* We have two Apps with the same name at the same path but different inodes. This means that the + translocated path is broken and should be removed */ + destroyTranslocatedPathForUser(pathToTranslocatedApp); + continue; + } + + return true; + } + } + + return false; +} + /* Given the directory where app translocations go for this user, the path to the app to be translocated and an optional destination mountpoint path. Check the mount table to see if a mount point already user, for this app. If a destMountPoint is provided, make sure it is for this user, and that @@ -721,13 +792,10 @@ static void setMountPointQuarantineIfNecessary(const string &mountPoint, const s } } -/* Given the path to a new mountpoint and the original path to translocate, calculate the path - to the desired app in the new mountpoint, and sanity check that calculation */ -static string newAppPath (const string &mountPoint, const TranslocationPath &originalPath) +static string newAppPathFrom (const string &mountPoint, const string &outPath) { string midPath = mountPoint+"/d"; - string outPath = originalPath.getTranslocatedPathToOriginalPath(midPath+"/"+originalPath.getComponentNameToTranslocate()); - + /* ExtendedAutoFileDesc will throw if one of these doesn't exist or isn't accessible */ ExtendedAutoFileDesc mountFd(mountPoint); ExtendedAutoFileDesc midFd(midPath); @@ -768,6 +836,34 @@ static string newAppPath (const string &mountPoint, const TranslocationPath &ori return outFd.getRealPath(); } + +static string newAppPath (const string &mountPoint, const GenericTranslocationPath &originalPath) +{ + string outPath = mountPoint+"/d/"+originalPath.getComponentNameToTranslocate(); + return newAppPathFrom(mountPoint, outPath); +} + +/* Given the path to a new mountpoint and the original path to translocate, calculate the path +to the desired app in the new mountpoint, and sanity check that calculation */ +static string newAppPath (const string &mountPoint, const TranslocationPath &originalPath) +{ + string outPath = originalPath.getTranslocatedPathToOriginalPath(mountPoint+"/d/"+originalPath.getComponentNameToTranslocate()); + return newAppPathFrom(mountPoint, outPath); +} + +static std::vector getMountData(const string& toTranslocate, TranslocationOptions opts) { + std::vector data; + data.reserve(sizeof(null_mount_conf) + toTranslocate.size() + 1); + null_mount_conf conf = {0}; + if ((opts & TranslocationOptions::Unveil) == TranslocationOptions::Unveil) { + conf.flags = NULLM_UNVEIL; + } + data.insert(data.end(), reinterpret_cast(&conf), reinterpret_cast(&conf + 1)); + data.insert(data.end(), toTranslocate.c_str(), toTranslocate.c_str() + toTranslocate.size()); + data.push_back('\0'); + return data; +} + /* Create an app translocation point given the original path and an optional destination path. note the destination path can only be an outermost path (where the translocation would happen) and not a path to nested code synchronize the process on the dispatch queue. */ @@ -809,7 +905,8 @@ string translocatePathForUser(const TranslocationPath &originalPath, const strin mountpoint = destMountPoint; } - UnixError::check(mount(NULLFS_FSTYPE, mountpoint.c_str(), MNT_RDONLY, (void*)toTranslocate.c_str())); + auto mount_data = getMountData(toTranslocate, originalPath.getOptions()); + UnixError::check(mount(NULLFS_FSTYPE, mountpoint.c_str(), MNT_RDONLY, mount_data.data())); setMountPointQuarantineIfNecessary(mountpoint, toTranslocate); //throws @@ -854,6 +951,62 @@ string translocatePathForUser(const TranslocationPath &originalPath, const strin return newPath; } +string translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath) +{ + string newPath; + exception_ptr exception(0); + + string mountpoint = destPath; + bool owned = false; + try + { + const string &toTranslocate = originalPath.getOriginalRealPath(); + if (pathExistsInMountTable(originalPath, destPath)) + { + /* A mount point exists already so bail*/ + newPath = newAppPath(mountpoint, originalPath); + return newPath; /* exit the block */ + } + + AutoFileDesc fd(getFDForDirectory(mountpoint, &owned)); //throws, makes the directory if it doesn't exist + + validateMountpoint(mountpoint, owned); //throws + + auto mount_data = getMountData(toTranslocate, originalPath.getOptions()); + UnixError::check(mount(NULLFS_FSTYPE, mountpoint.c_str(), MNT_RDONLY, mount_data.data())); + + setMountPointQuarantineIfNecessary(mountpoint, toTranslocate); //throws + + newPath = newAppPath(mountpoint, originalPath); //throws + + // log that we created a new mountpoint (we don't log when we are re-using) + Syslog::warning("SecTranslocateCreateGeneric: created %s", + newPath.c_str()); + } + catch (...) + { + exception = current_exception(); + + if (!mountpoint.empty()) + { + if (owned) + { + /* try to unmount/delete (best effort)*/ + unmount(mountpoint.c_str(), 0); + rmdir(mountpoint.c_str()); + } + } + } + + /* rethrow outside the dispatch block */ + if (exception) + { + rethrow_exception(exception); + } + + return newPath; +} + /* Loop through the directory in the specified user directory and delete any that aren't mountpoints */ static void cleanupTranslocationDirForUser(const string &userDir) { @@ -929,11 +1082,10 @@ bool destroyTranslocatedPathForUser(const string &translocatedPath) bool result = false; int error = 0; /* steps - 1. verify the translocatedPath is for the user - 2. verify it is a nullfs mountpoint (with app path) - 3. unmount it - 4. delete it - 5. loop through all the other directories in the app translation directory looking for directories not mounted on and delete them. + 1. verify it is a nullfs mountpoint (with app path) + 2. unmount it + 3. delete it + 4. loop through all the other directories in the app translation directory looking for directories not mounted on and delete them. */ string baseDirForUser = translocationDirForUser(); // throws @@ -947,7 +1099,7 @@ bool destroyTranslocatedPathForUser(const string &translocatedPath) To support unmount when nested apps end, just make sure that the requested path is on a translocation point for this user, not that they asked for a translocation point to be removed. */ - shouldUnmount = fd.isInPrefixDir(baseDirForUser) && fd.isFileSystemType(NULLFS_FSTYPE); + shouldUnmount = fd.isFileSystemType(NULLFS_FSTYPE); } if (shouldUnmount) diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp index a55961c5..653eb14d 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp @@ -48,22 +48,47 @@ extern const char* kSecTranslocateXPCFuncCheckIn; extern const char* kSecTranslocateXPCMessageFunction; extern const char* kSecTranslocateXPCMessageOriginalPath; extern const char* kSecTranslocateXPCMessageDestinationPath; +extern const char* kSecTranslocateXPCMessageOptions; extern const char* kSecTranslocateXPCMessagePid; /*XPC message reply keys */ extern const char* kSecTranslocateXPCReplyError; extern const char* kSecTranslocateXPCReplySecurePath; +enum class TranslocationOptions : int64_t { + Default = 0, + Generic = 1 << 0, + Unveil = 1 << 1 +}; + +class GenericTranslocationPath +{ +public: + GenericTranslocationPath(const string& path, TranslocationOptions opts); + inline bool shouldTranslocate() const { return should; }; + inline const string & getOriginalRealPath() const { return realOriginalPath; }; + inline const string & getComponentNameToTranslocate() const { return componentNameToTranslocate; }; + inline TranslocationOptions getOptions() const { return options; }; +private: + GenericTranslocationPath() = delete; + + bool should; + string realOriginalPath; + string componentNameToTranslocate; + TranslocationOptions options; +}; + class TranslocationPath { public: - TranslocationPath(string originalPath); + TranslocationPath(string originalPath, TranslocationOptions opts); inline bool shouldTranslocate() const { return should; }; inline const string & getOriginalRealPath() const { return realOriginalPath; }; inline const string & getPathToTranslocate() const { return pathToTranslocate; }; inline const string & getPathInsideTranslocation() const { return pathInsideTranslocationPoint; }; inline const string & getComponentNameToTranslocate() const { return componentNameToTranslocate; }; string getTranslocatedPathToOriginalPath(const string &translocationPoint) const; + inline TranslocationOptions getOptions() const { return options; }; private: TranslocationPath() = delete; @@ -72,6 +97,7 @@ private: string pathToTranslocate; string componentNameToTranslocate; //the final component of pathToTranslocate string pathInsideTranslocationPoint; + TranslocationOptions options; ExtendedAutoFileDesc findOuterMostCodeBundleForFD(ExtendedAutoFileDesc &fd); }; @@ -81,6 +107,7 @@ string getOriginalPath(const ExtendedAutoFileDesc& fd, bool* isDir); //throws // For methods below, the caller is responsible for ensuring that only one thread is // accessing/modifying the mount table at a time string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath); //throws +string translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath); //throws bool destroyTranslocatedPathForUser(const string &translocatedPath); //throws bool destroyTranslocatedPathsForUserOnVolume(const string &volumePath = ""); //throws void tryToDestroyUnusedTranslocationMounts(); @@ -88,4 +115,5 @@ void tryToDestroyUnusedTranslocationMounts(); } //namespace SecTranslocate }// namespace Security + #endif /* SecTranslocateShared_hpp */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp index e2503e2d..71c81655 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp @@ -91,7 +91,7 @@ void* checkedDlsym(void* handle, const char* symbol); //Path parsing functions vector splitPath(const string &path); string joinPath(vector& path); - string joinPathUpTo(vector &path, size_t index); +string joinPathUpTo(vector &path, size_t index); //File system utlities string getRealPath(const string &path); diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp index 769f72ac..f7c84c6f 100644 --- a/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp +++ b/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp @@ -34,6 +34,7 @@ #include "SecTranslocateXPCServer.hpp" #include "SecTranslocateUtilities.hpp" #include "SecTranslocateShared.hpp" +#include "SecTranslocateEnumUtils.hpp" namespace Security { namespace SecTranslocate { @@ -42,24 +43,36 @@ static void doCreate(xpc_object_t msg, xpc_object_t reply) { const char* original = xpc_dictionary_get_string(msg, kSecTranslocateXPCMessageOriginalPath); const char* dest = xpc_dictionary_get_string(msg, kSecTranslocateXPCMessageDestinationPath); + const int64_t opts = xpc_dictionary_get_int64(msg, kSecTranslocateXPCMessageOptions); string originalPath = original ? original : ""; string destPath = dest ? dest: ""; + TranslocationOptions options = static_cast(opts); - if( originalPath.empty()) + if (originalPath.empty()) { Syslog::error("SecTranslocate: XPCServer, doCreate no path to translocate"); UnixError::throwMe(EINVAL); } - TranslocationPath tPath(originalPath); + string result = originalPath; + + if ((options & TranslocationOptions::Generic) == TranslocationOptions::Generic) { + GenericTranslocationPath tPath(originalPath, TranslocationOptions::Unveil); - string result = tPath.getOriginalRealPath(); + if(tPath.shouldTranslocate()) + { + result = Security::SecTranslocate::translocatePathForUser(tPath, destPath); + } + } else { + TranslocationPath tPath(originalPath, TranslocationOptions::Default); - if(tPath.shouldTranslocate()) - { - result = Security::SecTranslocate::translocatePathForUser(tPath, destPath); + if(tPath.shouldTranslocate()) + { + result = Security::SecTranslocate::translocatePathForUser(tPath, destPath); + } } + xpc_dictionary_set_string(reply, kSecTranslocateXPCReplySecurePath, result.c_str()); } diff --git a/OSX/libsecurity_utilities/lib/alloc.cpp b/OSX/libsecurity_utilities/lib/alloc.cpp index 5d297087..fed1a610 100644 --- a/OSX/libsecurity_utilities/lib/alloc.cpp +++ b/OSX/libsecurity_utilities/lib/alloc.cpp @@ -46,7 +46,7 @@ extern "C" size_t malloc_size(void *); // // Features of the Allocator root class // -bool Allocator::operator == (const Allocator &alloc) const throw() +bool Allocator::operator == (const Allocator &alloc) const _NOEXCEPT { return this == &alloc; } @@ -63,14 +63,14 @@ Allocator::~Allocator() // pool). This is trivially achieved here by using singletons. // struct DefaultAllocator : public Allocator { - void *malloc(size_t size) throw(std::bad_alloc); - void free(void *addr) throw(); - void *realloc(void *addr, size_t size) throw(std::bad_alloc); + void *malloc(size_t size); + void free(void *addr) _NOEXCEPT; + void *realloc(void *addr, size_t size); }; struct SensitiveAllocator : public DefaultAllocator { - void free(void *addr) throw(); - void *realloc(void *addr, size_t size) throw(std::bad_alloc); + void free(void *addr) _NOEXCEPT; + void *realloc(void *addr, size_t size); }; struct DefaultAllocators { @@ -93,33 +93,33 @@ Allocator &Allocator::standard(UInt32 request) } } -void *DefaultAllocator::malloc(size_t size) throw(std::bad_alloc) +void *DefaultAllocator::malloc(size_t size) { if (void *result = ::malloc(size)) return result; throw std::bad_alloc(); } -void DefaultAllocator::free(void *addr) throw() +void DefaultAllocator::free(void *addr) _NOEXCEPT { ::free(addr); } -void *DefaultAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc) +void *DefaultAllocator::realloc(void *addr, size_t newSize) { if (void *result = ::realloc(addr, newSize)) return result; throw std::bad_alloc(); } -void SensitiveAllocator::free(void *addr) throw() +void SensitiveAllocator::free(void *addr) _NOEXCEPT { size_t size = malloc_size(addr); ::memset_s(addr, size, 0, size); DefaultAllocator::free(addr); } -void *SensitiveAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc) +void *SensitiveAllocator::realloc(void *addr, size_t newSize) { size_t oldSize = malloc_size(addr); if (newSize < oldSize) @@ -135,7 +135,7 @@ void *SensitiveAllocator::realloc(void *addr, size_t newSize) throw(std::bad_all // functions to safely free our (hidden) pointer without knowing about it. // An allocator argument of NULL is interpreted as the standard allocator. // -void *CssmHeap::operator new (size_t size, Allocator *alloc) throw(std::bad_alloc) +void *CssmHeap::operator new (size_t size, Allocator *alloc) { if (size > SIZE_T_MAX / 2) { throw std::bad_alloc(); @@ -150,12 +150,12 @@ void *CssmHeap::operator new (size_t size, Allocator *alloc) throw(std::bad_allo return addr; } -void CssmHeap::operator delete (void *addr, size_t size, Allocator *alloc) throw() +void CssmHeap::operator delete (void *addr, size_t size, Allocator *alloc) _NOEXCEPT { alloc->free(addr); // as per C++ std, called (only) if construction fails } -void CssmHeap::operator delete (void *addr, size_t size) throw() +void CssmHeap::operator delete (void *addr, size_t size) _NOEXCEPT { void *end = increment(addr, alignUp(size, alignof_template())); (*(Allocator **)end)->free(addr); diff --git a/OSX/libsecurity_utilities/lib/alloc.h b/OSX/libsecurity_utilities/lib/alloc.h index 8d276227..b77f9451 100644 --- a/OSX/libsecurity_utilities/lib/alloc.h +++ b/OSX/libsecurity_utilities/lib/alloc.h @@ -43,18 +43,18 @@ namespace Security class Allocator { public: virtual ~Allocator(); - virtual void *malloc(size_t) throw(std::bad_alloc) = 0; - virtual void free(void *) throw() = 0; - virtual void *realloc(void *, size_t) throw(std::bad_alloc) = 0; + virtual void *malloc(size_t)= 0; + virtual void free(void *) _NOEXCEPT = 0; + virtual void *realloc(void *, size_t)= 0; // // Template versions for added expressiveness. // Note that the integers are element counts, not byte sizes. // - template T *alloc() throw(std::bad_alloc) + template T *alloc() { return reinterpret_cast(malloc(sizeof(T))); } - template T *alloc(UInt32 count) throw(std::bad_alloc) + template T *alloc(UInt32 count) { size_t bytes = 0; if (__builtin_mul_overflow(sizeof(T), count, &bytes)) { @@ -64,7 +64,7 @@ public: } - template T *alloc(T *old, UInt32 count) throw(std::bad_alloc) + template T *alloc(T *old, UInt32 count) { size_t bytes = 0; if (__builtin_mul_overflow(sizeof(T), count, &bytes)) { @@ -78,14 +78,14 @@ public: // Happier malloc/realloc for any type. Note that these still have // the original (byte-sized) argument profile. // - template T *malloc(size_t size) throw(std::bad_alloc) + template T *malloc(size_t size) { return reinterpret_cast(malloc(size)); } - template T *realloc(void *addr, size_t size) throw(std::bad_alloc) + template T *realloc(void *addr, size_t size) { return reinterpret_cast(realloc(addr, size)); } // All right, if you *really* have to have calloc... - void *calloc(size_t size, size_t count) throw(std::bad_alloc) + void *calloc(size_t size, size_t count) { size_t bytes = 0; if(__builtin_mul_overflow(size, count, &bytes)) { @@ -98,7 +98,7 @@ public: } // compare Allocators for identity - virtual bool operator == (const Allocator &alloc) const throw(); + virtual bool operator == (const Allocator &alloc) const _NOEXCEPT; public: // allocator chooser options @@ -117,14 +117,14 @@ public: // Use this to cleanly destroy things. // template -inline void destroy(T *obj, Allocator &alloc) throw() +inline void destroy(T *obj, Allocator &alloc) _NOEXCEPT { obj->~T(); alloc.free(obj); } // untyped (release memory only, no destructor call) -inline void destroy(void *obj, Allocator &alloc) throw() +inline void destroy(void *obj, Allocator &alloc) _NOEXCEPT { alloc.free(obj); } @@ -145,17 +145,17 @@ inline void destroy(void *obj, Allocator &alloc) throw() // class CssmHeap { public: - void *operator new (size_t size, Allocator *alloc = NULL) throw(std::bad_alloc); - void operator delete (void *addr, size_t size) throw(); - void operator delete (void *addr, size_t size, Allocator *alloc) throw(); + void *operator new (size_t size, Allocator *alloc = NULL); + void operator delete (void *addr, size_t size) _NOEXCEPT; + void operator delete (void *addr, size_t size, Allocator *alloc) _NOEXCEPT; }; // -// Here is a version of auto_ptr that works with Allocators. It is designed +// Here is a version of unique_ptr that works with Allocators. It is designed // to be pretty much a drop-in replacement. It requires an allocator as a constructor // argument, of course. -// Note that CssmAutoPtr is perfectly valid, unlike its auto_ptr look-alike. +// Note that CssmAutoPtr is perfectly valid, unlike its unique_ptr look-alike. // You can't dereference it, naturally. // template @@ -176,7 +176,7 @@ public: ~CssmAutoPtr() { allocator.free(mine); } - T *get() const throw() { return mine; } + T *get() const _NOEXCEPT { return mine; } T *release() { T *result = mine; mine = NULL; return result; } void reset() { allocator.free(mine); mine = NULL; } @@ -203,7 +203,7 @@ public: ~CssmAutoPtr() { destroy(mine, allocator); } - void *get() throw() { return mine; } + void *get() _NOEXCEPT { return mine; } void *release() { void *result = mine; mine = NULL; return result; } void reset() { allocator.free(mine); mine = NULL; } @@ -248,10 +248,10 @@ public: // // Global C++ allocation hooks to use Allocators (global namespace) // -inline void *operator new (size_t size, Allocator &allocator) throw (std::bad_alloc) +inline void *operator new (size_t size, Allocator &allocator) { return allocator.malloc(size); } -inline void *operator new[] (size_t size, Allocator &allocator) throw (std::bad_alloc) +inline void *operator new[] (size_t size, Allocator &allocator) { return allocator.malloc(size); } diff --git a/OSX/libsecurity_utilities/lib/cfclass.cpp b/OSX/libsecurity_utilities/lib/cfclass.cpp index 530edb4b..6beabd29 100644 --- a/OSX/libsecurity_utilities/lib/cfclass.cpp +++ b/OSX/libsecurity_utilities/lib/cfclass.cpp @@ -89,7 +89,7 @@ CFClass::cleanupObject(intptr_t op, CFTypeRef cf, bool &zap) } uint32_t -CFClass::refCountForType(intptr_t op, CFTypeRef cf) throw() +CFClass::refCountForType(intptr_t op, CFTypeRef cf) _NOEXCEPT { uint32_t result = 0; bool zap = false; @@ -127,7 +127,7 @@ CFClass::refCountForType(intptr_t op, CFTypeRef cf) throw() void -CFClass::finalizeType(CFTypeRef cf) throw() +CFClass::finalizeType(CFTypeRef cf) _NOEXCEPT { /* We need to control the lifetime of the object. This means @@ -168,7 +168,7 @@ CFClass::finalizeType(CFTypeRef cf) throw() } Boolean -CFClass::equalType(CFTypeRef cf1, CFTypeRef cf2) throw() +CFClass::equalType(CFTypeRef cf1, CFTypeRef cf2) _NOEXCEPT { // CF checks for pointer equality and ensures type equality already try { @@ -179,7 +179,7 @@ CFClass::equalType(CFTypeRef cf1, CFTypeRef cf2) throw() } CFHashCode -CFClass::hashType(CFTypeRef cf) throw() +CFClass::hashType(CFTypeRef cf) _NOEXCEPT { try { return SecCFObject::optional(cf)->hash(); @@ -189,7 +189,7 @@ CFClass::hashType(CFTypeRef cf) throw() } CFStringRef -CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) throw() +CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) _NOEXCEPT { try { return SecCFObject::optional(cf)->copyFormattingDesc(dict); @@ -199,7 +199,7 @@ CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) throw() } CFStringRef -CFClass::copyDebugDescType(CFTypeRef cf) throw() +CFClass::copyDebugDescType(CFTypeRef cf) _NOEXCEPT { try { return SecCFObject::optional(cf)->copyDebugDesc(); diff --git a/OSX/libsecurity_utilities/lib/cfclass.h b/OSX/libsecurity_utilities/lib/cfclass.h index 6203f112..1adbbe18 100644 --- a/OSX/libsecurity_utilities/lib/cfclass.h +++ b/OSX/libsecurity_utilities/lib/cfclass.h @@ -41,12 +41,12 @@ public: CFTypeID typeID; private: - static void finalizeType(CFTypeRef cf) throw(); - static Boolean equalType(CFTypeRef cf1, CFTypeRef cf2) throw(); - static CFHashCode hashType(CFTypeRef cf) throw(); - static CFStringRef copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) throw(); - static CFStringRef copyDebugDescType(CFTypeRef cf) throw(); - static uint32_t refCountForType(intptr_t op, CFTypeRef cf) throw(); + static void finalizeType(CFTypeRef cf) _NOEXCEPT; + static Boolean equalType(CFTypeRef cf1, CFTypeRef cf2) _NOEXCEPT; + static CFHashCode hashType(CFTypeRef cf) _NOEXCEPT; + static CFStringRef copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) _NOEXCEPT; + static CFStringRef copyDebugDescType(CFTypeRef cf) _NOEXCEPT; + static uint32_t refCountForType(intptr_t op, CFTypeRef cf) _NOEXCEPT; static uint32_t cleanupObject(intptr_t op, CFTypeRef cf, bool &zap); }; diff --git a/OSX/libsecurity_utilities/lib/cfmunge.cpp b/OSX/libsecurity_utilities/lib/cfmunge.cpp index f26ccc72..2854e600 100644 --- a/OSX/libsecurity_utilities/lib/cfmunge.cpp +++ b/OSX/libsecurity_utilities/lib/cfmunge.cpp @@ -221,17 +221,21 @@ CFTypeRef CF_RETURNS_RETAINED CFMake::makedictionary() return dict; } else return NULL; // bad syntax - } else + } else { dict = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (dict == NULL) + } + + if (dict == NULL) { return dict; - if (add(dict)) - return dict; - else { - CFReleaseSafe(dict); - return NULL; - } + } + + if (add(dict)) { + return dict; + } else { + CFReleaseSafe(dict); + return NULL; + } } CFDictionaryRef CFMake::add(CFMutableDictionaryRef dict) diff --git a/OSX/libsecurity_utilities/lib/daemon.cpp b/OSX/libsecurity_utilities/lib/daemon.cpp index f06ced98..780174a7 100644 --- a/OSX/libsecurity_utilities/lib/daemon.cpp +++ b/OSX/libsecurity_utilities/lib/daemon.cpp @@ -36,7 +36,6 @@ namespace Security { namespace Daemon { - // // Daemonize this process, the UNIX way. // @@ -82,31 +81,5 @@ bool incarnate(bool doFork /*=true*/) return true; } - -// -// Re-execute myself. -// This is a pretty bad hack for libraries that are pretty broken and (essentially) -// don't work after a fork() unless you also exec(). -// -// WARNING: Don't even THINK of doing this in a setuid-anything program. -// -bool executeSelf(char **argv) -{ - static const char reExecEnv[] = "_RE_EXECUTE"; - if (getenv(reExecEnv)) { // was re-executed - secinfo("daemon", "self-execution complete"); - unsetenv(reExecEnv); - return true; - } else { - setenv(reExecEnv, "go", 1); - secinfo("daemon", "self-executing (ouch!)"); - execv(argv[0], argv); - perror("re-execution"); - Syslog::error("Re-execution attempt failed"); - return false; - } -} - - } // end namespace Daemon } // end namespace Security diff --git a/OSX/libsecurity_utilities/lib/daemon.h b/OSX/libsecurity_utilities/lib/daemon.h index 6e51747d..e65800b5 100644 --- a/OSX/libsecurity_utilities/lib/daemon.h +++ b/OSX/libsecurity_utilities/lib/daemon.h @@ -35,7 +35,6 @@ namespace Security { namespace Daemon { bool incarnate(bool doFork=true); -bool executeSelf(char **argv); } // end namespace Daemon } // end namespace Security diff --git a/OSX/libsecurity_utilities/lib/debugging_internal.cpp b/OSX/libsecurity_utilities/lib/debugging_internal.cpp index 55c74a7c..c95c802e 100644 --- a/OSX/libsecurity_utilities/lib/debugging_internal.cpp +++ b/OSX/libsecurity_utilities/lib/debugging_internal.cpp @@ -218,9 +218,11 @@ void Target::message(const char *scope, const char *format, va_list args) // now stuff the message body in, slightly roasted size_t left = buffer + sizeof(buffer) - bufp - 1; // reserve one size_t written = vsnprintf(bufp, left, format, args); - for (char *p = bufp; *p; p++) - if (!isprint(*p)) + for (char *p = bufp; *p; p++) { + if (!isprint(*p)) { *p = '?'; + } + } if (written >= left) { // snprintf overflowed bufp += left; strcpy(bufp - 3, "..."); diff --git a/OSX/libsecurity_utilities/lib/errors.cpp b/OSX/libsecurity_utilities/lib/errors.cpp index e715b11d..5072da2f 100644 --- a/OSX/libsecurity_utilities/lib/errors.cpp +++ b/OSX/libsecurity_utilities/lib/errors.cpp @@ -60,7 +60,7 @@ CommonError::CommonError(const CommonError &source) strlcpy(whatBuffer, source.whatBuffer, whatBufferSize); } -CommonError::~CommonError() throw () +CommonError::~CommonError() _NOEXCEPT { } @@ -135,7 +135,7 @@ UnixError::UnixError(int err, bool suppresslogging) : error(err) } } -const char *UnixError::what() const throw () +const char *UnixError::what() const _NOEXCEPT { return whatBuffer; } @@ -175,7 +175,7 @@ MacOSError::MacOSError(int err) : error(err) } } -const char *MacOSError::what() const throw () +const char *MacOSError::what() const _NOEXCEPT { return whatBuffer; } @@ -219,7 +219,7 @@ CFError::CFError() LogBacktrace(); } -const char *CFError::what() const throw () +const char *CFError::what() const _NOEXCEPT { return "CoreFoundation error"; } OSStatus CFError::osStatus() const diff --git a/OSX/libsecurity_utilities/lib/errors.h b/OSX/libsecurity_utilities/lib/errors.h index 4baae8f3..b0cf718d 100644 --- a/OSX/libsecurity_utilities/lib/errors.h +++ b/OSX/libsecurity_utilities/lib/errors.h @@ -50,7 +50,7 @@ protected: CommonError(); CommonError(const CommonError &source); public: - virtual ~CommonError() throw (); + virtual ~CommonError() _NOEXCEPT; virtual OSStatus osStatus() const = 0; virtual int unixError() const = 0; @@ -74,7 +74,7 @@ public: const int error; virtual OSStatus osStatus() const; virtual int unixError() const; - virtual const char *what () const throw (); + virtual const char *what () const _NOEXCEPT; static void check(int result) { if (result == -1) throwMe(); } static void throwMe(int err = errno) __attribute__((noreturn)); @@ -96,7 +96,7 @@ public: const int error; virtual OSStatus osStatus() const; virtual int unixError() const; - virtual const char *what () const throw (); + virtual const char *what () const _NOEXCEPT; static void check(OSStatus status) { if (status != errSecSuccess) throwMe(status); } static void throwMe(int err) __attribute__((noreturn)); @@ -120,7 +120,7 @@ protected: public: virtual OSStatus osStatus() const; virtual int unixError() const; - virtual const char *what () const throw (); + virtual const char *what () const _NOEXCEPT; template static void check(const T &p) { if (!p) throwMe(); } diff --git a/OSX/libsecurity_utilities/lib/globalizer.cpp b/OSX/libsecurity_utilities/lib/globalizer.cpp index df5af3bc..7d8306a1 100644 --- a/OSX/libsecurity_utilities/lib/globalizer.cpp +++ b/OSX/libsecurity_utilities/lib/globalizer.cpp @@ -42,7 +42,7 @@ // // The Error class thrown if Nexus operations fail // -GlobalNexus::Error::~Error() throw() +GlobalNexus::Error::~Error() _NOEXCEPT { } @@ -80,7 +80,7 @@ ProcessNexusBase::ProcessNexusBase(const char *identifier) { const char *env = getenv(identifier); if (env == NULL) { // perhaps we're first... - auto_ptr store(new Store); + unique_ptr store(new Store); char form[2*sizeof(Store *) + 2]; sprintf(form, "*%p", &store); setenv(identifier, form, 0); // do NOT overwrite... diff --git a/OSX/libsecurity_utilities/lib/globalizer.h b/OSX/libsecurity_utilities/lib/globalizer.h index 5610cc8a..db0e20ff 100644 --- a/OSX/libsecurity_utilities/lib/globalizer.h +++ b/OSX/libsecurity_utilities/lib/globalizer.h @@ -47,10 +47,10 @@ class GlobalNexus { public: class Error : public std::exception { public: - virtual ~Error() throw(); + virtual ~Error() _NOEXCEPT; const char * const message; Error(const char *m) : message(m) { } - const char *what() const throw() { return message; } + const char *what() const _NOEXCEPT { return message; } }; }; diff --git a/OSX/libsecurity_utilities/lib/mach++.cpp b/OSX/libsecurity_utilities/lib/mach++.cpp index ab6bb982..9708a823 100644 --- a/OSX/libsecurity_utilities/lib/mach++.cpp +++ b/OSX/libsecurity_utilities/lib/mach++.cpp @@ -47,7 +47,7 @@ Error::Error(kern_return_t err) : error(err) secnotice("security_exception", "mach error: %d", err); } -Error::~Error() throw() +Error::~Error() _NOEXCEPT { } @@ -142,9 +142,10 @@ mach_port_t Port::cancelNotify(mach_msg_id_t type) { // Mach won't let us unset the DPN port if we are already dead // (EVEN if the DPN has already been sent!) So just ignore that case... - if (isDead()) + if (isDead()) { return MACH_PORT_NULL; - return requestNotify(MACH_PORT_NULL, type); + } + return requestNotify(MACH_PORT_NULL, type); } mach_port_msgcount_t Port::qlimit() const diff --git a/OSX/libsecurity_utilities/lib/mach++.h b/OSX/libsecurity_utilities/lib/mach++.h index dba14c37..ba7f02b1 100644 --- a/OSX/libsecurity_utilities/lib/mach++.h +++ b/OSX/libsecurity_utilities/lib/mach++.h @@ -53,7 +53,7 @@ protected: // actually, kern_return_t can be just about any subsystem type return code Error(kern_return_t err); public: - virtual ~Error() throw(); + virtual ~Error() _NOEXCEPT; virtual OSStatus osStatus() const; virtual int unixError() const; @@ -107,8 +107,13 @@ public: // port allocation and management void allocate(mach_port_right_t right = MACH_PORT_RIGHT_RECEIVE) { check(mach_port_allocate(self(), right, &mPort)); } - void deallocate() { check(mach_port_deallocate(self(), mPort)); mPort = MACH_PORT_NULL;} - void destroy() { check(mach_port_destroy(self(), mPort)); mPort = MACH_PORT_NULL; } + /* + * (╯ರ ~ ರ)╯︵ ┻━┻ + * mach_port_deallocate() only deallocates send, send-once, dead-name, or port-set. + * Since allocate() defaults to receive, allocate() and deallocate() do not actually + * balance each other; deallocate() will fail with an invalid-right error. + */ + void deallocate() { check(mach_port_deallocate(self(), mPort)); mPort = MACH_PORT_NULL;} void insertRight(mach_msg_type_name_t type) { check(mach_port_insert_right(self(), mPort, mPort, type)); } @@ -134,25 +139,13 @@ protected: }; -// -// A simple Port that deallocates itself on destruction. -// If you need a subclass of Port, just assign it to a separate AutoPort. -// -class AutoPort : public Port { -public: - AutoPort() { } - AutoPort(mach_port_t port) : Port(port) { } - ~AutoPort() { if (mPort != MACH_PORT_NULL) deallocate(); } -}; - - // // Ports representing PortSets // class PortSet : public Port { public: PortSet() { allocate(MACH_PORT_RIGHT_PORT_SET); } - ~PortSet() { destroy(); } + ~PortSet() { deallocate(); } void operator += (const Port &port) { check(mach_port_move_member(self(), port, mPort)); } @@ -222,7 +215,7 @@ class ReceivePort : public Port { public: ReceivePort() { allocate(); } ReceivePort(const char *name, const Bootstrap &bootstrap, bool tryCheckin = true); - ~ReceivePort() { destroy(); } + ~ReceivePort() { modRefs(MACH_PORT_RIGHT_RECEIVE, -1); } }; diff --git a/OSX/libsecurity_utilities/lib/macho++.cpp b/OSX/libsecurity_utilities/lib/macho++.cpp index 32836ab0..f7f8c81d 100644 --- a/OSX/libsecurity_utilities/lib/macho++.cpp +++ b/OSX/libsecurity_utilities/lib/macho++.cpp @@ -768,11 +768,12 @@ const fat_arch *Universal::findArch(const Architecture &target) const // exact match for (const fat_arch *arch = mArchList; arch < end; ++arch) if (arch->cputype == target.cpuType() - && arch->cpusubtype == target.cpuSubtype()) + && (arch->cpusubtype & ~CPU_SUBTYPE_MASK) == target.cpuSubtype()) return arch; // match for generic model of main architecture for (const fat_arch *arch = mArchList; arch < end; ++arch) - if (arch->cputype == target.cpuType() && arch->cpusubtype == 0) + if (arch->cputype == target.cpuType() + && (arch->cpusubtype & ~CPU_SUBTYPE_MASK) == 0) return arch; // match for any subarchitecture of the main architecture (questionable) for (const fat_arch *arch = mArchList; arch < end; ++arch) @@ -790,7 +791,7 @@ MachO *Universal::findImage(const Architecture &target) const MachO* Universal::make(MachO* macho) const { - auto_ptr mo(macho); // safe resource + unique_ptr mo(macho); // safe resource uint32_t type = mo->type(); if (type == 0) // not a recognized Mach-O type UnixError::throwMe(ENOEXEC); @@ -829,7 +830,7 @@ void Universal::architectures(Architectures &archs) const for (unsigned n = 0; n < mArchCount; n++) archs.insert(mArchList[n]); } else { - auto_ptr macho(architecture()); + unique_ptr macho(architecture()); archs.insert(macho->architecture()); } } @@ -880,7 +881,7 @@ bool Universal::isSuspicious() const Universal::Architectures archList; architectures(archList); for (Universal::Architectures::const_iterator it = archList.begin(); it != archList.end(); ++it) { - auto_ptr macho(architecture(*it)); + unique_ptr macho(architecture(*it)); if (macho->isSuspicious()) return true; } diff --git a/OSX/libsecurity_utilities/lib/macho++.h b/OSX/libsecurity_utilities/lib/macho++.h index a58ec309..f479c686 100644 --- a/OSX/libsecurity_utilities/lib/macho++.h +++ b/OSX/libsecurity_utilities/lib/macho++.h @@ -53,7 +53,7 @@ public: Architecture(const char *name); cpu_type_t cpuType() const { return this->first; } - cpu_subtype_t cpuSubtype() const { return this->second; } + cpu_subtype_t cpuSubtype() const { return this->second & ~CPU_SUBTYPE_MASK; } const char *name() const; // NULL if unknown std::string displayName() const; // always display-able diff --git a/OSX/libsecurity_utilities/lib/muscle++.cpp b/OSX/libsecurity_utilities/lib/muscle++.cpp index face9600..5511fbd9 100644 --- a/OSX/libsecurity_utilities/lib/muscle++.cpp +++ b/OSX/libsecurity_utilities/lib/muscle++.cpp @@ -45,7 +45,7 @@ Error::Error(MSC_RV err) : error(err) } -const char *Error::what() const throw () +const char *Error::what() const _NOEXCEPT { return msc_error(error); } @@ -92,7 +92,10 @@ void Connection::open(const PCSC::ReaderState &reader, unsigned share) strncpy(info.slotName, reader.name(), MAX_READERNAME); // set ATR in info - assert(reader.length() <= MAX_ATR_SIZE); + if (reader.length() > MAX_ATR_SIZE) { + Error::throwMe(MSC_INVALID_PARAMETER); + } + memcpy(info.tokenId, reader.data(), reader.length()); info.tokenIdLength = (MSCULong32)reader.length(); diff --git a/OSX/libsecurity_utilities/lib/muscle++.h b/OSX/libsecurity_utilities/lib/muscle++.h index 016940ec..4c32be90 100644 --- a/OSX/libsecurity_utilities/lib/muscle++.h +++ b/OSX/libsecurity_utilities/lib/muscle++.h @@ -56,7 +56,7 @@ public: const MSC_RV error; OSStatus osStatus() const; int unixError() const; - const char *what () const throw (); + const char *what () const _NOEXCEPT; static void check(MSC_RV err) { if (err != MSC_SUCCESS) throwMe(err); } static void throwMe(MSC_RV err); diff --git a/OSX/libsecurity_utilities/lib/pcsc++.cpp b/OSX/libsecurity_utilities/lib/pcsc++.cpp index 67161287..2efb4c96 100644 --- a/OSX/libsecurity_utilities/lib/pcsc++.cpp +++ b/OSX/libsecurity_utilities/lib/pcsc++.cpp @@ -66,7 +66,7 @@ Error::Error(unsigned long err) : error(err) } -const char *Error::what() const throw () +const char *Error::what() const _NOEXCEPT { return pcsc_stringify_error((int32_t)error); } diff --git a/OSX/libsecurity_utilities/lib/pcsc++.h b/OSX/libsecurity_utilities/lib/pcsc++.h index 5ca469d7..b6eacebf 100644 --- a/OSX/libsecurity_utilities/lib/pcsc++.h +++ b/OSX/libsecurity_utilities/lib/pcsc++.h @@ -60,7 +60,7 @@ public: const unsigned long error; OSStatus osStatus() const; int unixError() const; - const char *what () const throw (); + const char *what () const _NOEXCEPT; static void check(unsigned long err) { if (err != SCARD_S_SUCCESS) throwMe(err); } static void throwMe(unsigned long err); diff --git a/OSX/libsecurity_utilities/lib/refcount.h b/OSX/libsecurity_utilities/lib/refcount.h index e94f5657..71b8c203 100644 --- a/OSX/libsecurity_utilities/lib/refcount.h +++ b/OSX/libsecurity_utilities/lib/refcount.h @@ -112,7 +112,7 @@ public: RefPointer& operator = (const RefPointer& p) { setPointer(p.ptr); return *this; } // dereference operations - T* get () const { _check(); return ptr; } // mimic auto_ptr + T* get () const { _check(); return ptr; } // mimic unique_ptr operator T * () const { _check(); return ptr; } T * operator -> () const { _check(); return ptr; } T & operator * () const { _check(); return *ptr; } diff --git a/OSX/libsecurity_utilities/lib/seccfobject.cpp b/OSX/libsecurity_utilities/lib/seccfobject.cpp index 93185ffc..04972e7c 100644 --- a/OSX/libsecurity_utilities/lib/seccfobject.cpp +++ b/OSX/libsecurity_utilities/lib/seccfobject.cpp @@ -112,7 +112,7 @@ void SecPointerBase::copy(SecCFObject * p) // SecCFObject // SecCFObject * -SecCFObject::optional(CFTypeRef cfTypeRef) throw() +SecCFObject::optional(CFTypeRef cfTypeRef) _NOEXCEPT { if (!cfTypeRef) return NULL; @@ -131,7 +131,7 @@ SecCFObject::required(CFTypeRef cfTypeRef, OSStatus error) } void * -SecCFObject::allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc) +SecCFObject::allocate(size_t size, const CFClass &cfclass) { CFTypeRef p = _CFRuntimeCreateInstance(NULL, cfclass.typeID, size + kAlignedRuntimeSize - sizeof(CFRuntimeBase), NULL); @@ -146,7 +146,7 @@ SecCFObject::allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc) } void -SecCFObject::operator delete(void *object) throw() +SecCFObject::operator delete(void *object) _NOEXCEPT { CFTypeRef cfType = reinterpret_cast(reinterpret_cast(object) - kAlignedRuntimeSize); @@ -217,7 +217,7 @@ SecCFObject::copyDebugDesc() } CFTypeRef -SecCFObject::handle(bool retain) throw() +SecCFObject::handle(bool retain) _NOEXCEPT { CFTypeRef cfType = *this; if (retain && !isNew()) CFRetain(cfType); diff --git a/OSX/libsecurity_utilities/lib/seccfobject.h b/OSX/libsecurity_utilities/lib/seccfobject.h index 29e9a5d3..6ea5445e 100644 --- a/OSX/libsecurity_utilities/lib/seccfobject.h +++ b/OSX/libsecurity_utilities/lib/seccfobject.h @@ -54,7 +54,7 @@ APIPTR handle(bool retain) \ #define SECCFFUNCTIONS_CREATABLE(OBJTYPE, APIPTR, CFCLASS) \ SECCFFUNCTIONS_BASE(OBJTYPE, APIPTR)\ \ -void *operator new(size_t size) throw(std::bad_alloc) \ +void *operator new(size_t size)\ { return SecCFObject::allocate(size, CFCLASS); } #define SECCFFUNCTIONS(OBJTYPE, APIPTR, ERRCODE, CFCLASS) \ @@ -79,7 +79,7 @@ struct SecRuntimeBase: CFRuntimeBase class SecCFObject { private: - void *operator new(size_t) throw(std::bad_alloc); + void *operator new(size_t); // Align up to a multiple of 16 bytes static const size_t kAlignedRuntimeSize = SECALIGNUP(sizeof(SecRuntimeBase), 4); @@ -97,23 +97,23 @@ public: return !atomic_flag_test_and_set(&(base->isOld)); } - static SecCFObject *optional(CFTypeRef) throw(); + static SecCFObject *optional(CFTypeRef) _NOEXCEPT; static SecCFObject *required(CFTypeRef, OSStatus error); - static void *allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc); + static void *allocate(size_t size, const CFClass &cfclass); SecCFObject(); virtual ~SecCFObject(); uint32_t updateRetainCount(intptr_t direction, uint32_t *oldCount); uint32_t getRetainCount() {return updateRetainCount(0, NULL);} - static void operator delete(void *object) throw(); - virtual operator CFTypeRef() const throw() + static void operator delete(void *object) _NOEXCEPT; + virtual operator CFTypeRef() const _NOEXCEPT { return reinterpret_cast(reinterpret_cast(this) - kAlignedRuntimeSize); } // This bumps up the retainCount by 1, by calling CFRetain(), iff retain is true - CFTypeRef handle(bool retain = true) throw(); + CFTypeRef handle(bool retain = true) _NOEXCEPT; virtual bool equal(SecCFObject &other); virtual CFHashCode hash(); @@ -156,10 +156,12 @@ public: T *yield() { T *result = static_cast(ptr); ptr = NULL; return result; } // dereference operations - T* get () const { return static_cast(ptr); } // mimic auto_ptr + T* get () const { return static_cast(ptr); } // mimic unique_ptr operator T * () const { return static_cast(ptr); } T * operator -> () const { return static_cast(ptr); } T & operator * () const { return *static_cast(ptr); } + + SecPointer& operator=(const SecPointer& other) { SecPointerBase::operator=(other); return *this; } }; template diff --git a/OSX/libsecurity_utilities/lib/simpleprefs.cpp b/OSX/libsecurity_utilities/lib/simpleprefs.cpp index c4d09774..26f40934 100644 --- a/OSX/libsecurity_utilities/lib/simpleprefs.cpp +++ b/OSX/libsecurity_utilities/lib/simpleprefs.cpp @@ -30,7 +30,7 @@ #include "errors.h" #include #include -#include +#include #include #include #include diff --git a/OSX/libsecurity_utilities/lib/sqlite++.h b/OSX/libsecurity_utilities/lib/sqlite++.h index 888fcc8e..4f690c25 100644 --- a/OSX/libsecurity_utilities/lib/sqlite++.h +++ b/OSX/libsecurity_utilities/lib/sqlite++.h @@ -50,11 +50,11 @@ public: Error(Database &db); Error(int err) : error(err) { } Error(int err, const char *msg) : error(err), message(msg) { } - ~Error() throw () { } + ~Error() _NOEXCEPT { } const int error; const std::string message; - const char *what() const throw () { return message.c_str(); } + const char *what() const _NOEXCEPT { return message.c_str(); } OSStatus osStatus() const; int unixError() const; diff --git a/OSX/libsecurity_utilities/lib/superblob.h b/OSX/libsecurity_utilities/lib/superblob.h index ba7a5811..ce20f30a 100644 --- a/OSX/libsecurity_utilities/lib/superblob.h +++ b/OSX/libsecurity_utilities/lib/superblob.h @@ -6,6 +6,7 @@ #include #include +#include #include namespace Security { @@ -262,8 +263,10 @@ _BlobType *SuperBlobCore<_BlobType, _magic, _Type>::Maker::make() const pc += it->second->length(); n++; } - secinfo("superblob", "Maker %p assembles %ld blob(s) into %p (size=%d)", - this, mPieces.size(), result, total); + ostringstream os; + os << "Maker " << this << " assembles " << mPieces.size() << " blob(s) into " << result + << " (size=" << total << ")"; + secinfo("superblob", "%s", os.str().c_str()); return result; } diff --git a/OSX/libsecurity_utilities/lib/trackingallocator.cpp b/OSX/libsecurity_utilities/lib/trackingallocator.cpp index 33650037..bab8ab47 100644 --- a/OSX/libsecurity_utilities/lib/trackingallocator.cpp +++ b/OSX/libsecurity_utilities/lib/trackingallocator.cpp @@ -43,20 +43,20 @@ TrackingAllocator::~TrackingAllocator() // Standard allocation operations. // We pass them down to our subAllocator and keep track of what we've got. // -void *TrackingAllocator::malloc(size_t inSize) throw(std::bad_alloc) +void *TrackingAllocator::malloc(size_t inSize) { void *anAddress = subAllocator.malloc(inSize); mAllocSet.insert(anAddress); return anAddress; } -void TrackingAllocator::free(void *inAddress) throw() +void TrackingAllocator::free(void *inAddress) _NOEXCEPT { subAllocator.free(inAddress); mAllocSet.erase(inAddress); } -void *TrackingAllocator::realloc(void *inAddress, size_t inNewSize) throw(std::bad_alloc) +void *TrackingAllocator::realloc(void *inAddress, size_t inNewSize) { void *anAddress = subAllocator.realloc(inAddress, inNewSize); if (anAddress != inAddress) diff --git a/OSX/libsecurity_utilities/lib/trackingallocator.h b/OSX/libsecurity_utilities/lib/trackingallocator.h index 01e2ccce..09fbee4e 100644 --- a/OSX/libsecurity_utilities/lib/trackingallocator.h +++ b/OSX/libsecurity_utilities/lib/trackingallocator.h @@ -47,9 +47,9 @@ public: Allocator &subAllocator; // standard Allocator operations - void *malloc(size_t inSize) throw(std::bad_alloc); - void free(void *inAddress) throw(); - void *realloc(void *inAddress, size_t inNewSize) throw(std::bad_alloc); + void *malloc(size_t inSize); + void free(void *inAddress) _NOEXCEPT; + void *realloc(void *inAddress, size_t inNewSize); // reset frees all memory; commit forgets about it all void reset(); diff --git a/OSX/libsecurity_utilities/lib/unix++.h b/OSX/libsecurity_utilities/lib/unix++.h index b41ccd7d..ed7be8be 100644 --- a/OSX/libsecurity_utilities/lib/unix++.h +++ b/OSX/libsecurity_utilities/lib/unix++.h @@ -96,6 +96,8 @@ public: FileDesc() : mFd(invalidFd), mAtEnd(false) { } FileDesc(int fd) : mFd(fd), mAtEnd(false) { } + FileDesc(const FileDesc& fd) : mFd(fd.mFd), mAtEnd(fd.mAtEnd) { } + static const mode_t modeMissingOk = S_IFIFO; // in mode means "do not throw on ENOENT" // implicit file system open() construction diff --git a/OSX/libsecurity_utilities/lib/unixchild.cpp b/OSX/libsecurity_utilities/lib/unixchild.cpp index 9e1c9f75..b6369d5c 100644 --- a/OSX/libsecurity_utilities/lib/unixchild.cpp +++ b/OSX/libsecurity_utilities/lib/unixchild.cpp @@ -42,6 +42,7 @@ #include #include +#include namespace Security { namespace UnixPlusPlus { @@ -371,7 +372,7 @@ bool Child::checkStatus(int options) secinfo("unixchild", "checking %p (pid %d)", this, this->pid()); int status; again: - switch (IFDEBUG(pid_t pid =) ::wait4(this->pid(), &status, options, NULL)) { + switch (pid_t pid = ::wait4(this->pid(), &status, options, NULL)) { case pid_t(-1): switch (errno) { case EINTR: @@ -420,7 +421,9 @@ void Child::checkChildren() } else if (!mChildren().empty()) { int status; while (pid_t pid = ::wait4(0, &status, WNOHANG, NULL)) { - secinfo("unixchild", "universal child check (%ld children known alive)", mChildren().size()); + ostringstream os; + os << "universal child check (" << mChildren().size() << " children known alive)"; + secinfo("unixchild", "%s", os.str().c_str()); switch (pid) { case pid_t(-1): switch (errno) { diff --git a/OSX/libsecurity_utilities/lib/utilities.h b/OSX/libsecurity_utilities/lib/utilities.h index 2bd28d56..b3bd7de1 100644 --- a/OSX/libsecurity_utilities/lib/utilities.h +++ b/OSX/libsecurity_utilities/lib/utilities.h @@ -35,6 +35,8 @@ #include #include +#include + namespace Security { diff --git a/OSX/libsecurity_utilities/lib/utility_config.h b/OSX/libsecurity_utilities/lib/utility_config.h index 7919078e..94611ebc 100644 --- a/OSX/libsecurity_utilities/lib/utility_config.h +++ b/OSX/libsecurity_utilities/lib/utility_config.h @@ -29,7 +29,7 @@ #define _H_UTILITY_CONFIG #include -#include +#include // // Decide what io apis we'll be using diff --git a/OSX/libsecurityd/lib/sec_xdr.c b/OSX/libsecurityd/lib/sec_xdr.c index e3ae277a..2e72e060 100644 --- a/OSX/libsecurityd/lib/sec_xdr.c +++ b/OSX/libsecurityd/lib/sec_xdr.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include "sec_xdr.h" diff --git a/OSX/libsecurityd/lib/sec_xdr_array.c b/OSX/libsecurityd/lib/sec_xdr_array.c index a0f710f1..e5bcc87a 100644 --- a/OSX/libsecurityd/lib/sec_xdr_array.c +++ b/OSX/libsecurityd/lib/sec_xdr_array.c @@ -72,7 +72,7 @@ static char *sccsid = "@(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC"; #include #include #include -#include +#include #include "sec_xdr.h" diff --git a/OSX/libsecurityd/lib/sec_xdr_reference.c b/OSX/libsecurityd/lib/sec_xdr_reference.c index 0ceadc0f..e36a6da7 100644 --- a/OSX/libsecurityd/lib/sec_xdr_reference.c +++ b/OSX/libsecurityd/lib/sec_xdr_reference.c @@ -59,7 +59,7 @@ static char *sccsid = "@(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC"; static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_reference.c,v 1.11 2002/03/22 21:53:26 obrien Exp $"; #endif #include -#include +#include /* * xdr_reference.c, Generic XDR routines impelmentation. * diff --git a/OSX/libsecurityd/lib/xdr_auth.c b/OSX/libsecurityd/lib/xdr_auth.c index 69ac9335..a4539cab 100644 --- a/OSX/libsecurityd/lib/xdr_auth.c +++ b/OSX/libsecurityd/lib/xdr_auth.c @@ -26,7 +26,6 @@ #include #include #include -#include bool_t xdr_AuthorizationItem(XDR *xdrs, AuthorizationItem *objp) diff --git a/OSX/libsecurityd/lib/xdr_cssm.c b/OSX/libsecurityd/lib/xdr_cssm.c index f74ce46e..e7200777 100644 --- a/OSX/libsecurityd/lib/xdr_cssm.c +++ b/OSX/libsecurityd/lib/xdr_cssm.c @@ -24,7 +24,7 @@ #include #include /* bzero() */ #include /* exit() */ -#include /* assert() */ +#include /* assert() */ #include /* XXX/gh because utilities/debugging.h doesn't */ #include diff --git a/OSX/macos_tapi_hacks.h b/OSX/macos_tapi_hacks.h index a03e17e8..02666f37 100644 --- a/OSX/macos_tapi_hacks.h +++ b/OSX/macos_tapi_hacks.h @@ -82,12 +82,20 @@ bool securityd_message_no_error(xpc_object_t message, CFErrorRef *error); void SecAccessGroupsSetCurrent(CFArrayRef accessGroups); CFArrayRef SecAccessGroupsGetCurrent(void); +void SecSecurityClientRegularToAppClip(void); +void SecSecurityClientAppClipToRegular(void); +void SecSecurityClientSetApplicationIdentifier(CFStringRef identifier); void SecServerSetTrustdMachServiceName(const char *name); // checkpw.c int checkpw_internal( const struct passwd* pw, const char* password ); +#ifdef __arm64__ +extern SecKeyRef SecCertificateCopyPublicKey_ios(SecCertificateRef certificate) __asm("_SecCertificateCopyPublicKey"); +extern CFDataRef SecCertificateCopySerialNumber_ios(SecCertificateRef certificate) __asm("_SecCertificateCopySerialNumber"); +#endif + #pragma clang diagnostic pop #endif /* macos_tapi_hack_h */ diff --git a/OSX/regressions/test/testenv.h b/OSX/regressions/test/testenv.h index 6c7b177d..bc53356d 100644 --- a/OSX/regressions/test/testenv.h +++ b/OSX/regressions/test/testenv.h @@ -33,7 +33,6 @@ extern "C" { extern int test_strict_bats; extern int test_verbose; extern int test_check_leaks; -extern char **test_skip_leaks_test; int tests_begin(int argc, char * const *argv); diff --git a/OSX/regressions/test/testenv.m b/OSX/regressions/test/testenv.m index 8692ff3c..f644cbe1 100644 --- a/OSX/regressions/test/testenv.m +++ b/OSX/regressions/test/testenv.m @@ -59,7 +59,6 @@ int test_strict_bats = 1; int test_verbose = 0; int test_onebatstest = 0; int test_check_leaks = 0; -char **test_skip_leaks_test = NULL; #ifdef NO_SERVER #include "keychain/securityd/spi.h" @@ -210,34 +209,8 @@ static int tests_run_test(struct one_test_s *test, int argc, char * const *argv) free(cmd); } if (ret != 0) { - unsigned n = 0; fprintf(stdout, "leaks found in test %s\n", test->name); - - if (test_skip_leaks_test) { - while (test_skip_leaks_test[n]) { - if (strcmp(test_skip_leaks_test[n], test->name) == 0) { - fprintf(stdout, "test %s known to be leaky, skipping\n", test->name); - ret = 0; - break; - } - } - } - if (ret) { - token = "FAIL"; - } - } else { - if (test_skip_leaks_test) { - unsigned n = 0; - - while (test_skip_leaks_test[n]) { - if (strcmp(test_skip_leaks_test[n], test->name) == 0) { - fprintf(stdout, "leaks didn't find leak in test %s, yet it was ignore\n", test->name); - token = "FAIL"; - break; - } - } - } - + token = "FAIL"; } } diff --git a/OSX/regressions/test/testmore.h b/OSX/regressions/test/testmore.h index 7bf5e726..cea9ccdb 100644 --- a/OSX/regressions/test/testmore.h +++ b/OSX/regressions/test/testmore.h @@ -41,12 +41,12 @@ __BEGIN_DECLS #define DISABLED_ONE_TEST(x) ONE_TEST(x) #define OFF_ONE_TEST(x) ONE_TEST(x) -typedef int (*one_test_entry)(int argc, char *const *argv); +typedef int (*_Nonnull one_test_entry)(int argc, char *_Nonnull const *_Nonnull argv); #define ONE_TEST_ENTRY(x) int x(int argc, char *const *argv) struct one_test_s { - char *name; /* test name. */ + const char * _Nonnull name; /* test name. */ one_test_entry entry; /* entry point. */ int off; /* off by default. */ int sub_tests; /* number of subtests. */ @@ -55,7 +55,7 @@ struct one_test_s { int todo_tests; /* number of todo tests that failed as expected. */ int actual_tests; /* number of tests attempted. */ int planned_tests; /* number of planned tests. */ - const char *plan_file; /* full path to file that called plan_tests() */ + const char *_Nonnull plan_file; /* full path to file that called plan_tests() */ int plan_line; /* line number in plan_file at which plan_tests was called. */ unsigned long duration; /* test duration in msecs. */ /* add more later: timing, etc... */ @@ -215,22 +215,22 @@ static void test_failed_noreturn() __attribute((analyzer_noreturn)) { }) -extern const char *test_directive; -extern const char *test_reason; +extern const char * _Nonnull test_directive; +extern const char * _Nonnull test_reason; -void test_bail_out(const char *reason, const char *file, unsigned line); -int test_diag(const char *directive, const char *reason, - const char *file, unsigned line, const char *fmt, ...) __attribute__((format(printf, 5, 6))); -int test_ok(int passed, __attribute((cf_consumed)) CFStringRef description, const char *directive, - const char *reason, const char *file, unsigned line, const char *fmt, ...); -void test_plan_skip_all(const char *reason); -void test_plan_tests(int count, const char *file, unsigned line); +void test_bail_out(const char * _Nonnull reason, const char * _Nonnull file, unsigned line); +int test_diag(const char *_Nonnull directive, const char *_Nonnull reason, + const char *_Nonnull file, unsigned line, const char *_Nonnull fmt, ...) __attribute__((format(printf, 5, 6))); +int test_ok(int passed, __attribute((cf_consumed)) CFStringRef _Nullable description, const char *_Nonnull directive, + const char *_Nonnull reason, const char *_Nonnull file, unsigned line, const char *_Nullable fmt, ...); +void test_plan_skip_all(const char *_Nonnull reason); +void test_plan_tests(int count, const char *_Nonnull file, unsigned line); int test_plan_ok(void); -void test_plan_final(int *failed, int *todo_pass, int *todo, int *actual, int *planned, const char **file, int *line); +void test_plan_final(int *_Nonnull failed, int *_Nonnull todo_pass, int *_Nonnull todo, int *_Nonnull actual, int *_Nonnull planned, const char *_Nonnull *_Nonnull file, int *_Nonnull line); -void test_skip(const char *reason, int how_many, int unless); +void test_skip(const char *_Nonnull reason, int how_many, int unless); -const char *sec_errstr(int err); +const char *_Nonnull sec_errstr(int err); __END_DECLS diff --git a/OSX/sec/Security/AppleExternalRootCertificates.h b/OSX/sec/Security/AppleExternalRootCertificates.h new file mode 100644 index 00000000..392314ca --- /dev/null +++ b/OSX/sec/Security/AppleExternalRootCertificates.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017 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@ + */ + +#ifndef _sec_AppleExternalRootCertificates_h +#define _sec_AppleExternalRootCertificates_h + +#include + +/* subject:/CN=Apple External EC Root/O=Apple Inc./C=US */ +/* issuer :/CN=Apple External EC Root/O=Apple Inc./C=US */ +uint8_t _AppleExternalECRootCA[519]={ + 0x30,0x82,0x02,0x03,0x30,0x82,0x01,0x89,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x76, + 0xAD,0x18,0xDB,0x88,0x12,0xB0,0x56,0xA1,0x26,0x9D,0x44,0x91,0x4E,0xEB,0xD4,0x30, + 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x30,0x43,0x31,0x1F,0x30, + 0x1D,0x06,0x03,0x55,0x04,0x03,0x0C,0x16,0x41,0x70,0x70,0x6C,0x65,0x20,0x45,0x78, + 0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x45,0x43,0x20,0x52,0x6F,0x6F,0x74,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,0x32,0x30,0x30,0x31,0x32,0x33,0x30,0x30,0x34,0x36,0x34,0x38, + 0x5A,0x17,0x0D,0x34,0x35,0x30,0x31,0x31,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x5A, + 0x30,0x43,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x03,0x0C,0x16,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x45,0x43,0x20,0x52, + 0x6F,0x6F,0x74,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,0x17,0xC7,0x4A, + 0xDD,0xD2,0x3C,0xAF,0xB0,0x76,0xA3,0x2A,0x57,0x1E,0x2C,0x7F,0x38,0x0B,0x62,0x04, + 0x75,0x54,0x36,0xBB,0x0E,0xB7,0xAA,0x2C,0x7B,0xF9,0xE8,0xB3,0xC5,0x09,0x08,0xB3, + 0xDF,0x20,0x27,0xB1,0x95,0x96,0x16,0x63,0x46,0x6C,0xFF,0x24,0xA4,0x00,0xF2,0x87, + 0xC1,0x7F,0xED,0xE7,0x28,0x49,0xB3,0x5A,0xBC,0x02,0xAA,0x93,0x47,0x62,0x9E,0x5F, + 0x9F,0x43,0xC9,0xF2,0x25,0x89,0x83,0x62,0x60,0xBB,0x57,0x6A,0x59,0xA8,0x0B,0xB3, + 0x32,0x25,0x75,0xD7,0x8B,0xEF,0xF1,0xD2,0x41,0xD3,0x57,0x90,0x4B,0xA3,0x42,0x30, + 0x40,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01, + 0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x3F,0xA4,0xC0, + 0x94,0x20,0x70,0xCB,0x3B,0xDD,0xA8,0x54,0xE6,0x14,0x1E,0x29,0xCC,0x4D,0x14,0x38, + 0x53,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,0x68,0x00, + 0x30,0x65,0x02,0x31,0x00,0x9D,0x4D,0x05,0x75,0x65,0x76,0xD8,0x70,0x03,0x14,0x39, + 0x8E,0x41,0xC7,0xB2,0xFE,0x53,0xDC,0x6E,0xE6,0x13,0x18,0x51,0x0A,0x1F,0xC4,0xB5, + 0xCF,0x22,0x40,0x75,0x79,0xCA,0x98,0x6E,0xB0,0xF5,0x88,0x71,0x11,0x3E,0x3B,0x7C, + 0x38,0x35,0xD7,0x1F,0xB9,0x02,0x30,0x5B,0x7C,0x87,0xF3,0xF6,0xDD,0x51,0x96,0x6D, + 0xF8,0x7E,0xF2,0x78,0x3A,0xC6,0xA6,0x85,0x55,0xE8,0xBD,0x20,0xAC,0xE1,0x58,0x79, + 0x14,0x50,0x3D,0x54,0xC3,0xF1,0x22,0x15,0x18,0x87,0x95,0x67,0x9E,0x19,0x69,0x89, + 0x51,0x2C,0xD0,0x55,0xEA,0x52,0x6C, +}; + +/* subject:/CN=Test Apple External EC Root/O=Apple Inc./C=US */ +/* issuer :/CN=Test Apple External EC Root/O=Apple Inc./C=US */ +uint8_t _TestAppleExternalECRootCA[530]={ + 0x30,0x82,0x02,0x0E,0x30,0x82,0x01,0x93,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x70, + 0x1B,0x1A,0x15,0x07,0x97,0x6A,0x6A,0x8D,0xBD,0x23,0x36,0xF2,0x48,0x4A,0x4E,0x30, + 0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,0x30,0x48,0x31,0x24,0x30, + 0x22,0x06,0x03,0x55,0x04,0x03,0x0C,0x1B,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x45,0x43,0x20,0x52, + 0x6F,0x6F,0x74,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,0x39,0x31,0x31,0x30,0x35,0x31, + 0x38,0x30,0x30,0x34,0x36,0x5A,0x17,0x0D,0x34,0x34,0x31,0x30,0x32,0x39,0x31,0x38, + 0x30,0x30,0x34,0x36,0x5A,0x30,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x03, + 0x0C,0x1B,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x45,0x78,0x74, + 0x65,0x72,0x6E,0x61,0x6C,0x20,0x45,0x43,0x20,0x52,0x6F,0x6F,0x74,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,0x91,0xC2,0xB5,0xBC,0x6A,0x99,0x8B,0x68,0x5A, + 0xCE,0xD4,0x8C,0x48,0xF1,0x0F,0xD2,0x00,0x8D,0x88,0x6A,0x14,0x53,0xEC,0xFA,0xE7, + 0xCC,0x97,0x01,0x0A,0x64,0x9F,0x69,0xE2,0xF8,0xC8,0x54,0x0E,0xD2,0x7C,0x9A,0x22, + 0xE5,0xEF,0xE1,0x56,0xF3,0x2A,0xB0,0x99,0xAD,0x88,0x4A,0xCE,0x2C,0xD4,0x60,0x90, + 0xF1,0x90,0xA6,0xB0,0x45,0xC4,0x82,0x0B,0xB0,0x46,0xE5,0xE7,0x14,0xCC,0x98,0x9E, + 0x13,0xD0,0x43,0x51,0x64,0x0C,0xCD,0xA6,0xAF,0x5C,0x14,0x52,0x5A,0xF2,0x08,0x8D, + 0xE4,0x04,0x54,0x74,0x13,0x91,0x02,0xA3,0x42,0x30,0x40,0x30,0x0F,0x06,0x03,0x55, + 0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x07,0x6B,0x07,0x47,0x33,0xE4,0x96,0xB4,0xFC, + 0x6F,0xFA,0x32,0x2C,0x8E,0xBE,0x70,0xC2,0x8F,0x80,0x3C,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,0x69,0x00,0x30,0x66,0x02,0x31,0x00,0xED, + 0xC0,0xC6,0x05,0x62,0x3E,0x4C,0x76,0x0C,0x5B,0x62,0xF9,0x54,0x2E,0x90,0xC4,0xDB, + 0x29,0xD1,0x2D,0x2F,0x30,0x15,0x8A,0xCF,0x9F,0xA0,0x5A,0x40,0x6C,0x6A,0x9F,0x76, + 0xC1,0x5E,0xC3,0x37,0x40,0xA1,0x9B,0xA4,0x0D,0x31,0x9D,0x4C,0xBB,0x2B,0xAE,0x02, + 0x31,0x00,0xDA,0xCB,0xE4,0x1D,0x12,0x4E,0x03,0x2F,0x91,0xCF,0x2A,0xB3,0xF4,0xB3, + 0x8D,0x89,0x69,0xF2,0x9B,0xFC,0xB4,0x05,0x95,0x0B,0xCB,0x63,0x12,0xC8,0xAA,0x8D, + 0x58,0xE8,0xF3,0x2A,0xF6,0x36,0x32,0xAC,0x0A,0x24,0x94,0x84,0x85,0x00,0x96,0x62, + 0x62,0x57, +}; + +#endif /* _sec_AppleExternalRootCertificates_h */ diff --git a/OSX/sec/Security/Regressions/otr/otr-00-identity.c b/OSX/sec/Security/Regressions/otr/otr-00-identity.c index 0439e50a..71652028 100644 --- a/OSX/sec/Security/Regressions/otr/otr-00-identity.c +++ b/OSX/sec/Security/Regressions/otr/otr-00-identity.c @@ -30,6 +30,10 @@ #include #include #include +#include +#include +#include +#include static void RegressionsLogError(CFErrorRef error) { if (error == NULL) { @@ -52,13 +56,59 @@ static void RegressionsLogError(CFErrorRef error) { CFReleaseSafe(tempDictionary); } -static int kTestTestCount = 18; +static int kTestTestCount = 27; + +static void otr_00_identity_MessageProtectionKeys() +{ + // We create a MessageProtection-style key. + int32_t keysz32 = 256; + CFNumberRef ksizeNumber = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFDictionaryRef dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom, + kSecAttrKeyClass, kSecAttrKeyClassPrivate, + kSecAttrKeySizeInBits, ksizeNumber, + kSecAttrIsPermanent, kCFBooleanFalse, NULL); + + CFErrorRef error = NULL; + SecKeyRef testIdentityKey = SecKeyCreateRandomKey(dict, &error); + ok(testIdentityKey != NULL, "Failed to create test key."); + + CFReleaseSafe(ksizeNumber); + CFReleaseSafe(dict); + + SecOTRFullIdentityRef identity1 = SecOTRFullIdentityCreateFromSecKeyRef(kCFAllocatorDefault, testIdentityKey, &error); + ok(identity1->isMessageProtectionKey, "Should be MessageProtection Key"); + ok(identity1->privateKeyPersistentRef == NULL, "MessageProtection key shouldn't have a peristent ref."); + + CFMutableDataRef serializeInto = CFDataCreateMutable(kCFAllocatorDefault, 100); + SecOTRFIAppendSerialization(identity1, serializeInto, &error); + + SecOTRFullIdentityRef identity2 = SecOTRFullIdentityCreateFromData(kCFAllocatorDefault, serializeInto, &error); + ok(identity2->isMessageProtectionKey, "Should still be a MessageProtection Key"); + ok(identity2->privateKeyPersistentRef == NULL, "MessageProtection key shouldn't have a peristent ref."); + + CFDataRef serializedKey1 = SecKeyCopyExternalRepresentation(identity1->privateSigningKey, &error); + CFDataRef serializedKey2 = SecKeyCopyExternalRepresentation(identity2->privateSigningKey, &error); + + ok(CFEqual(serializedKey1, serializedKey2)); + ok(error == NULL, "Testing shouldn't cause any errors"); + + CFReleaseSafe(error); + CFReleaseSafe(serializedKey1); + CFReleaseSafe(serializedKey2); + CFReleaseSafe(identity1); + CFReleaseSafe(identity2); + CFReleaseSafe(testIdentityKey); + CFReleaseNull(serializeInto); +} + static void tests(void) { CFErrorRef testError = NULL; SecOTRFullIdentityRef idToPurge = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError); ok(idToPurge != NULL, "Make Identity: %@", testError); + ok(idToPurge->isMessageProtectionKey == false, "Keys shouldn't be defaulting to MessageProtection type"); RegressionsLogError(testError); CFReleaseNull(testError); @@ -70,6 +120,7 @@ static void tests(void) SecOTRFullIdentityRef purgeIdInflate = SecOTRFullIdentityCreateFromData(kCFAllocatorDefault, purgeExport, &testError); ok(purgeIdInflate != NULL, "Inflate Identity: %@", testError); + ok(idToPurge->isMessageProtectionKey == false, "Keys shouldn't be re-imported as MessageProtection types"); RegressionsLogError(testError); CFReleaseNull(testError); @@ -195,8 +246,12 @@ static void tests(void) CFReleaseSafe(failIDInflate2); CFReleaseSafe(testInteropImport); CFReleaseSafe(interopIDInflate); + + otr_00_identity_MessageProtectionKeys(); } + + int otr_00_identity(int argc, char *const *argv) { plan_tests(kTestTestCount); diff --git a/OSX/sec/Security/Regressions/secitem/si-21-sectrust-asr.c b/OSX/sec/Security/Regressions/secitem/si-21-sectrust-asr.c index 0e7e5350..a7a1d78c 100644 --- a/OSX/sec/Security/Regressions/secitem/si-21-sectrust-asr.c +++ b/OSX/sec/Security/Regressions/secitem/si-21-sectrust-asr.c @@ -152,7 +152,7 @@ static void tests(void) "trust is kSecTrustResultOtherError"); } SecKeyRef pub_key_leaf; - isnt(pub_key_leaf = SecTrustCopyPublicKey(trust), NULL, "get leaf pub key"); + isnt(pub_key_leaf = SecTrustCopyKey(trust), NULL, "get leaf pub key"); if (!pub_key_leaf) { goto errOut; } CFErrorRef error = NULL; ok(SecKeyVerifySignature(pub_key_leaf, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, sha1Data, signature, &error), diff --git a/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c b/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c deleted file mode 100644 index bf63ea1b..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Copyright (c) 2006-2018 Apple Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -#include "si-23-sectrust-ocsp.h" - -static void tests(void) -{ - SecTrustRef trust; - SecCertificateRef cert0, cert1; - isnt(cert0 = SecCertificateCreateWithBytes(NULL, _ocsp_c0, sizeof(_ocsp_c0)), - NULL, "create cert0"); - isnt(cert1 = SecCertificateCreateWithBytes(NULL, _ocsp_c1, sizeof(_ocsp_c1)), - NULL, "create cert1"); - CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - CFArrayAppendValue(certs, cert0); - CFArrayAppendValue(certs, cert1); - - SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.apple.com")); - SecPolicyRef ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod); - const void *v_policies[] = { sslPolicy, ocspPolicy }; - CFArrayRef policies = CFArrayCreate(NULL, v_policies, - array_size(v_policies), &kCFTypeArrayCallBacks); - CFRelease(sslPolicy); - CFRelease(ocspPolicy); - ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), - "create trust"); - /* April 14, 2019 at 10:46:40 PM PDT */ - CFDateRef date = CFDateCreate(NULL, 577000000.0); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - - is(SecTrustGetVerifyTime(trust), 577000000.0, "get date"); - - SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - - /* Certificates are only EV if they are also CT. */ - CFDictionaryRef info = SecTrustCopyInfo(trust); - CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(info, - kSecTrustInfoExtendedValidationKey); - ok(ev, "extended validation succeeded"); - - CFReleaseSafe(info); - CFReleaseSafe(trust); - CFReleaseSafe(policies); - CFReleaseSafe(certs); - CFReleaseSafe(cert0); - CFReleaseSafe(cert1); - CFReleaseSafe(date); -} - -static void test_ocsp_responder_policy() { - SecCertificateRef leaf = NULL, subCA = NULL, responderCert = NULL; - CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - SecTrustRef trust = NULL; - SecPolicyRef ocspSignerPolicy = NULL; - SecTrustResultType trustResult = kSecTrustResultInvalid; - - /* August 14, 2018 at 9:26:40 PM PDT */ - CFDateRef date = CFDateCreate(NULL, 556000000.0); - - isnt(leaf = SecCertificateCreateWithBytes(NULL, valid_ist_certificate, - sizeof(valid_ist_certificate)), NULL, "create ist leaf"); - isnt(subCA = SecCertificateCreateWithBytes(NULL, ist_intermediate_certificate, - sizeof(ist_intermediate_certificate)), NULL, "create ist subCA"); - CFArrayAppendValue(certs, leaf); - CFArrayAppendValue(certs, subCA); - - ok(ocspSignerPolicy = SecPolicyCreateOCSPSigner(), - "create ocspSigner policy"); - - ok_status(SecTrustCreateWithCertificates(certs, ocspSignerPolicy, &trust), - "create trust for c0 -> c1"); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, - "trust is kSecTrustResultRecoverableTrustFailure"); - - isnt(responderCert = SecCertificateCreateWithBytes(NULL, _responderCert, - sizeof(_responderCert)), NULL, "create responderCert"); - CFArraySetValueAtIndex(certs, 0, responderCert); - ok_status(SecTrustCreateWithCertificates(certs, ocspSignerPolicy, &trust), - "create trust for ocspResponder -> c1"); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - - CFReleaseNull(leaf); - CFReleaseNull(subCA); - CFReleaseNull(responderCert); - CFReleaseNull(certs); - CFReleaseNull(trust); - CFReleaseSafe(ocspSignerPolicy); - CFReleaseNull(date); -} - -static void test_revocation() { - SecTrustRef trust; - SecCertificateRef rcert0, rcert1; - isnt(rcert0 = SecCertificateCreateWithBytes(NULL, - revoked_ist_certificate, sizeof(revoked_ist_certificate)), - NULL, "create rcert0"); - isnt(rcert1 = SecCertificateCreateWithBytes(NULL, - ist_intermediate_certificate, sizeof(ist_intermediate_certificate)), - NULL, "create rcert1"); - CFMutableArrayRef rcerts = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - CFArrayAppendValue(rcerts, rcert0); - CFArrayAppendValue(rcerts, rcert1); - - SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, CFSTR("revoked.geotrust-global-ca.test-pages.certificatemanager.apple.com")); - SecPolicyRef ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod); - const void *v_policies[] = { sslPolicy, ocspPolicy }; - CFArrayRef policies = CFArrayCreate(NULL, v_policies, - array_size(v_policies), &kCFTypeArrayCallBacks); - CFRelease(sslPolicy); - CFRelease(ocspPolicy); - ok_status(SecTrustCreateWithCertificates(rcerts, policies, &trust), - "create trust"); - /* Feb 5th 2015. */ - CFDateRef date = CFDateCreate(NULL, 444900000); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - CFReleaseSafe(date); - - is(SecTrustGetVerifyTime(trust), 444900000, "get date"); - - SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is((trustResult > kSecTrustResultUnspecified), true, - "trust is %d, expected value greater than 4", (int)trustResult); - CFDictionaryRef results = SecTrustCopyResult(trust); - CFTypeRef revoked = NULL; - if (results) { - CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails")); - if (perCertResults) { - CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0); - if (leafResults) { - revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation")); - } - } - } - is(revoked != NULL, true, "revoked result is %@", revoked); - CFReleaseSafe(results); - - - /* Now verify the cert at a date in the past relative to the previous - date, but still within the cert's validity period. Although the - cached response from our prior attempt will appear to have been - produced in the future, it should still be honored since it's - validly signed. - */ - /* Dec 11th 2014. */ - date = CFDateCreate(NULL, 440000000); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - CFReleaseSafe(date); - - is(SecTrustGetVerifyTime(trust), 440000000, "get date"); - - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is((trustResult > kSecTrustResultUnspecified), true, - "trust is %d, expected value greater than 4", (int)trustResult); - results = SecTrustCopyResult(trust); - revoked = NULL; - if (results) { - CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails")); - if (perCertResults) { - CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0); - if (leafResults) { - revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation")); - } - } - } - is(revoked != NULL, true, "revoked result is %@", revoked); - CFReleaseSafe(results); - - CFReleaseSafe(trust); - CFReleaseSafe(policies); - CFReleaseSafe(rcerts); - CFReleaseSafe(rcert0); - CFReleaseSafe(rcert1); -} - -static void test_forced_revocation() -{ - /* - * Test verification requiring a positive response from the revocation server - */ - - OSStatus status; - SecCertificateRef smime_leaf_cert; - SecCertificateRef smime_CA_cert; - SecCertificateRef smime_root_cert; - - // Import certificates from byte array above - isnt(smime_leaf_cert = SecCertificateCreateWithBytes(NULL, ocsp_smime_leaf_certificate, sizeof(ocsp_smime_leaf_certificate)), - NULL, "SMIME Leaf Cert"); - isnt(smime_CA_cert = SecCertificateCreateWithBytes(NULL, ocsp_smime_CA_certificate, sizeof(ocsp_smime_CA_certificate)), - NULL, "SMIME CA Cert"); - isnt(smime_root_cert = SecCertificateCreateWithBytes(NULL, ocsp_smime_root_certificate, sizeof(ocsp_smime_root_certificate)), - NULL, "SMIME Root Cert"); - - SecPolicyRef smimePolicy = SecPolicyCreateWithProperties(kSecPolicyAppleSMIME, NULL); - SecPolicyRef revocPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod | kSecRevocationRequirePositiveResponse); - isnt(smimePolicy, NULL, "SMIME Policy"); - isnt(revocPolicy, NULL, "SMIME Revocation Policy"); - - // Default Policies - CFMutableArrayRef SMIMEDefaultPolicy = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMEDefaultPolicy, smimePolicy); - - // Default Policies + explicit revocation - CFMutableArrayRef SMIMEDefaultPolicyWithRevocation = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation, smimePolicy); - CFArrayAppendValue(SMIMEDefaultPolicyWithRevocation, revocPolicy); - - // Valid chain of Cert (leaf + CA) - CFMutableArrayRef SMIMECertChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMECertChain, smime_leaf_cert); - CFArrayAppendValue(SMIMECertChain, smime_CA_cert); - - // Valid anchor certs - CFMutableArrayRef SMIMEAnchors = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(SMIMEAnchors, smime_root_cert); - - // Free Resources contained in arrays - CFReleaseSafe(smime_leaf_cert); - CFReleaseSafe(smime_CA_cert); - CFReleaseSafe(smime_root_cert); - CFReleaseSafe(smimePolicy); - CFReleaseSafe(revocPolicy); - - CFDateRef VerifyDate; - isnt(VerifyDate = CFDateCreate(NULL, 332900000.0), NULL, "Create verify date"); - if (!VerifyDate) { goto errOut; } - - // Standard evaluation for the given verify date - { - SecTrustRef trust = NULL; - SecTrustResultType trust_result; - - ok_status(status = SecTrustCreateWithCertificates(SMIMECertChain, SMIMEDefaultPolicy, &trust), - "SecTrustCreateWithCertificates"); - ok_status(SecTrustSetVerifyDate(trust, VerifyDate), "Set date"); - ok_status(SecTrustSetAnchorCertificates(trust, SMIMEAnchors), "Set anchors"); - - ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); - - // Check results - // NOTE: We now expect a fatal error, since the "TC TrustCenter Class 1 L1 CA IX" CA - // is revoked. That CA is no longer present in Valid since the TC root was removed - // from the trust store, and as of May 2018, its OCSP server no longer resolves in DNS. - // However, the OCSP URI for the CA's issuer is still active and reports the CA as revoked. - // - is_status(trust_result, kSecTrustResultFatalTrustFailure, "trust is kSecTrustResultFatalTrustFailure"); - - CFReleaseNull(trust); - } - - // Revocation-required evaluation should fail, since this CA's servers no longer exist - // and no valid responses are available - { - SecTrustRef trust = NULL; - SecTrustResultType trust_result; - - ok_status(status = SecTrustCreateWithCertificates(SMIMECertChain, SMIMEDefaultPolicyWithRevocation, &trust), - "SecTrustCreateWithCertificates"); - ok_status(SecTrustSetVerifyDate(trust, VerifyDate), "Set date"); - ok_status(SecTrustSetAnchorCertificates(trust, SMIMEAnchors), "Set anchors"); - - ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); - - // Check results - // NOTE: We now expect a fatal error, since the "TC TrustCenter Class 1 L1 CA IX" CA - // is revoked. That CA is no longer present in Valid since the TC root was removed - // from the trust store, and as of May 2018, its OCSP server no longer resolves in DNS. - // However, the OCSP URI for the CA's issuer is still active and reports the CA as revoked. - // - is_status(trust_result, kSecTrustResultFatalTrustFailure, "trust is kSecTrustResultFatalTrustFailure"); - - CFReleaseNull(trust); - } - - // Free remaining resources -errOut: - CFReleaseSafe(VerifyDate); - CFReleaseSafe(SMIMEDefaultPolicy); - CFReleaseSafe(SMIMEDefaultPolicyWithRevocation); - CFReleaseSafe(SMIMECertChain); - CFReleaseSafe(SMIMEAnchors); -} - -#if 0 -static void hexdump(const uint8_t *bytes, size_t len) { - size_t ix; - printf("#anchor-sha1: "); - for (ix = 0; ix < len; ++ix) { - printf("%02X", bytes[ix]); - } - printf("\n"); -} - -static void datadump(const uint8_t *bytes, size_t len) { - size_t ix; - printf("#anchor-sha1: "); - for (ix = 0; ix < len; ++ix) { - printf("%c", bytes[ix]); - } - printf("\n"); -} - -static void display_anchor_digest(SecTrustRef trust) { - CFIndex count = SecTrustGetCertificateCount(trust); - SecCertificateRef anchor = SecTrustGetCertificateAtIndex(trust, count - 1); - CFDataRef digest = SecCertificateGetSHA1Digest(anchor); - CFDataRef xml = CFPropertyListCreateXMLData(NULL, digest); - datadump(CFDataGetBytePtr(xml), CFDataGetLength(xml)); -} -#endif - -static void test_aia(void) { - SecCertificateRef ovh = NULL, comodo_ev = NULL, comodo_aia = NULL; - CFMutableArrayRef certs = NULL, policies = NULL; - SecPolicyRef sslPolicy = NULL, revPolicy = NULL; - CFDateRef verifyDate = NULL; - CFDictionaryRef info = NULL; - SecTrustRef trust = NULL; - SecTrustResultType trustResult = kSecTrustResultInvalid; - CFBooleanRef ev = NULL; - - /* Initialize common variables */ - isnt(ovh = SecCertificateCreateWithBytes(NULL, ovh_certificate, - sizeof(ovh_certificate)), NULL, "create ovh cert"); - isnt(comodo_ev = SecCertificateCreateWithBytes(NULL, comodo_ev_certificate, - sizeof(comodo_ev_certificate)), NULL, "create comodo_ev cert"); - isnt(comodo_aia = SecCertificateCreateWithBytes(NULL, - comodo_aia_certificate, sizeof(comodo_aia_certificate)), NULL, - "create comodo_aia cert"); - certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - policies = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - sslPolicy = SecPolicyCreateSSL(false, NULL); // For now, use SSL client policy to avoid SHA-1 deprecation - revPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); - CFArrayAppendValue(policies, sslPolicy); - CFArrayAppendValue(policies, revPolicy); - /* May 9th 2018. */ - verifyDate = CFDateCreate(NULL, 547600500); - - /* First run with no intermediate and disallow network fetching. - * Evaluation should fail because it couldn't get the intermediate. */ - CFArrayAppendValue(certs, ovh); - ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), - "create trust"); - ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); - ok_status(SecTrustSetNetworkFetchAllowed(trust, false), "set no network"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, - "trust is kSecTrustResultRecoverableTrustFailure"); - - /* Now allow networking. Evaluation should succeed after fetching - * the intermediate. */ - ok_status(SecTrustSetNetworkFetchAllowed(trust, true), "set allow network"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - CFReleaseNull(trust); - - /* Now run with the intermediate returned by the ssl server. */ - CFArrayAppendValue(certs, comodo_ev); - ok_status(SecTrustCreateWithCertificates(certs, sslPolicy, &trust), - "create trust"); - ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - info = SecTrustCopyInfo(trust); - ev = (CFBooleanRef)CFDictionaryGetValue(info, - kSecTrustInfoExtendedValidationKey); - ok(ev, "extended validation succeeded due to caissuers fetch"); - //display_anchor_digest(trust); - CFReleaseSafe(info); - CFReleaseSafe(trust); - - /* Now run with the intermediate returned by following the url in the - Certificate Access Information Authority (AIA) extension of the ovh - leaf certificate. */ - CFArrayAppendValue(certs, comodo_aia); - ok_status(SecTrustCreateWithCertificates(certs, sslPolicy, &trust), - "re-create trust with aia intermediate"); - ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - info = SecTrustCopyInfo(trust); - ev = (CFBooleanRef)CFDictionaryGetValue(info, - kSecTrustInfoExtendedValidationKey); - ok(ev, "extended validation succeeded"); - //display_anchor_digest(trust); - CFReleaseSafe(info); - CFReleaseSafe(trust); - - /* Now run with the intermediate returned by following the url in the - Certificate Access Information Authority (AIA) extension of the ovh - leaf certificate. */ - CFArrayRemoveValueAtIndex(certs, 1); - ok_status(SecTrustCreateWithCertificates(certs, sslPolicy, &trust), - "re-create trust with aia intermediate"); - ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - info = SecTrustCopyInfo(trust); - ev = (CFBooleanRef)CFDictionaryGetValue(info, - kSecTrustInfoExtendedValidationKey); - ok(ev, "extended validation succeeded"); - //display_anchor_digest(trust); - CFReleaseSafe(info); - CFReleaseSafe(trust); - - /* Common variable cleanup. */ - CFReleaseSafe(sslPolicy); - CFReleaseSafe(revPolicy); - CFReleaseSafe(certs); - CFReleaseSafe(policies); - CFReleaseSafe(comodo_aia); - CFReleaseSafe(comodo_ev); - CFReleaseSafe(ovh); - CFReleaseSafe(verifyDate); -} - -static void test_aia_https(void) { - SecCertificateRef leaf = NULL; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFArrayRef certs = NULL; - CFDateRef verifyDate = NULL; - CFErrorRef error = NULL; - - leaf = SecCertificateCreateWithBytes(NULL, _caissuer_https, sizeof(_caissuer_https)); - const void *v_certs[] = { leaf }; - - certs = CFArrayCreate(NULL, v_certs, 1, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateSSL(true, CFSTR("example.com")); - require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); - - verifyDate = CFDateCreate(NULL, 546700000.0); // April 29, 2018 at 6:06:40 AM PDT - require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - /* Evaluate trust. This cert does not chain to anything trusted and we can't fetch an - * intermediate because the URI is https. */ - is(SecTrustEvaluateWithError(trust, &error), false, "leaf with missing intermediate and https CAIssuer URI succeeded"); - if (error) { - is(CFErrorGetCode(error), errSecCreateChainFailed, "got wrong error code for revoked cert, got %ld, expected %d", - (long)CFErrorGetCode(error), errSecCreateChainFailed); - } else { - fail("expected trust evaluation to fail and it did not."); - } -#pragma clang diagnostic pop - -errOut: - CFReleaseNull(leaf); - CFReleaseNull(policy); - CFReleaseNull(trust); - CFReleaseNull(certs); - CFReleaseNull(verifyDate); - CFReleaseNull(error); -} - -static void test_results_dictionary_revocation_reason(void) { - SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFArrayRef certs = NULL, anchors = NULL; - CFDateRef verifyDate = NULL; - CFErrorRef error = NULL; - CFDataRef ocspResponse = NULL; - - leaf = SecCertificateCreateWithBytes(NULL, _probablyRevokedLeaf, sizeof(_probablyRevokedLeaf)); - subCA = SecCertificateCreateWithBytes(NULL, _digiCertSha2SubCA, sizeof(_digiCertSha2SubCA)); - root = SecCertificateCreateWithBytes(NULL, _digiCertGlobalRoot, sizeof(_digiCertGlobalRoot)); - - const void *v_certs[] = { leaf, subCA }; - const void *v_anchors[] = { root }; - - certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateSSL(true, CFSTR("revoked.badssl.com")); - require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); - - anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); - require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors")); - - verifyDate = CFDateCreate(NULL, 543000000.0); // March 17, 2018 at 10:20:00 AM PDT - require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); - - /* Set the stapled response */ - ocspResponse = CFDataCreate(NULL, _digicertOCSPResponse, sizeof(_digicertOCSPResponse)); - ok_status(SecTrustSetOCSPResponse(trust, ocspResponse), "failed to set OCSP response"); - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - /* Evaluate trust. This cert is revoked, but is only listed as "probably revoked" by valid.apple.com. - * This cert should come back as revoked. */ - is(SecTrustEvaluateWithError(trust, &error), false, "revoked cert succeeded"); - if (error) { - is(CFErrorGetCode(error), errSecCertificateRevoked, "got wrong error code for revoked cert, got %ld, expected %d", - (long)CFErrorGetCode(error), errSecCertificateRevoked); - - /* Verify that the results dictionary contains all the right keys for a revoked cert */ - CFDictionaryRef result = SecTrustCopyResult(trust); - isnt(result, NULL, "failed to copy result dictionary"); - if (result) { - int64_t reason = -1; - CFNumberRef cfreason = CFNumberCreate(NULL, kCFNumberSInt64Type, &reason); - is(CFNumberCompare(cfreason, CFDictionaryGetValue(result, kSecTrustRevocationReason), NULL), kCFCompareEqualTo, "expected revocation reason -1"); - CFReleaseNull(cfreason); - } - CFReleaseNull(result); - } else { - fail("expected trust evaluation to fail and it did not."); - } -#pragma clang diagnostic pop - -errOut: - CFReleaseNull(leaf); - CFReleaseNull(subCA); - CFReleaseNull(root); - CFReleaseNull(policy); - CFReleaseNull(trust); - CFReleaseNull(certs); - CFReleaseNull(anchors); - CFReleaseNull(verifyDate); - CFReleaseNull(error); - CFReleaseNull(ocspResponse); -} - -static void test_results_dictionary_revocation_checked(void) { - SecCertificateRef leaf = NULL, subCA = NULL, root = NULL; - SecPolicyRef sslPolicy = NULL, ocspPolicy = NULL; - SecTrustRef trust = NULL; - CFArrayRef certs = NULL, anchors = NULL, policies = NULL; - CFDateRef verifyDate = NULL; - CFErrorRef error = NULL; - - leaf = SecCertificateCreateWithBytes(NULL, _ocsp_c0, sizeof(_ocsp_c0)); - subCA = SecCertificateCreateWithBytes(NULL, _ocsp_c1, sizeof(_ocsp_c1)); - root = SecCertificateCreateWithBytes(NULL, _ocsp_c2, sizeof(_ocsp_c2)); - - sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.apple.com")); - ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod); - - const void *v_certs[] = { leaf, subCA }; - const void *v_anchors[] = { root }; - const void *v_policies[] = { sslPolicy, ocspPolicy }; - - certs = CFArrayCreate(NULL, v_certs, 2, &kCFTypeArrayCallBacks); - policies = CFArrayCreate(NULL, v_policies, 2, &kCFTypeArrayCallBacks); - require_noerr_action(SecTrustCreateWithCertificates(certs, policies, &trust), errOut, fail("failed to create trust object")); - - anchors = CFArrayCreate(NULL, v_anchors, 1, &kCFTypeArrayCallBacks); - require_noerr_action(SecTrustSetAnchorCertificates(trust, anchors), errOut, fail("failed to set anchors")); - - verifyDate = CFDateCreate(NULL, 577000000.0); // April 14, 2019 at 10:46:40 PM PDT - require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability-new" - is(SecTrustEvaluateWithError(trust, &error), true, "valid cert failed"); - - /* Verify that the results dictionary contains all the right keys for a valid cert where revocation checked */ - CFDictionaryRef result = SecTrustCopyResult(trust); - isnt(result, NULL, "failed to copy result dictionary"); - if (result) { - is(CFDictionaryGetValue(result, kSecTrustRevocationChecked), kCFBooleanTrue, "expected revocation checked flag"); - CFDateRef validUntil = CFDictionaryGetValue(result, kSecTrustRevocationValidUntilDate); - isnt(validUntil, NULL, "expected revocation valid until date"); - if (validUntil) { - ok(CFDateGetAbsoluteTime(validUntil) > CFAbsoluteTimeGetCurrent(), "expected valid until date in the future"); - } else { - fail("did not get valid until date"); - } - } - CFReleaseNull(result); -#pragma clang diagnostic pop - -errOut: - CFReleaseNull(leaf); - CFReleaseNull(subCA); - CFReleaseNull(root); - CFReleaseNull(ocspPolicy); - CFReleaseNull(sslPolicy); - CFReleaseNull(trust); - CFReleaseNull(certs); - CFReleaseNull(anchors); - CFReleaseNull(policies); - CFReleaseNull(verifyDate); - CFReleaseNull(error); -} - -static int ping_host(char *host_name){ - - struct sockaddr_in pin; - struct hostent *nlp_host; - int sd; - int port; - int retries = 5; - - port=80; - - //tries 5 times then give up - while ((nlp_host=gethostbyname(host_name))==0 && retries--){ - printf("Resolve Error! (%s) %d\n", host_name, h_errno); - sleep(1); - } - - if(nlp_host==0) - return 0; - - bzero(&pin,sizeof(pin)); - pin.sin_family=AF_INET; - pin.sin_addr.s_addr=htonl(INADDR_ANY); - pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr; - pin.sin_port=htons(port); - - sd=socket(AF_INET,SOCK_STREAM,0); - - if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){ - printf("connect error! (%s) %d\n", host_name, errno); - close(sd); - return 0; - } - else{ - close(sd); - return 1; - } -} - -int si_23_sectrust_ocsp(int argc, char *const *argv) -{ - char *hosts[] = { - "EVSecure-ocsp.verisign.com", - "EVIntl-ocsp.verisign.com", - "EVIntl-aia.verisign.com", - "ocsp.comodoca.com", - "crt.comodoca.com", - "ocsp.entrust.net", - "ocsp.digicert.com", - }; - - unsigned host_cnt = 0; - - plan_tests(105); - - for (host_cnt = 0; host_cnt < sizeof(hosts)/sizeof(hosts[0]); host_cnt ++) { - if(!ping_host(hosts[host_cnt])) { - printf("Accessing specific server (%s) failed, check the network!\n", hosts[host_cnt]); - return 0; - } - } - - tests(); - test_ocsp_responder_policy(); - test_aia(); - test_aia_https(); - test_revocation(); - test_forced_revocation(); - test_results_dictionary_revocation_reason(); - test_results_dictionary_revocation_checked(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.h b/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.h deleted file mode 100644 index cc78fcf5..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.h +++ /dev/null @@ -1,1603 +0,0 @@ -/* - * Copyright (c) 2018 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@ - */ - - -#ifndef _SECURITY_SI_23_SECTRUST_OCSP_H_ -#define _SECURITY_SI_23_SECTRUST_OCSP_H_ - -/* subject:/businessCategory=Private Organization/jurisdictionCountryName=US/jurisdictionStateOrProvinceName=California/serialNumber=C0806592/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Internet Services for Akamai/CN=www.apple.com */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA */ -static const uint8_t _ocsp_c0[]={ - 0x30,0x82,0x06,0xF1,0x30,0x82,0x05,0xD9,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x0F, - 0x8E,0x4E,0x4C,0x9C,0xF5,0x5E,0xA5,0xFE,0x2E,0x9B,0x2B,0x7E,0xFF,0xDE,0x8F,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x75, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x34,0x30,0x32,0x06,0x03,0x55,0x04,0x03,0x13,0x2B,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x53,0x48,0x41,0x32,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64, - 0x20,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x72,0x76, - 0x65,0x72,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x39,0x30,0x33,0x30,0x37,0x30, - 0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x30,0x30,0x33,0x30,0x37,0x31,0x32, - 0x30,0x30,0x30,0x30,0x5A,0x30,0x81,0xEE,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04, - 0x0F,0x0C,0x14,0x50,0x72,0x69,0x76,0x61,0x74,0x65,0x20,0x4F,0x72,0x67,0x61,0x6E, - 0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x31,0x13,0x30,0x11,0x06,0x0B,0x2B,0x06,0x01, - 0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,0x13,0x02,0x55,0x53,0x31,0x1B,0x30,0x19, - 0x06,0x0B,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x02,0x13,0x0A,0x43, - 0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x11,0x30,0x0F,0x06,0x03,0x55, - 0x04,0x05,0x13,0x08,0x43,0x30,0x38,0x30,0x36,0x35,0x39,0x32,0x31,0x0B,0x30,0x09, - 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55, - 0x04,0x08,0x13,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12, - 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, - 0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70, - 0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B, - 0x13,0x1C,0x49,0x6E,0x74,0x65,0x72,0x6E,0x65,0x74,0x20,0x53,0x65,0x72,0x76,0x69, - 0x63,0x65,0x73,0x20,0x66,0x6F,0x72,0x20,0x41,0x6B,0x61,0x6D,0x61,0x69,0x31,0x16, - 0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x77,0x77,0x77,0x2E,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,0xED,0x5E,0x5D,0xC6,0x85,0xBE,0xE5,0x2A,0x78, - 0x7A,0x1F,0x77,0x1F,0x42,0x17,0xEA,0xC1,0xE3,0x75,0xAE,0xC9,0x38,0x7A,0xE0,0xCF, - 0x9F,0xEB,0xBA,0x47,0x42,0xCF,0x63,0x75,0x26,0xD3,0x4C,0x8E,0x6C,0x2F,0xC7,0xBC, - 0x1C,0xBB,0x37,0xC9,0xA5,0xA0,0xD3,0x8F,0xEA,0x3D,0x02,0xC8,0xE8,0x06,0xA1,0xA7, - 0x2B,0x4C,0x7B,0x91,0x55,0xBC,0x51,0xAB,0xE7,0xC8,0xB8,0xA8,0xA6,0x49,0x3E,0x94, - 0x45,0xF1,0x00,0x90,0x26,0xB9,0xB5,0xAF,0xB5,0xA0,0x22,0x41,0x2C,0x10,0x52,0x8B, - 0xD9,0xF0,0x91,0xE5,0x40,0x76,0x60,0xFD,0xC2,0xB1,0xFE,0xD0,0x55,0xC3,0x4F,0x18, - 0x7D,0x20,0x00,0x0C,0x8B,0x41,0x2C,0x2D,0xC1,0x0A,0xC0,0xE1,0x2E,0xDE,0xF8,0x47, - 0x84,0xB2,0x36,0x4E,0x03,0x5F,0x77,0x90,0xF6,0xF5,0x60,0xD8,0xAA,0x25,0x10,0xEB, - 0x37,0x38,0x03,0x7F,0x4B,0x46,0x36,0x76,0x2E,0x66,0xFE,0x18,0xE4,0x9B,0x31,0xEC, - 0xD5,0x2A,0xDB,0x60,0x90,0xD7,0xA0,0xD5,0xAB,0x79,0x9C,0x01,0xF6,0xAC,0x87,0x88, - 0x73,0x43,0x08,0xE0,0x48,0xF0,0x09,0xAC,0x41,0x40,0x60,0xE4,0x9C,0xA7,0xCC,0xBD, - 0x2F,0xC7,0x5D,0x32,0x32,0x2E,0x42,0xD7,0x69,0x2F,0x46,0x30,0xD3,0x6E,0x17,0xBA, - 0x1C,0xA6,0xBA,0xBC,0xB5,0x62,0x53,0x89,0xC7,0x4A,0xEF,0xB9,0xF8,0x0F,0x25,0x2F, - 0xB4,0x7A,0x5C,0x05,0xFB,0xE4,0xFD,0x13,0x47,0x1B,0xFF,0x60,0x6F,0x40,0xF2,0x0F, - 0x2D,0x53,0x38,0x3F,0x21,0x87,0x4D,0x08,0xB1,0x1B,0xD3,0xDA,0xAB,0xD5,0x9E,0x94, - 0x69,0x43,0xA3,0xA2,0x5E,0xF1,0xE9,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x03,0x01, - 0x30,0x82,0x02,0xFD,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80, - 0x14,0x3D,0xD3,0x50,0xA5,0xD6,0xA0,0xAD,0xEE,0xF3,0x4A,0x60,0x0A,0x65,0xD3,0x21, - 0xD4,0xF8,0xF8,0xD6,0x0F,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, - 0xD8,0xF5,0xFF,0x6D,0xDC,0x96,0x30,0x5C,0xAD,0x80,0x75,0xFF,0xCE,0xC5,0xF7,0x9D, - 0x16,0x73,0xCB,0x16,0x30,0x2A,0x06,0x03,0x55,0x1D,0x11,0x04,0x23,0x30,0x21,0x82, - 0x10,0x69,0x6D,0x61,0x67,0x65,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F, - 0x6D,0x82,0x0D,0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, - 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01, - 0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30, - 0x75,0x06,0x03,0x55,0x1D,0x1F,0x04,0x6E,0x30,0x6C,0x30,0x34,0xA0,0x32,0xA0,0x30, - 0x86,0x2E,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x33,0x2E,0x64,0x69, - 0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x68,0x61,0x32,0x2D, - 0x65,0x76,0x2D,0x73,0x65,0x72,0x76,0x65,0x72,0x2D,0x67,0x32,0x2E,0x63,0x72,0x6C, - 0x30,0x34,0xA0,0x32,0xA0,0x30,0x86,0x2E,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63, - 0x72,0x6C,0x34,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D, - 0x2F,0x73,0x68,0x61,0x32,0x2D,0x65,0x76,0x2D,0x73,0x65,0x72,0x76,0x65,0x72,0x2D, - 0x67,0x32,0x2E,0x63,0x72,0x6C,0x30,0x4B,0x06,0x03,0x55,0x1D,0x20,0x04,0x44,0x30, - 0x42,0x30,0x37,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xFD,0x6C,0x02,0x01,0x30,0x2A, - 0x30,0x28,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74, - 0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65, - 0x72,0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x07,0x06,0x05,0x67,0x81, - 0x0C,0x01,0x01,0x30,0x81,0x88,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, - 0x04,0x7C,0x30,0x7A,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, - 0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69, - 0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x52,0x06,0x08,0x2B,0x06, - 0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63, - 0x61,0x63,0x65,0x72,0x74,0x73,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E, - 0x63,0x6F,0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x53,0x48,0x41,0x32, - 0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69, - 0x6F,0x6E,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x09, - 0x06,0x03,0x55,0x1D,0x13,0x04,0x02,0x30,0x00,0x30,0x82,0x01,0x04,0x06,0x0A,0x2B, - 0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02,0x04,0x81,0xF5,0x04,0x81,0xF2,0x00, - 0xF0,0x00,0x76,0x00,0xBB,0xD9,0xDF,0xBC,0x1F,0x8A,0x71,0xB5,0x93,0x94,0x23,0x97, - 0xAA,0x92,0x7B,0x47,0x38,0x57,0x95,0x0A,0xAB,0x52,0xE8,0x1A,0x90,0x96,0x64,0x36, - 0x8E,0x1E,0xD1,0x85,0x00,0x00,0x01,0x69,0x58,0x42,0xD1,0x06,0x00,0x00,0x04,0x03, - 0x00,0x47,0x30,0x45,0x02,0x20,0x68,0x81,0x0C,0x54,0x88,0x45,0x7A,0xC6,0x84,0xB8, - 0x65,0x9B,0xFD,0x9C,0x34,0x80,0xF6,0x38,0x91,0xEF,0xCF,0x58,0xF9,0xFD,0xF3,0x50, - 0x6F,0xAD,0x8E,0xA0,0xAD,0xE8,0x02,0x21,0x00,0xCE,0x32,0x9D,0x5B,0x3D,0xA2,0x8B, - 0xB6,0x04,0x48,0xEE,0x01,0x26,0x6C,0xD3,0x50,0xA1,0xEA,0x7F,0x25,0x0C,0x00,0x2A, - 0x42,0x6D,0x42,0x0D,0x13,0xC0,0xA9,0x85,0xBC,0x00,0x76,0x00,0x56,0x14,0x06,0x9A, - 0x2F,0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC, - 0x99,0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x69, - 0x58,0x42,0xD1,0x44,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x4B,0xD4, - 0x64,0x52,0xD3,0x52,0xF0,0x3E,0xD8,0xD4,0x3D,0xC5,0x40,0x72,0xED,0xC3,0x04,0x8C, - 0x3C,0x16,0x46,0x5D,0x38,0x02,0xBA,0xA2,0x1E,0x52,0xAA,0xE1,0xDA,0xB6,0x02,0x21, - 0x00,0xA3,0x5E,0x2F,0x6B,0xCC,0xB9,0x34,0xD9,0xA4,0x00,0x70,0xE1,0x3A,0x99,0xB4, - 0x0D,0x25,0x6D,0xD3,0x59,0x77,0xC2,0x98,0x8C,0x6A,0xA0,0xAE,0xA7,0xE1,0x06,0x73, - 0x32,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, - 0x03,0x82,0x01,0x01,0x00,0x3F,0xD9,0xA1,0x19,0xB3,0x7C,0x56,0xA5,0x89,0xE5,0xA2, - 0x33,0x33,0xE3,0xFC,0xBB,0x29,0xDB,0xD7,0x69,0x76,0x31,0x2F,0x69,0x97,0x90,0xA1, - 0x0C,0x11,0x0B,0x5A,0xCB,0xAB,0x41,0x66,0xB2,0x9B,0xDF,0x71,0xD6,0xDC,0x92,0x91, - 0xB6,0x17,0x8B,0xD3,0x9C,0x83,0x3C,0xDC,0x7C,0xA7,0x29,0x5D,0xBA,0x38,0x97,0x9B, - 0x0D,0x07,0xE0,0x46,0xCA,0x27,0x5F,0x41,0xA0,0xC0,0x84,0x1E,0x47,0x00,0xDC,0x87, - 0x79,0xFD,0xAF,0x3E,0x34,0xC2,0x6D,0xB1,0x47,0x0C,0x52,0x14,0x81,0xAC,0xB2,0x6C, - 0xB4,0x30,0xB2,0x41,0x61,0x77,0x07,0x96,0x05,0x5B,0x26,0x36,0xA2,0x94,0xC2,0x70, - 0xC3,0xCD,0xC1,0x15,0xAC,0x33,0x0D,0x60,0x68,0xFA,0x19,0x95,0x3E,0x28,0x14,0xDE, - 0x19,0x15,0xF2,0x4B,0x43,0xAB,0x00,0xBF,0x54,0xE3,0xAF,0x5A,0x29,0x0F,0x32,0xCB, - 0xCC,0xBE,0x7F,0x07,0x30,0xF6,0xD9,0x49,0xE6,0x27,0x1F,0xC0,0x3B,0x9C,0x3D,0x2E, - 0xD1,0x6C,0xC5,0xB6,0x0E,0x8D,0x17,0xDC,0x48,0x5C,0x1F,0xC1,0x7E,0x4B,0xBA,0x8C, - 0x43,0xCA,0xAF,0x99,0x76,0x88,0x9B,0xA4,0x68,0x60,0xFA,0xC2,0xD3,0x87,0xEF,0x39, - 0x16,0x8C,0x49,0x36,0x2C,0x09,0xF9,0x07,0x2A,0x2E,0x7B,0x61,0x3E,0x76,0x76,0xEF, - 0x74,0x96,0xA5,0xAE,0xFF,0x6B,0x4C,0xF7,0x7F,0x96,0x41,0xBE,0x9C,0x09,0x41,0xBA, - 0x8A,0x1C,0xFD,0xC2,0x4A,0xE1,0x0A,0xA8,0x7E,0x7B,0xA8,0x98,0xA8,0x01,0x5D,0xAB, - 0xEF,0xDB,0x36,0xB3,0xE6,0x93,0x5D,0x27,0x0C,0x26,0xC3,0x33,0x93,0x74,0xAF,0x79, - 0x81,0xE5,0xD4,0x46,0x4E, -}; - -/* subject:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA */ -static const uint8_t _ocsp_c1[]= { - 0x30,0x82,0x04,0xB6,0x30,0x82,0x03,0x9E,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x0C, - 0x79,0xA9,0x44,0xB0,0x8C,0x11,0x95,0x20,0x92,0x61,0x5F,0xE2,0x6B,0x1D,0x83,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x6C, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x48,0x69,0x67,0x68,0x20,0x41,0x73,0x73,0x75,0x72,0x61,0x6E,0x63, - 0x65,0x20,0x45,0x56,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, - 0x31,0x33,0x31,0x30,0x32,0x32,0x31,0x32,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32, - 0x38,0x31,0x30,0x32,0x32,0x31,0x32,0x30,0x30,0x30,0x30,0x5A,0x30,0x75,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x20,0x49, - 0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77,0x77,0x77, - 0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31,0x34,0x30, - 0x32,0x06,0x03,0x55,0x04,0x03,0x13,0x2B,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x53,0x48,0x41,0x32,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56, - 0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x72,0x76,0x65,0x72, - 0x20,0x43,0x41,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,0xD7,0x53,0xA4,0x04,0x51,0xF8,0x99,0xA6,0x16,0x48,0x4B,0x67, - 0x27,0xAA,0x93,0x49,0xD0,0x39,0xED,0x0C,0xB0,0xB0,0x00,0x87,0xF1,0x67,0x28,0x86, - 0x85,0x8C,0x8E,0x63,0xDA,0xBC,0xB1,0x40,0x38,0xE2,0xD3,0xF5,0xEC,0xA5,0x05,0x18, - 0xB8,0x3D,0x3E,0xC5,0x99,0x17,0x32,0xEC,0x18,0x8C,0xFA,0xF1,0x0C,0xA6,0x64,0x21, - 0x85,0xCB,0x07,0x10,0x34,0xB0,0x52,0x88,0x2B,0x1F,0x68,0x9B,0xD2,0xB1,0x8F,0x12, - 0xB0,0xB3,0xD2,0xE7,0x88,0x1F,0x1F,0xEF,0x38,0x77,0x54,0x53,0x5F,0x80,0x79,0x3F, - 0x2E,0x1A,0xAA,0xA8,0x1E,0x4B,0x2B,0x0D,0xAB,0xB7,0x63,0xB9,0x35,0xB7,0x7D,0x14, - 0xBC,0x59,0x4B,0xDF,0x51,0x4A,0xD2,0xA1,0xE2,0x0C,0xE2,0x90,0x82,0x87,0x6A,0xAE, - 0xEA,0xD7,0x64,0xD6,0x98,0x55,0xE8,0xFD,0xAF,0x1A,0x50,0x6C,0x54,0xBC,0x11,0xF2, - 0xFD,0x4A,0xF2,0x9D,0xBB,0x7F,0x0E,0xF4,0xD5,0xBE,0x8E,0x16,0x89,0x12,0x55,0xD8, - 0xC0,0x71,0x34,0xEE,0xF6,0xDC,0x2D,0xEC,0xC4,0x87,0x25,0x86,0x8D,0xD8,0x21,0xE4, - 0xB0,0x4D,0x0C,0x89,0xDC,0x39,0x26,0x17,0xDD,0xF6,0xD7,0x94,0x85,0xD8,0x04,0x21, - 0x70,0x9D,0x6F,0x6F,0xFF,0x5C,0xBA,0x19,0xE1,0x45,0xCB,0x56,0x57,0x28,0x7E,0x1C, - 0x0D,0x41,0x57,0xAA,0xB7,0xB8,0x27,0xBB,0xB1,0xE4,0xFA,0x2A,0xEF,0x21,0x23,0x75, - 0x1A,0xAD,0x2D,0x9B,0x86,0x35,0x8C,0x9C,0x77,0xB5,0x73,0xAD,0xD8,0x94,0x2D,0xE4, - 0xF3,0x0C,0x9D,0xEE,0xC1,0x4E,0x62,0x7E,0x17,0xC0,0x71,0x9E,0x2C,0xDE,0xF1,0xF9, - 0x10,0x28,0x19,0x33,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x49,0x30,0x82,0x01, - 0x45,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01, - 0x01,0xFF,0x02,0x01,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, - 0x04,0x03,0x02,0x01,0x86,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x03,0x02,0x30,0x34,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, - 0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, - 0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69, - 0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x4B,0x06,0x03,0x55,0x1D, - 0x1F,0x04,0x44,0x30,0x42,0x30,0x40,0xA0,0x3E,0xA0,0x3C,0x86,0x3A,0x68,0x74,0x74, - 0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x34,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72, - 0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x48,0x69, - 0x67,0x68,0x41,0x73,0x73,0x75,0x72,0x61,0x6E,0x63,0x65,0x45,0x56,0x52,0x6F,0x6F, - 0x74,0x43,0x41,0x2E,0x63,0x72,0x6C,0x30,0x3D,0x06,0x03,0x55,0x1D,0x20,0x04,0x36, - 0x30,0x34,0x30,0x32,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x2A,0x30,0x28,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70,0x73,0x3A, - 0x2F,0x2F,0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63, - 0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, - 0x14,0x3D,0xD3,0x50,0xA5,0xD6,0xA0,0xAD,0xEE,0xF3,0x4A,0x60,0x0A,0x65,0xD3,0x21, - 0xD4,0xF8,0xF8,0xD6,0x0F,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, - 0x80,0x14,0xB1,0x3E,0xC3,0x69,0x03,0xF8,0xBF,0x47,0x01,0xD4,0x98,0x26,0x1A,0x08, - 0x02,0xEF,0x63,0x64,0x2B,0xC3,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, - 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x9D,0xB6,0xD0,0x90,0x86,0xE1, - 0x86,0x02,0xED,0xC5,0xA0,0xF0,0x34,0x1C,0x74,0xC1,0x8D,0x76,0xCC,0x86,0x0A,0xA8, - 0xF0,0x4A,0x8A,0x42,0xD6,0x3F,0xC8,0xA9,0x4D,0xAD,0x7C,0x08,0xAD,0xE6,0xB6,0x50, - 0xB8,0xA2,0x1A,0x4D,0x88,0x07,0xB1,0x29,0x21,0xDC,0xE7,0xDA,0xC6,0x3C,0x21,0xE0, - 0xE3,0x11,0x49,0x70,0xAC,0x7A,0x1D,0x01,0xA4,0xCA,0x11,0x3A,0x57,0xAB,0x7D,0x57, - 0x2A,0x40,0x74,0xFD,0xD3,0x1D,0x85,0x18,0x50,0xDF,0x57,0x47,0x75,0xA1,0x7D,0x55, - 0x20,0x2E,0x47,0x37,0x50,0x72,0x8C,0x7F,0x82,0x1B,0xD2,0x62,0x8F,0x2D,0x03,0x5A, - 0xDA,0xC3,0xC8,0xA1,0xCE,0x2C,0x52,0xA2,0x00,0x63,0xEB,0x73,0xBA,0x71,0xC8,0x49, - 0x27,0x23,0x97,0x64,0x85,0x9E,0x38,0x0E,0xAD,0x63,0x68,0x3C,0xBA,0x52,0x81,0x58, - 0x79,0xA3,0x2C,0x0C,0xDF,0xDE,0x6D,0xEB,0x31,0xF2,0xBA,0xA0,0x7C,0x6C,0xF1,0x2C, - 0xD4,0xE1,0xBD,0x77,0x84,0x37,0x03,0xCE,0x32,0xB5,0xC8,0x9A,0x81,0x1A,0x4A,0x92, - 0x4E,0x3B,0x46,0x9A,0x85,0xFE,0x83,0xA2,0xF9,0x9E,0x8C,0xA3,0xCC,0x0D,0x5E,0xB3, - 0x3D,0xCF,0x04,0x78,0x8F,0x14,0x14,0x7B,0x32,0x9C,0xC7,0x00,0xA6,0x5C,0xC4,0xB5, - 0xA1,0x55,0x8D,0x5A,0x56,0x68,0xA4,0x22,0x70,0xAA,0x3C,0x81,0x71,0xD9,0x9D,0xA8, - 0x45,0x3B,0xF4,0xE5,0xF6,0xA2,0x51,0xDD,0xC7,0x7B,0x62,0xE8,0x6F,0x0C,0x74,0xEB, - 0xB8,0xDA,0xF8,0xBF,0x87,0x0D,0x79,0x50,0x91,0x90,0x9B,0x18,0x3B,0x91,0x59,0x27, - 0xF1,0x35,0x28,0x13,0xAB,0x26,0x7E,0xD5,0xF7,0x7A, -}; - -/* subject:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA */ -static const uint8_t _ocsp_c2[]= { - 0x30,0x82,0x03,0xC5,0x30,0x82,0x02,0xAD,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x02, - 0xAC,0x5C,0x26,0x6A,0x0B,0x40,0x9B,0x8F,0x0B,0x79,0xF2,0xAE,0x46,0x25,0x77,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x6C, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x2B,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x48,0x69,0x67,0x68,0x20,0x41,0x73,0x73,0x75,0x72,0x61,0x6E,0x63, - 0x65,0x20,0x45,0x56,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, - 0x30,0x36,0x31,0x31,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x33, - 0x31,0x31,0x31,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x30,0x6C,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x20,0x49, - 0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77,0x77,0x77, - 0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31,0x2B,0x30, - 0x29,0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x48,0x69,0x67,0x68,0x20,0x41,0x73,0x73,0x75,0x72,0x61,0x6E,0x63,0x65,0x20, - 0x45,0x56,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,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,0xC6,0xCC,0xE5,0x73,0xE6, - 0xFB,0xD4,0xBB,0xE5,0x2D,0x2D,0x32,0xA6,0xDF,0xE5,0x81,0x3F,0xC9,0xCD,0x25,0x49, - 0xB6,0x71,0x2A,0xC3,0xD5,0x94,0x34,0x67,0xA2,0x0A,0x1C,0xB0,0x5F,0x69,0xA6,0x40, - 0xB1,0xC4,0xB7,0xB2,0x8F,0xD0,0x98,0xA4,0xA9,0x41,0x59,0x3A,0xD3,0xDC,0x94,0xD6, - 0x3C,0xDB,0x74,0x38,0xA4,0x4A,0xCC,0x4D,0x25,0x82,0xF7,0x4A,0xA5,0x53,0x12,0x38, - 0xEE,0xF3,0x49,0x6D,0x71,0x91,0x7E,0x63,0xB6,0xAB,0xA6,0x5F,0xC3,0xA4,0x84,0xF8, - 0x4F,0x62,0x51,0xBE,0xF8,0xC5,0xEC,0xDB,0x38,0x92,0xE3,0x06,0xE5,0x08,0x91,0x0C, - 0xC4,0x28,0x41,0x55,0xFB,0xCB,0x5A,0x89,0x15,0x7E,0x71,0xE8,0x35,0xBF,0x4D,0x72, - 0x09,0x3D,0xBE,0x3A,0x38,0x50,0x5B,0x77,0x31,0x1B,0x8D,0xB3,0xC7,0x24,0x45,0x9A, - 0xA7,0xAC,0x6D,0x00,0x14,0x5A,0x04,0xB7,0xBA,0x13,0xEB,0x51,0x0A,0x98,0x41,0x41, - 0x22,0x4E,0x65,0x61,0x87,0x81,0x41,0x50,0xA6,0x79,0x5C,0x89,0xDE,0x19,0x4A,0x57, - 0xD5,0x2E,0xE6,0x5D,0x1C,0x53,0x2C,0x7E,0x98,0xCD,0x1A,0x06,0x16,0xA4,0x68,0x73, - 0xD0,0x34,0x04,0x13,0x5C,0xA1,0x71,0xD3,0x5A,0x7C,0x55,0xDB,0x5E,0x64,0xE1,0x37, - 0x87,0x30,0x56,0x04,0xE5,0x11,0xB4,0x29,0x80,0x12,0xF1,0x79,0x39,0x88,0xA2,0x02, - 0x11,0x7C,0x27,0x66,0xB7,0x88,0xB7,0x78,0xF2,0xCA,0x0A,0xA8,0x38,0xAB,0x0A,0x64, - 0xC2,0xBF,0x66,0x5D,0x95,0x84,0xC1,0xA1,0x25,0x1E,0x87,0x5D,0x1A,0x50,0x0B,0x20, - 0x12,0xCC,0x41,0xBB,0x6E,0x0B,0x51,0x38,0xB8,0x4B,0xCB,0x02,0x03,0x01,0x00,0x01, - 0xA3,0x63,0x30,0x61,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, - 0x03,0x02,0x01,0x86,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05, - 0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, - 0xB1,0x3E,0xC3,0x69,0x03,0xF8,0xBF,0x47,0x01,0xD4,0x98,0x26,0x1A,0x08,0x02,0xEF, - 0x63,0x64,0x2B,0xC3,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80, - 0x14,0xB1,0x3E,0xC3,0x69,0x03,0xF8,0xBF,0x47,0x01,0xD4,0x98,0x26,0x1A,0x08,0x02, - 0xEF,0x63,0x64,0x2B,0xC3,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, - 0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x1C,0x1A,0x06,0x97,0xDC,0xD7,0x9C, - 0x9F,0x3C,0x88,0x66,0x06,0x08,0x57,0x21,0xDB,0x21,0x47,0xF8,0x2A,0x67,0xAA,0xBF, - 0x18,0x32,0x76,0x40,0x10,0x57,0xC1,0x8A,0xF3,0x7A,0xD9,0x11,0x65,0x8E,0x35,0xFA, - 0x9E,0xFC,0x45,0xB5,0x9E,0xD9,0x4C,0x31,0x4B,0xB8,0x91,0xE8,0x43,0x2C,0x8E,0xB3, - 0x78,0xCE,0xDB,0xE3,0x53,0x79,0x71,0xD6,0xE5,0x21,0x94,0x01,0xDA,0x55,0x87,0x9A, - 0x24,0x64,0xF6,0x8A,0x66,0xCC,0xDE,0x9C,0x37,0xCD,0xA8,0x34,0xB1,0x69,0x9B,0x23, - 0xC8,0x9E,0x78,0x22,0x2B,0x70,0x43,0xE3,0x55,0x47,0x31,0x61,0x19,0xEF,0x58,0xC5, - 0x85,0x2F,0x4E,0x30,0xF6,0xA0,0x31,0x16,0x23,0xC8,0xE7,0xE2,0x65,0x16,0x33,0xCB, - 0xBF,0x1A,0x1B,0xA0,0x3D,0xF8,0xCA,0x5E,0x8B,0x31,0x8B,0x60,0x08,0x89,0x2D,0x0C, - 0x06,0x5C,0x52,0xB7,0xC4,0xF9,0x0A,0x98,0xD1,0x15,0x5F,0x9F,0x12,0xBE,0x7C,0x36, - 0x63,0x38,0xBD,0x44,0xA4,0x7F,0xE4,0x26,0x2B,0x0A,0xC4,0x97,0x69,0x0D,0xE9,0x8C, - 0xE2,0xC0,0x10,0x57,0xB8,0xC8,0x76,0x12,0x91,0x55,0xF2,0x48,0x69,0xD8,0xBC,0x2A, - 0x02,0x5B,0x0F,0x44,0xD4,0x20,0x31,0xDB,0xF4,0xBA,0x70,0x26,0x5D,0x90,0x60,0x9E, - 0xBC,0x4B,0x17,0x09,0x2F,0xB4,0xCB,0x1E,0x43,0x68,0xC9,0x07,0x27,0xC1,0xD2,0x5C, - 0xF7,0xEA,0x21,0xB9,0x68,0x12,0x9C,0x3C,0x9C,0xBF,0x9E,0xFC,0x80,0x5C,0x9B,0x63, - 0xCD,0xEC,0x47,0xAA,0x25,0x27,0x67,0xA0,0x37,0xF3,0x00,0x82,0x7D,0x54,0xD7,0xA9, - 0xF8,0xE9,0x2E,0x13,0xA3,0x77,0xE8,0x1F,0x4A, -}; - -/* subject:/CN=Apple IST CA 2 OCSP Responder NL01/O=Apple Inc./C=US */ -/* issuer :/CN=Apple IST CA 2 - G1/OU=Certification Authority/O=Apple Inc./C=US */ -static const uint8_t _responderCert[]= { - 0x30,0x82,0x03,0xBB,0x30,0x82,0x02,0xA3,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x5B, - 0x1B,0xA7,0xF8,0x9D,0xF4,0x7B,0x7C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04, - 0x03,0x13,0x13,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43,0x41,0x20, - 0x32,0x20,0x2D,0x20,0x47,0x31,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13, - 0x17,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,0x13,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,0x38,0x31,0x31,0x30,0x30,0x34,0x36,0x35,0x33,0x5A,0x17,0x0D,0x31,0x38,0x30, - 0x39,0x32,0x32,0x30,0x30,0x34,0x36,0x35,0x33,0x5A,0x30,0x4F,0x31,0x2B,0x30,0x29, - 0x06,0x03,0x55,0x04,0x03,0x0C,0x22,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54, - 0x20,0x43,0x41,0x20,0x32,0x20,0x4F,0x43,0x53,0x50,0x20,0x52,0x65,0x73,0x70,0x6F, - 0x6E,0x64,0x65,0x72,0x20,0x4E,0x4C,0x30,0x31,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,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,0xA5,0x35,0xB2,0xC4, - 0xF2,0xAB,0x4C,0xFE,0xAA,0x5D,0xC7,0x23,0x52,0x68,0x42,0xC7,0x77,0x27,0x78,0x4E, - 0x80,0xFD,0x06,0xA3,0x51,0xA2,0x4F,0xF7,0x7A,0xD0,0x19,0x78,0xFD,0xEA,0x94,0xD8, - 0xE3,0x0C,0x3C,0x50,0x17,0x30,0xDB,0x84,0x38,0x13,0xE1,0xCF,0x6C,0xA0,0x1F,0x01, - 0xC7,0x12,0xC7,0x96,0x64,0x09,0x45,0x2F,0xA2,0x83,0xFE,0x4E,0x2C,0xF2,0x39,0x6F, - 0x20,0x34,0x6D,0xEC,0xBE,0xF9,0x86,0xA3,0xEF,0x40,0x1B,0x61,0x2D,0xE1,0xA4,0xB9, - 0xD4,0x3E,0x8E,0x65,0x7B,0x2F,0x26,0xD5,0x54,0xA6,0x12,0xC7,0x50,0xC8,0x89,0x94, - 0x86,0xFA,0x41,0x48,0xCF,0xE2,0xF1,0xF8,0xF2,0x0E,0xCC,0x25,0x43,0x0C,0x66,0x85, - 0xDC,0x88,0xA0,0x76,0x90,0x45,0xFC,0x4E,0x95,0x8F,0xA2,0x17,0x2F,0xAF,0x7C,0x41, - 0x59,0xA0,0xA1,0x36,0x98,0x18,0x20,0x4D,0x07,0xF5,0x7F,0xD1,0x66,0x65,0xC6,0x74, - 0xEA,0xBE,0xB8,0x20,0x88,0x29,0x27,0x5D,0x06,0x55,0xD0,0xB2,0x11,0xAF,0x52,0x58, - 0xD1,0x8A,0x57,0x6E,0x85,0x8D,0x0C,0xBD,0x6A,0xD3,0x87,0x09,0xF6,0x0F,0x07,0x7B, - 0x5C,0x8F,0x96,0x16,0xB5,0x89,0xB7,0x63,0xC4,0x33,0xDA,0x67,0x63,0xA3,0xC4,0x4B, - 0x73,0xEF,0x57,0x96,0x4F,0x15,0x2F,0x1B,0xF7,0x8E,0x35,0x24,0x18,0x68,0x87,0x16, - 0x0A,0x76,0x71,0x8B,0x94,0x11,0xB9,0xCC,0x02,0x97,0x2D,0x6F,0x94,0x00,0x1A,0x31, - 0xA6,0x9A,0x6B,0x4A,0xD3,0x64,0xB0,0x0F,0xA2,0xB0,0x5E,0xC0,0x2A,0x13,0xD6,0x7C, - 0x90,0xA6,0x5C,0xEE,0x7F,0x78,0xCA,0x7F,0x62,0x2F,0xF9,0x47,0x02,0x03,0x01,0x00, - 0x01,0xA3,0x81,0x87,0x30,0x81,0x84,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,0xD8,0x7A,0x94,0x44,0x7C,0x90,0x70,0x90,0x16,0x9E,0xDD,0x17,0x9C,0x01, - 0x44,0x03,0x86,0xD6,0x2A,0x29,0x30,0x0F,0x06,0x09,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x30,0x01,0x05,0x04,0x02,0x05,0x00,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C, - 0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x09,0x30,0x1D,0x06,0x03, - 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x75,0xDB,0x74,0x13,0x4A,0xCB,0xCB,0x5A,0x6B, - 0x78,0x40,0x5A,0x81,0x67,0x42,0xA5,0xD9,0xD0,0x4E,0x38,0x30,0x0E,0x06,0x03,0x55, - 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x0D,0x06,0x09,0x2A, - 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x3A, - 0x7E,0x84,0xE2,0x58,0xED,0x07,0xDD,0xE5,0xBD,0x5E,0x88,0x55,0x06,0x23,0x16,0x20, - 0xD1,0x85,0x89,0x60,0x83,0x19,0x21,0x04,0x9C,0x57,0xFE,0x91,0x30,0xBD,0x7C,0x83, - 0x45,0xA3,0xA1,0x11,0x0A,0x29,0xCF,0x6C,0x55,0x47,0xC3,0x7B,0x8C,0xEE,0x43,0xFE, - 0x42,0x0F,0xE6,0xCE,0xC7,0x24,0xAF,0x21,0x2E,0xC7,0xFD,0xFA,0xBA,0x7E,0xCE,0xA3, - 0x9D,0x92,0x5B,0x54,0x4C,0x4F,0x14,0x55,0xD6,0x5F,0xB0,0xB0,0x73,0xFD,0x78,0x61, - 0xDC,0xF6,0xA1,0xB6,0xFF,0xAF,0x3B,0x49,0x6F,0x62,0x95,0xD0,0x4E,0xA9,0x3F,0xE8, - 0x5C,0xCD,0x36,0xEA,0xED,0x57,0x04,0x32,0xB6,0xB0,0x91,0xDC,0x32,0xA6,0xC7,0x84, - 0x9C,0x3F,0x24,0x3A,0x64,0x56,0x62,0xA2,0x02,0x15,0xC9,0x63,0x96,0x8E,0x6C,0xF5, - 0x3E,0xB1,0xE4,0x3C,0x79,0x63,0xE0,0x94,0xE8,0xD0,0x73,0x31,0x7B,0x3C,0x99,0x66, - 0x82,0x2D,0x47,0x49,0x22,0x33,0xD4,0xD1,0x80,0x35,0xF1,0xB1,0xFD,0x01,0x92,0x07, - 0x6B,0x1E,0xF1,0xD0,0x02,0x84,0x24,0xD6,0xDF,0x2F,0x10,0x06,0x0F,0x36,0x5D,0x4B, - 0x1A,0xE3,0xDB,0x1F,0x8C,0x54,0x07,0x63,0x41,0x9E,0x74,0x6E,0x6F,0x9D,0xCE,0xCC, - 0x36,0x7B,0xE0,0xC5,0xCB,0x04,0x12,0xFF,0xF3,0x09,0xD7,0x36,0x5D,0x09,0xD0,0xCD, - 0xF2,0x73,0xAA,0x10,0x5D,0x0D,0xC2,0x12,0x21,0x00,0x89,0xE5,0x34,0x17,0x6C,0x76, - 0xE2,0x2F,0xDA,0xBD,0xCA,0xFB,0x9D,0xF2,0x1C,0x3B,0x62,0xCA,0xC0,0x97,0x82,0x54, - 0x92,0x4E,0x0C,0xD0,0x3B,0x79,0xD0,0x41,0x29,0x84,0xF5,0x75,0x40,0xB4,0xE8, -}; - -/* subject:/serialNumber=424761419/jurisdictionC=FR/businessCategory=Private Organization/C=FR/postalCode=59100/ST=Nord/L=Roubaix/street=2 rue Kellermann/O=OVH SAS/OU=IT/OU=COMODO EV SSL/CN=ovh.com */ -/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ -static unsigned char ovh_certificate[1884]={ - 0x30,0x82,0x07,0x58,0x30,0x82,0x06,0x40,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x40, - 0x46,0x47,0xDC,0xC2,0x4B,0x04,0x42,0xD4,0x89,0x8D,0x08,0x4D,0x4B,0xC2,0x01,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81, - 0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, - 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, - 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, - 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, - 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, - 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55, - 0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45, - 0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69, - 0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72, - 0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x37,0x30,0x34,0x32,0x38,0x30,0x30,0x30, - 0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x39,0x30,0x34,0x32,0x38,0x32,0x33,0x35,0x39, - 0x35,0x39,0x5A,0x30,0x81,0xEA,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x05,0x13, - 0x09,0x34,0x32,0x34,0x37,0x36,0x31,0x34,0x31,0x39,0x31,0x13,0x30,0x11,0x06,0x0B, - 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,0x13,0x02,0x46,0x52,0x31, - 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0F,0x13,0x14,0x50,0x72,0x69,0x76,0x61,0x74, - 0x65,0x20,0x4F,0x72,0x67,0x61,0x6E,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x46,0x52,0x31,0x0E,0x30,0x0C,0x06, - 0x03,0x55,0x04,0x11,0x13,0x05,0x35,0x39,0x31,0x30,0x30,0x31,0x0D,0x30,0x0B,0x06, - 0x03,0x55,0x04,0x08,0x13,0x04,0x4E,0x6F,0x72,0x64,0x31,0x10,0x30,0x0E,0x06,0x03, - 0x55,0x04,0x07,0x13,0x07,0x52,0x6F,0x75,0x62,0x61,0x69,0x78,0x31,0x19,0x30,0x17, - 0x06,0x03,0x55,0x04,0x09,0x13,0x10,0x32,0x20,0x72,0x75,0x65,0x20,0x4B,0x65,0x6C, - 0x6C,0x65,0x72,0x6D,0x61,0x6E,0x6E,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x0A, - 0x13,0x07,0x4F,0x56,0x48,0x20,0x53,0x41,0x53,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x0B,0x13,0x02,0x49,0x54,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x0B,0x13, - 0x0D,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x45,0x56,0x20,0x53,0x53,0x4C,0x31,0x10, - 0x30,0x0E,0x06,0x03,0x55,0x04,0x03,0x13,0x07,0x6F,0x76,0x68,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,0x93,0xA1,0x5D,0x05,0x5F,0x1A,0x26,0x56,0x3D,0xDC,0xC2,0x7C,0x1B,0xA1,0x7A, - 0x63,0x16,0x4F,0xBD,0xE0,0x77,0x85,0x04,0xB0,0x9B,0x49,0xE9,0x2B,0x5C,0xB1,0x51, - 0xFD,0x8A,0x14,0x51,0xC7,0xD9,0x50,0xDE,0x64,0x2F,0xFE,0x8C,0x27,0xC3,0x01,0x48, - 0x64,0x7C,0x85,0x3F,0x93,0xD4,0x09,0xE6,0x42,0xDF,0xC1,0xE4,0xEB,0x6A,0xC0,0x87, - 0x90,0xA5,0xF6,0x9C,0xD4,0x6B,0x08,0x77,0xFB,0x56,0x44,0x2B,0x8A,0xE0,0x05,0x73, - 0x14,0x6B,0x02,0x7D,0x76,0x44,0x7B,0x3E,0xA6,0xE5,0x23,0xA9,0xE1,0x8F,0x99,0xDD, - 0x15,0xCD,0xD9,0xD9,0x6D,0xB9,0x95,0x5B,0xE8,0xB6,0xE2,0x52,0xDD,0xF0,0xB0,0x80, - 0x1B,0xC1,0x95,0x4B,0x2C,0x9D,0x5E,0x8D,0x02,0x6B,0x59,0x6C,0x26,0x8B,0xC3,0x19, - 0x0D,0x3E,0xA8,0x34,0xD0,0x43,0x81,0xD7,0xBD,0xB3,0xA7,0x04,0xE1,0x05,0x82,0xA6, - 0x1F,0x4D,0x70,0x67,0x05,0x96,0x88,0xE8,0xE9,0x2E,0x95,0xD2,0x36,0x75,0xD6,0xC8, - 0x0C,0x59,0xBF,0x9F,0x1F,0x9F,0xB4,0xFF,0xF0,0x10,0x8C,0xC3,0xE6,0x8B,0x9F,0xE2, - 0x8E,0x00,0x60,0x58,0xCB,0x6F,0xAD,0x84,0x7B,0xA5,0x36,0xDB,0xB2,0xA4,0xEB,0xC6, - 0xC8,0xD8,0x61,0x6E,0x4A,0xDC,0x5C,0x3E,0x2C,0x33,0xCB,0x1E,0x16,0x8B,0x8C,0xA3, - 0x5F,0x0F,0x30,0x4E,0x0A,0x5D,0xA0,0x53,0x7C,0xCE,0xAB,0x29,0x9A,0xC6,0x64,0xC5, - 0x5A,0xD7,0x94,0x3D,0x81,0xB1,0x05,0x3F,0x2A,0x6D,0xD7,0xB8,0x9D,0xF1,0x6D,0x13, - 0xFD,0x82,0xB4,0xF9,0x88,0x77,0xAB,0xB8,0x2C,0x7A,0x81,0x6E,0x68,0xFF,0x6E,0x04, - 0xC1,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x03,0x4E,0x30,0x82,0x03,0x4A,0x30,0x1F, - 0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x39,0xDA,0xFF,0xCA,0x28, - 0x14,0x8A,0xA8,0x74,0x13,0x08,0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30, - 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x0B,0x0F,0xAD,0xA6,0xC3,0xBF, - 0x98,0xA1,0xEC,0xCD,0x20,0xB3,0x2C,0x75,0x03,0x56,0x3A,0xA6,0xD3,0xE6,0x30,0x0E, - 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x0C, - 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1D,0x06,0x03, - 0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03, - 0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55, - 0x1D,0x20,0x04,0x3F,0x30,0x3D,0x30,0x3B,0x06,0x0C,0x2B,0x06,0x01,0x04,0x01,0xB2, - 0x31,0x01,0x02,0x01,0x05,0x01,0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x02,0x01,0x16,0x1D,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65, - 0x63,0x75,0x72,0x65,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F, - 0x43,0x50,0x53,0x30,0x56,0x06,0x03,0x55,0x1D,0x1F,0x04,0x4F,0x30,0x4D,0x30,0x4B, - 0xA0,0x49,0xA0,0x47,0x86,0x45,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C, - 0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F, - 0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x56, - 0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x53,0x65,0x63,0x75,0x72,0x65,0x53, - 0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x6C,0x30,0x81,0x87,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x7B,0x30,0x79,0x30,0x51,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x45,0x68,0x74,0x74,0x70,0x3A,0x2F, - 0x2F,0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F, - 0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x45,0x78,0x74,0x65,0x6E, - 0x64,0x65,0x64,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x53,0x65,0x63, - 0x75,0x72,0x65,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x74,0x30, - 0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74, - 0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63, - 0x61,0x2E,0x63,0x6F,0x6D,0x30,0x1F,0x06,0x03,0x55,0x1D,0x11,0x04,0x18,0x30,0x16, - 0x82,0x07,0x6F,0x76,0x68,0x2E,0x63,0x6F,0x6D,0x82,0x0B,0x77,0x77,0x77,0x2E,0x6F, - 0x76,0x68,0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01,0x7E,0x06,0x0A,0x2B,0x06,0x01,0x04, - 0x01,0xD6,0x79,0x02,0x04,0x02,0x04,0x82,0x01,0x6E,0x04,0x82,0x01,0x6A,0x01,0x68, - 0x00,0x76,0x00,0xA4,0xB9,0x09,0x90,0xB4,0x18,0x58,0x14,0x87,0xBB,0x13,0xA2,0xCC, - 0x67,0x70,0x0A,0x3C,0x35,0x98,0x04,0xF9,0x1B,0xDF,0xB8,0xE3,0x77,0xCD,0x0E,0xC8, - 0x0D,0xDC,0x10,0x00,0x00,0x01,0x5B,0xB5,0x7B,0xC8,0x2D,0x00,0x00,0x04,0x03,0x00, - 0x47,0x30,0x45,0x02,0x21,0x00,0xD5,0x1B,0x6C,0xAE,0x75,0x46,0x62,0x0C,0x8B,0x2E, - 0x14,0xB1,0xDE,0x7C,0xA5,0xFE,0x5C,0x4F,0x3E,0xB0,0xFF,0xFF,0x33,0xA2,0x84,0x58, - 0x51,0x57,0x97,0x09,0xAF,0x09,0x02,0x20,0x49,0xD7,0x12,0x12,0x6C,0x2A,0x00,0x21, - 0x5E,0x48,0xF8,0xD0,0xF2,0xA5,0x81,0x2A,0x4E,0xE9,0x22,0x0A,0x4E,0x46,0x8F,0xDB, - 0xA5,0x9C,0x4B,0x43,0x7E,0x51,0x24,0xE4,0x00,0x76,0x00,0x56,0x14,0x06,0x9A,0x2F, - 0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC,0x99, - 0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x5B,0xB5, - 0x7B,0xC5,0xC8,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x36,0xA9,0x1D, - 0x52,0x63,0x04,0x11,0x1F,0x65,0xC6,0x97,0x7C,0x17,0xFC,0x17,0x8D,0xDB,0x9D,0xA7, - 0xB7,0x84,0x66,0x03,0x55,0x95,0x7D,0x42,0x39,0x98,0x60,0xDE,0x19,0x02,0x21,0x00, - 0x8B,0xB7,0x16,0xC0,0x20,0x17,0xBF,0x31,0x36,0xBD,0xBC,0x1C,0x12,0x61,0x42,0xC0, - 0x5C,0x19,0x97,0x0A,0xFA,0x85,0xDB,0x5D,0xC3,0x65,0xBE,0x18,0xBF,0x89,0x6F,0xB9, - 0x00,0x76,0x00,0xEE,0x4B,0xBD,0xB7,0x75,0xCE,0x60,0xBA,0xE1,0x42,0x69,0x1F,0xAB, - 0xE1,0x9E,0x66,0xA3,0x0F,0x7E,0x5F,0xB0,0x72,0xD8,0x83,0x00,0xC4,0x7B,0x89,0x7A, - 0xA8,0xFD,0xCB,0x00,0x00,0x01,0x5B,0xB5,0x7B,0xC7,0xFA,0x00,0x00,0x04,0x03,0x00, - 0x47,0x30,0x45,0x02,0x21,0x00,0xF8,0xFE,0x02,0xC9,0xAF,0x02,0x18,0xF4,0x12,0x00, - 0x39,0x3C,0x15,0xE0,0x9C,0x78,0x04,0x19,0x55,0xAE,0x8F,0xB4,0x22,0xB9,0x08,0x66, - 0x9E,0x21,0x3E,0xF0,0x7D,0xC6,0x02,0x20,0x47,0x45,0x31,0xC7,0x2C,0xC3,0xBE,0xC7, - 0x5B,0xD8,0x31,0x0A,0xD6,0xAF,0x9D,0xAF,0x04,0x45,0xAA,0x51,0x7D,0x43,0xEF,0x35, - 0x4D,0x81,0xB3,0x0A,0x2F,0x8D,0xD8,0x61,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6C,0x8E,0xB5,0x58, - 0x8A,0xC5,0x66,0xAC,0x99,0x68,0xF9,0x80,0x68,0x8E,0xC5,0x10,0xF7,0xD7,0x37,0x5E, - 0x09,0x8C,0x6B,0xCF,0x30,0x2B,0x98,0x3F,0x76,0x4D,0x69,0xBA,0xE8,0x61,0x1D,0xDE, - 0x1A,0x14,0x4F,0x5A,0x0B,0x54,0x0F,0x66,0xEF,0xB9,0xB3,0x51,0x6C,0x9B,0x86,0x1D, - 0xB9,0x13,0xC8,0x54,0x24,0x6C,0x82,0x6E,0x4B,0x3C,0x53,0xC7,0x7D,0x0B,0x40,0x4A, - 0x7E,0x23,0xF2,0x79,0x6B,0xC3,0xFF,0x9D,0xDF,0xC0,0x16,0x7B,0xFF,0x7B,0x04,0xC9, - 0xE0,0xEB,0x3F,0x28,0xC6,0xD2,0x79,0xEE,0xAE,0x7E,0x38,0x5F,0x0D,0xDF,0x71,0xE7, - 0xAA,0x38,0x7E,0xF3,0x28,0xE8,0xB2,0xAC,0x69,0xB9,0x69,0xD4,0x05,0x8E,0xF1,0x00, - 0x71,0x77,0x97,0x7F,0x94,0x36,0x45,0xE5,0x9C,0x15,0xA3,0xF1,0x40,0xD7,0xB5,0xEA, - 0x95,0x56,0x75,0x60,0x86,0xFB,0xCD,0xB7,0x81,0x5A,0x34,0x1A,0x83,0x1E,0xC2,0x50, - 0xA2,0x57,0x16,0x13,0x53,0x95,0xFA,0x95,0xD0,0x64,0x1E,0x09,0x45,0x50,0x05,0x63, - 0x3A,0x86,0xB2,0x1D,0x9B,0x19,0x0E,0x89,0x7E,0x75,0x17,0xDA,0xC5,0x4D,0x4F,0x71, - 0x55,0x82,0x3E,0x5F,0x41,0x25,0x2F,0x86,0x9E,0x3D,0xF1,0x32,0xFA,0x77,0x7C,0x30, - 0x6C,0x50,0x2F,0xE7,0x11,0x7B,0xE1,0x3F,0xA8,0x2E,0xEF,0xAC,0x36,0x94,0x8F,0xF0, - 0x92,0xB4,0xCA,0x1A,0x53,0x8E,0x12,0x26,0x48,0xC4,0xA8,0x25,0x19,0x96,0x19,0x11, - 0xA2,0xA2,0x48,0xEB,0x8C,0x12,0x59,0x7F,0xCE,0xFC,0x4B,0xC9,0x19,0x10,0x61,0x2B, - 0xB3,0xA6,0x6B,0xB4,0xBA,0x68,0xB9,0x22,0x58,0xE4,0x82,0x27, -}; - -/* This is the cert the ssl server returns to us. */ -/* subject:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ -/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority */ -static unsigned char comodo_ev_certificate[1554]={ - 0x30,0x82,0x06,0x0E,0x30,0x82,0x03,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x06, - 0xA7,0x43,0x80,0xD4,0xEB,0xFE,0xD4,0x35,0xB5,0xA3,0xF7,0xE1,0x6A,0xBD,0xD8,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x30,0x81, - 0x85,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, - 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, - 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, - 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, - 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, - 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x2B,0x30,0x29,0x06,0x03,0x55, - 0x04,0x03,0x13,0x22,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x43, - 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74, - 0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x31,0x32,0x30,0x32,0x31,0x32, - 0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x37,0x30,0x32,0x31,0x31,0x32, - 0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x81,0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13, - 0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72,0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73, - 0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61, - 0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11, - 0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43,0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65, - 0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F, - 0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20, - 0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72, - 0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,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,0x95,0x56,0xDE,0x54, - 0xB4,0xDF,0xD5,0x02,0x49,0x7B,0xD1,0x5B,0x5C,0xA2,0xB2,0x1E,0x8F,0x9C,0x2B,0x62, - 0x4C,0x2B,0x8D,0x12,0x28,0xF3,0x1A,0x95,0xA3,0xC6,0x10,0xFD,0x29,0xDE,0xE1,0x9F, - 0x0B,0x38,0x40,0x93,0xD1,0xEF,0x6E,0x95,0x10,0xFC,0xE1,0x90,0x17,0x77,0x2C,0xEE, - 0x75,0x3E,0x7B,0x63,0xEC,0x61,0x92,0x6E,0x4F,0x3B,0xAB,0x80,0x49,0x6B,0xDF,0x00, - 0xEA,0x03,0x00,0x7F,0x2F,0x75,0xD5,0x28,0x2F,0xEC,0x56,0x67,0x8F,0x80,0x83,0xA3, - 0xBD,0xDC,0x03,0x99,0x93,0x8B,0x94,0x91,0x56,0x5B,0xA1,0xB8,0x6A,0x3A,0x3F,0x06, - 0xBD,0x0E,0x92,0xCC,0x60,0x9C,0xFD,0xB5,0xE0,0x9F,0x66,0x30,0x5F,0xDB,0xE6,0x94, - 0xF0,0x95,0x6A,0xAF,0xC8,0x8A,0xAF,0x80,0xD9,0xE6,0x88,0x39,0x01,0x7C,0x1C,0xC0, - 0xC5,0x2A,0xF7,0x7B,0x95,0xA0,0xF2,0x76,0xAB,0x6D,0x9B,0x72,0x39,0x30,0xEB,0xD1, - 0x57,0x55,0x01,0x9D,0x58,0x11,0x9D,0x7C,0x6D,0x84,0x8F,0x49,0xE8,0x9D,0x09,0xFC, - 0x3C,0xFD,0x0A,0x4A,0x76,0x14,0x21,0x5C,0x16,0x73,0x40,0x23,0x19,0x74,0xC3,0xBA, - 0x58,0x0A,0xA6,0x96,0x2E,0xDE,0x36,0xE5,0x9F,0xD0,0xC2,0xF0,0xE1,0xE0,0xC1,0x62, - 0xE3,0xC2,0x18,0x45,0x19,0x51,0xAA,0x17,0x1E,0xE8,0x23,0x75,0xD4,0xC8,0xD0,0x96, - 0x13,0xFF,0xC7,0x24,0xD1,0x8C,0x0B,0x27,0xAE,0x9E,0x7A,0xDC,0x3A,0x61,0x63,0x60, - 0x88,0x97,0x2D,0x5D,0x05,0x0B,0xE5,0x3B,0xEB,0xAE,0xCE,0x3A,0x47,0x73,0x76,0xA8, - 0xFA,0x2C,0xDD,0xC0,0x87,0x17,0xE9,0xAC,0x30,0x99,0xF8,0x1F,0x02,0x03,0x01,0x00, - 0x01,0xA3,0x82,0x01,0x69,0x30,0x82,0x01,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23, - 0x04,0x18,0x30,0x16,0x80,0x14,0xBB,0xAF,0x7E,0x02,0x3D,0xFA,0xA6,0xF1,0x3C,0x84, - 0x8E,0xAD,0xEE,0x38,0x98,0xEC,0xD9,0x32,0x32,0xD4,0x30,0x1D,0x06,0x03,0x55,0x1D, - 0x0E,0x04,0x16,0x04,0x14,0x39,0xDA,0xFF,0xCA,0x28,0x14,0x8A,0xA8,0x74,0x13,0x08, - 0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13, - 0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x3E,0x06, - 0x03,0x55,0x1D,0x20,0x04,0x37,0x30,0x35,0x30,0x33,0x06,0x04,0x55,0x1D,0x20,0x00, - 0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1D, - 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65,0x63,0x75,0x72,0x65,0x2E,0x63, - 0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x4C,0x06, - 0x03,0x55,0x1D,0x1F,0x04,0x45,0x30,0x43,0x30,0x41,0xA0,0x3F,0xA0,0x3D,0x86,0x3B, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x63,0x6F,0x6D,0x6F,0x64, - 0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53, - 0x41,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x41,0x75, - 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x2E,0x63,0x72,0x6C,0x30,0x71,0x06,0x08,0x2B, - 0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3B,0x06,0x08,0x2B, - 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, - 0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D, - 0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x41,0x64,0x64,0x54,0x72,0x75, - 0x73,0x74,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, - 0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x30,0x0D, - 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x03,0x82,0x02, - 0x01,0x00,0x44,0x42,0x9D,0x41,0x51,0x2B,0x48,0x88,0x5D,0x97,0x9B,0x79,0x5E,0x11, - 0x01,0x4A,0x52,0x19,0x7B,0x41,0x2C,0xC7,0x89,0x3C,0xD0,0x72,0xDC,0x85,0xFA,0x58, - 0xAF,0xD5,0x25,0xE4,0x13,0xF8,0x58,0x65,0x67,0x9F,0x0D,0xFF,0x57,0x8B,0xA9,0x85, - 0x5E,0xCA,0xA6,0x4B,0xB0,0xA7,0xB2,0x2D,0xE0,0x8C,0x22,0xCD,0xFB,0xFF,0x79,0xA4, - 0x8C,0x2B,0x8D,0xFE,0x02,0x3D,0x24,0xDE,0xA9,0x5D,0x5F,0xE4,0x0F,0x47,0xD0,0xDB, - 0x66,0x25,0x3E,0x87,0x47,0x0C,0xAE,0x22,0xC5,0x50,0x22,0x84,0xD7,0xED,0x4A,0x59, - 0x1A,0xF6,0x93,0xA5,0x93,0xB0,0xE0,0x1B,0x81,0xF2,0x56,0xC4,0xC8,0x10,0x53,0xE4, - 0xD4,0x76,0xB1,0xD1,0x5B,0x69,0x4B,0x77,0xB2,0xE0,0x4F,0xC4,0x84,0xE7,0xD4,0xA0, - 0x50,0xEE,0x3C,0xFA,0x44,0xFC,0xD0,0x57,0xB9,0xE1,0x28,0x53,0xFD,0x53,0xCD,0xDC, - 0xB9,0x1F,0x7A,0x40,0xBD,0x30,0x3F,0xD8,0x6C,0xD2,0xF3,0xE7,0x07,0x9F,0x1F,0x22, - 0xB5,0xEA,0x22,0x71,0xCB,0x2A,0xF0,0x56,0x7C,0xFE,0xAC,0xA8,0xD1,0x06,0x0F,0x14, - 0x14,0x52,0x4C,0xFE,0x64,0x2B,0x0C,0x69,0x2A,0xB8,0x0D,0x50,0x6E,0x3E,0x04,0x07, - 0xBF,0x7A,0x20,0x8B,0xF8,0xEE,0x65,0x09,0xE1,0xC7,0x49,0x08,0x32,0x3D,0x0D,0x28, - 0x7E,0x49,0x1D,0xB7,0x4A,0xEF,0x02,0xE7,0x0D,0x80,0x17,0xC8,0x5C,0xE0,0x61,0x62, - 0xCB,0xEC,0xB3,0x60,0x79,0x25,0xDA,0x1A,0x65,0x73,0x9C,0x38,0x10,0xA0,0x26,0x3A, - 0xB0,0xC8,0x16,0x7D,0x93,0x31,0x22,0xEE,0x74,0x0B,0x88,0xC0,0x5C,0x89,0x41,0x00, - 0x28,0xA9,0x47,0x31,0xDF,0x7D,0x49,0x45,0x9A,0xF5,0xE6,0xA7,0x45,0x1A,0xD2,0x8E, - 0x13,0x10,0xDF,0x83,0xAF,0x9B,0x0D,0xAD,0x7E,0x7E,0x9D,0x35,0x50,0x34,0x04,0xCE, - 0xE9,0x20,0xD6,0x9E,0xDB,0x9D,0xD4,0xA8,0xDA,0x64,0xB4,0xD1,0x2F,0x59,0x2E,0x5E, - 0xA2,0x36,0x61,0xD4,0x24,0xA0,0x82,0x33,0x33,0x8A,0xA1,0xD1,0x6C,0xEF,0x61,0x68, - 0xA3,0xE5,0xD2,0x56,0xAD,0xC5,0xFD,0x5E,0x62,0xEB,0x15,0xA8,0x74,0x12,0x4C,0x2F, - 0x31,0x8C,0xE9,0xC1,0xDF,0x10,0x4B,0x01,0xEA,0xF6,0x54,0x1B,0xCD,0x7F,0x3B,0xBD, - 0x5C,0x9F,0xC1,0xDB,0xCF,0x01,0xCA,0xF2,0xBA,0x60,0x12,0x21,0x31,0xED,0xA9,0x64, - 0xB8,0xB2,0x49,0x58,0x17,0x6D,0x5A,0xD7,0xCD,0x8C,0x6D,0xBE,0x9E,0x7F,0xE2,0x02, - 0x58,0xA7,0xDB,0xC3,0x2D,0x58,0xF6,0x74,0x06,0x6A,0x9A,0xF6,0x61,0xF9,0xF6,0x00, - 0xB6,0x69,0xD8,0x3A,0x8B,0x31,0x59,0xDD,0x91,0xE6,0x7C,0x27,0x23,0x87,0xDD,0x03, - 0x0F,0x8F,0x2A,0x8C,0x1E,0x83,0x01,0x4E,0x01,0x61,0x0C,0x52,0x73,0x6D,0xFC,0x08, - 0xA2,0xB9,0x2A,0x66,0xE4,0x76,0x4D,0x31,0xA0,0x56,0x9B,0xD9,0x53,0x8D,0xA2,0xB6, - 0x8F,0x02,0xC8,0xE6,0x3A,0xA6,0x04,0xD1,0x48,0xFB,0xC3,0x4A,0x02,0x76,0xFD,0x2F, - 0xD2,0xBC,0x13,0xB6,0xE8,0x6D,0x34,0x24,0xFA,0x9D,0x29,0x8A,0xC7,0xA1,0x2B,0x14, - 0xF1,0x96,0x00,0x73,0xB9,0x13,0xE9,0xC0,0xB9,0x3A,0x47,0x56,0x02,0x71,0x80,0x27, - 0xA4,0xBC,0x25,0xB6,0xE9,0xBD,0xE4,0xE9,0x98,0x74,0x16,0xF1,0x37,0x84,0x81,0x07, - 0xB4,0x82, -}; - -/* This is the cert we get when we get the url in the AIA extension of the ovh leaf. */ -/* subject:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ -/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority */ -static unsigned char comodo_aia_certificate[1554]={ - 0x30,0x82,0x06,0x0E,0x30,0x82,0x03,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x06, - 0xA7,0x43,0x80,0xD4,0xEB,0xFE,0xD4,0x35,0xB5,0xA3,0xF7,0xE1,0x6A,0xBD,0xD8,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x30,0x81, - 0x85,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, - 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, - 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, - 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, - 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, - 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x2B,0x30,0x29,0x06,0x03,0x55, - 0x04,0x03,0x13,0x22,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x43, - 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74, - 0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x31,0x32,0x30,0x32,0x31,0x32, - 0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x37,0x30,0x32,0x31,0x31,0x32, - 0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x81,0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13, - 0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72,0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73, - 0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61, - 0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11, - 0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43,0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65, - 0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F, - 0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20, - 0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72, - 0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,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,0x95,0x56,0xDE,0x54, - 0xB4,0xDF,0xD5,0x02,0x49,0x7B,0xD1,0x5B,0x5C,0xA2,0xB2,0x1E,0x8F,0x9C,0x2B,0x62, - 0x4C,0x2B,0x8D,0x12,0x28,0xF3,0x1A,0x95,0xA3,0xC6,0x10,0xFD,0x29,0xDE,0xE1,0x9F, - 0x0B,0x38,0x40,0x93,0xD1,0xEF,0x6E,0x95,0x10,0xFC,0xE1,0x90,0x17,0x77,0x2C,0xEE, - 0x75,0x3E,0x7B,0x63,0xEC,0x61,0x92,0x6E,0x4F,0x3B,0xAB,0x80,0x49,0x6B,0xDF,0x00, - 0xEA,0x03,0x00,0x7F,0x2F,0x75,0xD5,0x28,0x2F,0xEC,0x56,0x67,0x8F,0x80,0x83,0xA3, - 0xBD,0xDC,0x03,0x99,0x93,0x8B,0x94,0x91,0x56,0x5B,0xA1,0xB8,0x6A,0x3A,0x3F,0x06, - 0xBD,0x0E,0x92,0xCC,0x60,0x9C,0xFD,0xB5,0xE0,0x9F,0x66,0x30,0x5F,0xDB,0xE6,0x94, - 0xF0,0x95,0x6A,0xAF,0xC8,0x8A,0xAF,0x80,0xD9,0xE6,0x88,0x39,0x01,0x7C,0x1C,0xC0, - 0xC5,0x2A,0xF7,0x7B,0x95,0xA0,0xF2,0x76,0xAB,0x6D,0x9B,0x72,0x39,0x30,0xEB,0xD1, - 0x57,0x55,0x01,0x9D,0x58,0x11,0x9D,0x7C,0x6D,0x84,0x8F,0x49,0xE8,0x9D,0x09,0xFC, - 0x3C,0xFD,0x0A,0x4A,0x76,0x14,0x21,0x5C,0x16,0x73,0x40,0x23,0x19,0x74,0xC3,0xBA, - 0x58,0x0A,0xA6,0x96,0x2E,0xDE,0x36,0xE5,0x9F,0xD0,0xC2,0xF0,0xE1,0xE0,0xC1,0x62, - 0xE3,0xC2,0x18,0x45,0x19,0x51,0xAA,0x17,0x1E,0xE8,0x23,0x75,0xD4,0xC8,0xD0,0x96, - 0x13,0xFF,0xC7,0x24,0xD1,0x8C,0x0B,0x27,0xAE,0x9E,0x7A,0xDC,0x3A,0x61,0x63,0x60, - 0x88,0x97,0x2D,0x5D,0x05,0x0B,0xE5,0x3B,0xEB,0xAE,0xCE,0x3A,0x47,0x73,0x76,0xA8, - 0xFA,0x2C,0xDD,0xC0,0x87,0x17,0xE9,0xAC,0x30,0x99,0xF8,0x1F,0x02,0x03,0x01,0x00, - 0x01,0xA3,0x82,0x01,0x69,0x30,0x82,0x01,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23, - 0x04,0x18,0x30,0x16,0x80,0x14,0xBB,0xAF,0x7E,0x02,0x3D,0xFA,0xA6,0xF1,0x3C,0x84, - 0x8E,0xAD,0xEE,0x38,0x98,0xEC,0xD9,0x32,0x32,0xD4,0x30,0x1D,0x06,0x03,0x55,0x1D, - 0x0E,0x04,0x16,0x04,0x14,0x39,0xDA,0xFF,0xCA,0x28,0x14,0x8A,0xA8,0x74,0x13,0x08, - 0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13, - 0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x3E,0x06, - 0x03,0x55,0x1D,0x20,0x04,0x37,0x30,0x35,0x30,0x33,0x06,0x04,0x55,0x1D,0x20,0x00, - 0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1D, - 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65,0x63,0x75,0x72,0x65,0x2E,0x63, - 0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x4C,0x06, - 0x03,0x55,0x1D,0x1F,0x04,0x45,0x30,0x43,0x30,0x41,0xA0,0x3F,0xA0,0x3D,0x86,0x3B, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x63,0x6F,0x6D,0x6F,0x64, - 0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53, - 0x41,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x41,0x75, - 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x2E,0x63,0x72,0x6C,0x30,0x71,0x06,0x08,0x2B, - 0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3B,0x06,0x08,0x2B, - 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, - 0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D, - 0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x41,0x64,0x64,0x54,0x72,0x75, - 0x73,0x74,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, - 0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x30,0x0D, - 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x03,0x82,0x02, - 0x01,0x00,0x44,0x42,0x9D,0x41,0x51,0x2B,0x48,0x88,0x5D,0x97,0x9B,0x79,0x5E,0x11, - 0x01,0x4A,0x52,0x19,0x7B,0x41,0x2C,0xC7,0x89,0x3C,0xD0,0x72,0xDC,0x85,0xFA,0x58, - 0xAF,0xD5,0x25,0xE4,0x13,0xF8,0x58,0x65,0x67,0x9F,0x0D,0xFF,0x57,0x8B,0xA9,0x85, - 0x5E,0xCA,0xA6,0x4B,0xB0,0xA7,0xB2,0x2D,0xE0,0x8C,0x22,0xCD,0xFB,0xFF,0x79,0xA4, - 0x8C,0x2B,0x8D,0xFE,0x02,0x3D,0x24,0xDE,0xA9,0x5D,0x5F,0xE4,0x0F,0x47,0xD0,0xDB, - 0x66,0x25,0x3E,0x87,0x47,0x0C,0xAE,0x22,0xC5,0x50,0x22,0x84,0xD7,0xED,0x4A,0x59, - 0x1A,0xF6,0x93,0xA5,0x93,0xB0,0xE0,0x1B,0x81,0xF2,0x56,0xC4,0xC8,0x10,0x53,0xE4, - 0xD4,0x76,0xB1,0xD1,0x5B,0x69,0x4B,0x77,0xB2,0xE0,0x4F,0xC4,0x84,0xE7,0xD4,0xA0, - 0x50,0xEE,0x3C,0xFA,0x44,0xFC,0xD0,0x57,0xB9,0xE1,0x28,0x53,0xFD,0x53,0xCD,0xDC, - 0xB9,0x1F,0x7A,0x40,0xBD,0x30,0x3F,0xD8,0x6C,0xD2,0xF3,0xE7,0x07,0x9F,0x1F,0x22, - 0xB5,0xEA,0x22,0x71,0xCB,0x2A,0xF0,0x56,0x7C,0xFE,0xAC,0xA8,0xD1,0x06,0x0F,0x14, - 0x14,0x52,0x4C,0xFE,0x64,0x2B,0x0C,0x69,0x2A,0xB8,0x0D,0x50,0x6E,0x3E,0x04,0x07, - 0xBF,0x7A,0x20,0x8B,0xF8,0xEE,0x65,0x09,0xE1,0xC7,0x49,0x08,0x32,0x3D,0x0D,0x28, - 0x7E,0x49,0x1D,0xB7,0x4A,0xEF,0x02,0xE7,0x0D,0x80,0x17,0xC8,0x5C,0xE0,0x61,0x62, - 0xCB,0xEC,0xB3,0x60,0x79,0x25,0xDA,0x1A,0x65,0x73,0x9C,0x38,0x10,0xA0,0x26,0x3A, - 0xB0,0xC8,0x16,0x7D,0x93,0x31,0x22,0xEE,0x74,0x0B,0x88,0xC0,0x5C,0x89,0x41,0x00, - 0x28,0xA9,0x47,0x31,0xDF,0x7D,0x49,0x45,0x9A,0xF5,0xE6,0xA7,0x45,0x1A,0xD2,0x8E, - 0x13,0x10,0xDF,0x83,0xAF,0x9B,0x0D,0xAD,0x7E,0x7E,0x9D,0x35,0x50,0x34,0x04,0xCE, - 0xE9,0x20,0xD6,0x9E,0xDB,0x9D,0xD4,0xA8,0xDA,0x64,0xB4,0xD1,0x2F,0x59,0x2E,0x5E, - 0xA2,0x36,0x61,0xD4,0x24,0xA0,0x82,0x33,0x33,0x8A,0xA1,0xD1,0x6C,0xEF,0x61,0x68, - 0xA3,0xE5,0xD2,0x56,0xAD,0xC5,0xFD,0x5E,0x62,0xEB,0x15,0xA8,0x74,0x12,0x4C,0x2F, - 0x31,0x8C,0xE9,0xC1,0xDF,0x10,0x4B,0x01,0xEA,0xF6,0x54,0x1B,0xCD,0x7F,0x3B,0xBD, - 0x5C,0x9F,0xC1,0xDB,0xCF,0x01,0xCA,0xF2,0xBA,0x60,0x12,0x21,0x31,0xED,0xA9,0x64, - 0xB8,0xB2,0x49,0x58,0x17,0x6D,0x5A,0xD7,0xCD,0x8C,0x6D,0xBE,0x9E,0x7F,0xE2,0x02, - 0x58,0xA7,0xDB,0xC3,0x2D,0x58,0xF6,0x74,0x06,0x6A,0x9A,0xF6,0x61,0xF9,0xF6,0x00, - 0xB6,0x69,0xD8,0x3A,0x8B,0x31,0x59,0xDD,0x91,0xE6,0x7C,0x27,0x23,0x87,0xDD,0x03, - 0x0F,0x8F,0x2A,0x8C,0x1E,0x83,0x01,0x4E,0x01,0x61,0x0C,0x52,0x73,0x6D,0xFC,0x08, - 0xA2,0xB9,0x2A,0x66,0xE4,0x76,0x4D,0x31,0xA0,0x56,0x9B,0xD9,0x53,0x8D,0xA2,0xB6, - 0x8F,0x02,0xC8,0xE6,0x3A,0xA6,0x04,0xD1,0x48,0xFB,0xC3,0x4A,0x02,0x76,0xFD,0x2F, - 0xD2,0xBC,0x13,0xB6,0xE8,0x6D,0x34,0x24,0xFA,0x9D,0x29,0x8A,0xC7,0xA1,0x2B,0x14, - 0xF1,0x96,0x00,0x73,0xB9,0x13,0xE9,0xC0,0xB9,0x3A,0x47,0x56,0x02,0x71,0x80,0x27, - 0xA4,0xBC,0x25,0xB6,0xE9,0xBD,0xE4,0xE9,0x98,0x74,0x16,0xF1,0x37,0x84,0x81,0x07, - 0xB4,0x82, -}; - -static unsigned char valid_ist_certificate[] = { - 0x30,0x82,0x08,0x51,0x30,0x82,0x07,0x39,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x3A, - 0xFC,0x35,0x65,0x26,0x40,0x12,0xAF,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04, - 0x03,0x13,0x13,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43,0x41,0x20, - 0x32,0x20,0x2D,0x20,0x47,0x31,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13, - 0x17,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,0x13,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,0x37,0x31,0x36,0x32,0x32,0x31,0x31,0x30,0x38,0x5A,0x17,0x0D,0x32,0x30,0x30, - 0x38,0x31,0x34,0x32,0x32,0x31,0x31,0x30,0x38,0x5A,0x30,0x79,0x31,0x18,0x30,0x16, - 0x06,0x03,0x55,0x04,0x03,0x0C,0x0F,0x76,0x61,0x6C,0x69,0x64,0x2E,0x61,0x70,0x70, - 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C, - 0x1D,0x6D,0x61,0x6E,0x61,0x67,0x65,0x6D,0x65,0x6E,0x74,0x3A,0x69,0x64,0x6D,0x73, - 0x2E,0x67,0x72,0x6F,0x75,0x70,0x2E,0x31,0x32,0x30,0x38,0x39,0x32,0x30,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, - 0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61, - 0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, - 0x06,0x13,0x02,0x55,0x53,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,0xC7,0x5F,0xAC,0x4A,0xAC,0x71,0xFC,0xF1,0x80,0x8D, - 0x57,0xA1,0xDC,0x3B,0x48,0x4F,0x02,0x83,0xBA,0xE0,0x57,0x36,0xAB,0x53,0xB5,0x14, - 0x47,0x8F,0x87,0x24,0xA6,0x7A,0x40,0x5C,0xC3,0x28,0x6E,0x29,0x6D,0x54,0x35,0x89, - 0x79,0xA9,0x12,0xF3,0xD7,0x0A,0x4E,0xBE,0xC7,0xFB,0x75,0xF3,0x1B,0x92,0x6D,0x3F, - 0x7B,0xCC,0x72,0x63,0xF5,0xE8,0x57,0xC8,0xD2,0x7A,0x36,0x98,0x6E,0x61,0x0F,0x48, - 0xD1,0xC3,0x37,0xA4,0xB9,0x94,0x1C,0x66,0x18,0x75,0x97,0x34,0xED,0xFA,0x96,0x00, - 0x24,0x1A,0x8D,0x2E,0xFB,0x98,0x48,0x85,0xA5,0x73,0x9E,0xED,0x7D,0x8E,0x3C,0xCF, - 0xED,0xE9,0xE1,0x5F,0x1C,0x36,0xFF,0x20,0x2D,0x62,0x5C,0x0E,0x3D,0xCC,0x6E,0x3D, - 0xDB,0xF8,0x5A,0x8A,0x5A,0x2A,0x75,0xDC,0x09,0xC4,0x21,0x45,0x55,0x04,0xE3,0xEC, - 0x20,0xF0,0x5E,0xE3,0xC7,0x1A,0xD3,0x16,0x78,0x07,0xF1,0x65,0xF3,0xAD,0xB5,0x68, - 0x4B,0x0E,0x5D,0xA9,0x37,0xEA,0x58,0xAA,0x19,0x1F,0xF4,0xB4,0xF3,0x01,0xB0,0xE0, - 0xDC,0x25,0x4D,0x8A,0x2E,0xB1,0xC4,0xD3,0xE6,0x05,0x9E,0x23,0x8B,0x1E,0x8B,0xD0, - 0x14,0xA1,0x7E,0xC7,0x98,0xF1,0x68,0x9C,0x2D,0x10,0xDE,0xF9,0x79,0x14,0x3E,0x98, - 0x73,0x19,0x94,0x4B,0x4A,0xF7,0x52,0xDA,0x4D,0x98,0x26,0xAC,0xB2,0x76,0x1A,0x71, - 0xB5,0xFA,0x0D,0xE8,0x93,0xEB,0x92,0xF8,0x77,0x82,0xE5,0xE9,0xD4,0x07,0x8C,0xFD, - 0x20,0x8D,0xA0,0x25,0xD2,0x8A,0x6F,0xE2,0x33,0xA7,0x24,0x56,0x14,0x30,0x29,0x9D, - 0x6B,0xAB,0x2A,0x33,0xF9,0xD3,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x04,0xF2,0x30, - 0x82,0x04,0xEE,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,0xD8,0x7A, - 0x94,0x44,0x7C,0x90,0x70,0x90,0x16,0x9E,0xDD,0x17,0x9C,0x01,0x44,0x03,0x86,0xD6, - 0x2A,0x29,0x30,0x7E,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x72, - 0x30,0x70,0x30,0x34,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x28, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x65,0x72,0x74,0x73,0x2E,0x61,0x70,0x70, - 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74,0x63, - 0x61,0x32,0x67,0x31,0x2E,0x64,0x65,0x72,0x30,0x38,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x30,0x01,0x86,0x2C,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, - 0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70, - 0x30,0x33,0x2D,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74,0x63,0x61,0x32,0x67,0x31, - 0x32,0x30,0x30,0x43,0x06,0x03,0x55,0x1D,0x11,0x04,0x3C,0x30,0x3A,0x82,0x0F,0x76, - 0x61,0x6C,0x69,0x64,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x82,0x13, - 0x76,0x61,0x6C,0x69,0x64,0x2D,0x75,0x61,0x74,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, - 0x63,0x6F,0x6D,0x82,0x12,0x76,0x61,0x6C,0x69,0x64,0x2D,0x71,0x61,0x2E,0x61,0x70, - 0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x81,0xFF,0x06,0x03,0x55,0x1D,0x20,0x04, - 0x81,0xF7,0x30,0x81,0xF4,0x30,0x81,0xF1,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63, - 0x64,0x05,0x0B,0x04,0x30,0x81,0xE2,0x30,0x81,0xA4,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x02,0x02,0x30,0x81,0x97,0x0C,0x81,0x94,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,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65, - 0x70,0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x61,0x6E,0x79,0x20,0x61,0x70, - 0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61, - 0x6E,0x64,0x20,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66, - 0x20,0x75,0x73,0x65,0x20,0x61,0x6E,0x64,0x2F,0x6F,0x72,0x20,0x63,0x65,0x72,0x74, - 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69, - 0x63,0x65,0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x39, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x2D,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,0x72,0x70,0x61,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25, - 0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x37,0x06,0x03,0x55,0x1D,0x1F,0x04, - 0x30,0x30,0x2E,0x30,0x2C,0xA0,0x2A,0xA0,0x28,0x86,0x26,0x68,0x74,0x74,0x70,0x3A, - 0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F, - 0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74,0x63,0x61,0x32,0x67,0x31,0x2E,0x63,0x72, - 0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x55,0xF7,0x8E,0xC8, - 0x40,0x19,0x7D,0x8B,0x19,0x80,0xA5,0xF5,0xC6,0x44,0x75,0x8A,0x04,0x1E,0x7D,0x48, - 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0, - 0x30,0x82,0x02,0x6D,0x06,0x0A,0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02, - 0x04,0x82,0x02,0x5D,0x04,0x82,0x02,0x59,0x02,0x57,0x00,0x75,0x00,0xBB,0xD9,0xDF, - 0xBC,0x1F,0x8A,0x71,0xB5,0x93,0x94,0x23,0x97,0xAA,0x92,0x7B,0x47,0x38,0x57,0x95, - 0x0A,0xAB,0x52,0xE8,0x1A,0x90,0x96,0x64,0x36,0x8E,0x1E,0xD1,0x85,0x00,0x00,0x01, - 0x64,0xA5,0x2E,0xD8,0xFD,0x00,0x00,0x04,0x03,0x00,0x46,0x30,0x44,0x02,0x20,0x3E, - 0xD8,0xAB,0x26,0x35,0xFC,0xAC,0xE8,0x97,0xE8,0x84,0x28,0x73,0x0D,0xFB,0x6F,0x7B, - 0x02,0xF6,0x8E,0xB8,0xD1,0xAC,0xF3,0x9C,0xDF,0x37,0x2E,0x42,0x53,0x6B,0x3A,0x02, - 0x20,0x73,0x9A,0xED,0x05,0x2C,0x5C,0xDD,0x5A,0x60,0x2D,0xF9,0xB3,0x5C,0x7B,0xB3, - 0x95,0x0F,0xF1,0x21,0xD3,0xB5,0x1C,0x40,0xBC,0x50,0x79,0xE2,0xF3,0x19,0x89,0xAC, - 0xE7,0x00,0x75,0x00,0x56,0x14,0x06,0x9A,0x2F,0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD, - 0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC,0x99,0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55, - 0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x64,0xA5,0x2E,0xD9,0xA9,0x00,0x00,0x04,0x03, - 0x00,0x46,0x30,0x44,0x02,0x20,0x2E,0x5B,0x93,0xD3,0xCA,0x9A,0x1E,0x80,0xC3,0x50, - 0x1C,0xC1,0x37,0x6B,0x11,0x76,0x34,0xE8,0xE3,0xC7,0x8D,0x17,0xD0,0x4D,0x2E,0xA7, - 0xD9,0x98,0x6E,0x15,0x3A,0xC3,0x02,0x20,0x18,0x2B,0xD6,0x7A,0x11,0x46,0xC0,0xE1, - 0x99,0xDA,0x51,0x9C,0xBA,0xC5,0xC3,0x4C,0x3F,0x9A,0xB2,0xD1,0xDA,0xB7,0x6B,0x69, - 0x33,0x81,0x23,0x46,0x6F,0x54,0xFF,0x3F,0x00,0x76,0x00,0xEE,0x4B,0xBD,0xB7,0x75, - 0xCE,0x60,0xBA,0xE1,0x42,0x69,0x1F,0xAB,0xE1,0x9E,0x66,0xA3,0x0F,0x7E,0x5F,0xB0, - 0x72,0xD8,0x83,0x00,0xC4,0x7B,0x89,0x7A,0xA8,0xFD,0xCB,0x00,0x00,0x01,0x64,0xA5, - 0x2E,0xD9,0x25,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x5E,0x30,0x51, - 0x55,0x80,0x59,0xEA,0x60,0x45,0x10,0x9D,0x8E,0x61,0x07,0x34,0xD4,0xC2,0x08,0x46, - 0xEB,0xAC,0x4A,0xC3,0x72,0xC6,0x04,0x8E,0xF4,0x5D,0xF6,0xAF,0x51,0x02,0x21,0x00, - 0xC0,0x20,0xF0,0x01,0x1F,0x74,0xD4,0x33,0x24,0xE3,0x70,0xB3,0x80,0x47,0xE9,0x8A, - 0xB6,0x47,0xE4,0x65,0xA4,0x98,0x8D,0x6A,0xD8,0x75,0xE4,0xFE,0xC7,0x7A,0x89,0x5E, - 0x00,0x77,0x00,0x55,0x81,0xD4,0xC2,0x16,0x90,0x36,0x01,0x4A,0xEA,0x0B,0x9B,0x57, - 0x3C,0x53,0xF0,0xC0,0xE4,0x38,0x78,0x70,0x25,0x08,0x17,0x2F,0xA3,0xAA,0x1D,0x07, - 0x13,0xD3,0x0C,0x00,0x00,0x01,0x64,0xA5,0x2E,0xD9,0x74,0x00,0x00,0x04,0x03,0x00, - 0x48,0x30,0x46,0x02,0x21,0x00,0x94,0x79,0x39,0x0B,0x5F,0x59,0x89,0x4D,0xD4,0x09, - 0x28,0xB4,0xE1,0x07,0xC0,0x58,0xDC,0xA3,0x86,0x07,0x68,0x29,0x02,0xDA,0x86,0xE6, - 0x70,0xBE,0x32,0xB7,0xC6,0x33,0x02,0x21,0x00,0xA6,0x72,0x28,0x8B,0xC9,0x61,0xC4, - 0xFB,0x53,0x98,0x8F,0x99,0x3F,0x92,0x7E,0x06,0x21,0x10,0xA1,0x58,0x1D,0x28,0x44, - 0x80,0x29,0x91,0xC2,0xE6,0xBB,0xCE,0xCC,0x0E,0x00,0x76,0x00,0x87,0x75,0xBF,0xE7, - 0x59,0x7C,0xF8,0x8C,0x43,0x99,0x5F,0xBD,0xF3,0x6E,0xFF,0x56,0x8D,0x47,0x56,0x36, - 0xFF,0x4A,0xB5,0x60,0xC1,0xB4,0xEA,0xFF,0x5E,0xA0,0x83,0x0F,0x00,0x00,0x01,0x64, - 0xA5,0x2E,0xD9,0x12,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x37,0x9C, - 0x18,0xFC,0x24,0x63,0xAD,0x19,0xD6,0xA2,0x82,0xD9,0x47,0x82,0xAE,0x94,0x66,0x97, - 0xE4,0x73,0xCC,0x36,0x40,0x8A,0x6F,0xA5,0xAA,0x3C,0x99,0x92,0x8D,0x8F,0x02,0x21, - 0x00,0xF4,0x44,0x4A,0x8D,0x3A,0x18,0x31,0xDA,0xF5,0xDD,0xF4,0x37,0x4F,0xB3,0x1D, - 0xF6,0x15,0xBD,0x8B,0xF5,0x75,0x53,0x12,0x35,0xE5,0xD5,0x4D,0x08,0x0E,0xA7,0xC2, - 0x69,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, - 0x03,0x82,0x01,0x01,0x00,0x8F,0x46,0xED,0x04,0x6F,0xED,0xF7,0xAA,0xB9,0xE3,0x29, - 0xF7,0x4A,0x9F,0x69,0xEB,0xB2,0x61,0xD0,0x37,0x68,0x8F,0xC8,0xCF,0xB2,0x4F,0x1F, - 0x02,0x3E,0xF3,0x78,0x38,0x67,0xDB,0xD1,0xFA,0x60,0x16,0x70,0xDD,0xB7,0x44,0x12, - 0x54,0x0A,0x8C,0x3E,0xEC,0xF2,0xE9,0xBC,0x78,0x11,0x8D,0x7F,0x44,0x16,0xF0,0x87, - 0xD6,0xD8,0xA2,0x65,0xBC,0x11,0x32,0x4A,0xED,0xA9,0xF9,0xD7,0xB6,0xF7,0x9B,0x0F, - 0xFF,0x82,0x06,0x12,0x04,0x77,0xB9,0x13,0x08,0xAB,0x98,0x5D,0x07,0x04,0x7C,0xDC, - 0x43,0x1E,0x86,0x16,0x8C,0xF7,0xB2,0x67,0x42,0x65,0x43,0x40,0x9B,0x1F,0xC6,0x97, - 0x18,0x41,0xCF,0x2F,0xA9,0xC8,0x4D,0x57,0x4E,0x84,0x28,0x0F,0xC9,0x3A,0xEF,0xB6, - 0x3D,0x9C,0xE9,0x96,0x12,0xFA,0xF2,0x35,0xA0,0xF1,0xDB,0x9D,0x0A,0x65,0x23,0xBB, - 0xC9,0x38,0xCC,0x39,0x7E,0x6B,0x17,0x80,0x48,0xF1,0xAC,0xF3,0x12,0x33,0x7B,0xBE, - 0x5E,0x7B,0xC4,0x8D,0xC6,0xB9,0x9B,0x85,0x0A,0x8A,0x52,0x4F,0x5E,0xC7,0x1F,0x12, - 0xDB,0xA5,0xBA,0x33,0x9E,0xA2,0x3A,0x9E,0x11,0x82,0x4E,0x42,0x0E,0x3F,0x82,0xDF, - 0x36,0x91,0xF7,0x24,0xB6,0xFC,0x6D,0x00,0x19,0xF2,0xD0,0x31,0x70,0x1F,0xED,0xE6, - 0x37,0xED,0x1D,0xB3,0xDB,0x06,0x01,0x90,0x0E,0x95,0x9B,0xD6,0x34,0x5F,0xFA,0xE6, - 0xD1,0x34,0xA6,0xD9,0x61,0x63,0x3E,0x2D,0x59,0x7B,0xD4,0xA5,0x9E,0x3F,0xFE,0xFE, - 0x58,0xC9,0x60,0xAE,0xA4,0xC2,0xCB,0xA6,0x50,0x9D,0x50,0xDB,0x38,0x80,0x2F,0xC9, - 0x2A,0xC5,0xEF,0x98,0xCF, -}; - -static unsigned char revoked_ist_certificate[1515]={ - 0x30,0x82,0x05,0xE7,0x30,0x82,0x04,0xCF,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x7F, - 0x00,0xCE,0x8A,0xD6,0x3F,0x5B,0x34,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04, - 0x03,0x13,0x13,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43,0x41,0x20, - 0x32,0x20,0x2D,0x20,0x47,0x31,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13, - 0x17,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,0x13,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,0x34, - 0x31,0x31,0x32,0x38,0x31,0x35,0x30,0x36,0x31,0x34,0x5A,0x17,0x0D,0x31,0x36,0x31, - 0x32,0x32,0x37,0x31,0x35,0x30,0x36,0x31,0x34,0x5A,0x30,0x81,0xAB,0x31,0x4B,0x30, - 0x49,0x06,0x03,0x55,0x04,0x03,0x0C,0x42,0x72,0x65,0x76,0x6F,0x6B,0x65,0x64,0x2E, - 0x67,0x65,0x6F,0x74,0x72,0x75,0x73,0x74,0x2D,0x67,0x6C,0x6F,0x62,0x61,0x6C,0x2D, - 0x63,0x61,0x2E,0x74,0x65,0x73,0x74,0x2D,0x70,0x61,0x67,0x65,0x73,0x2E,0x63,0x65, - 0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x6D,0x61,0x6E,0x61,0x67,0x65,0x72, - 0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x25,0x30,0x23,0x06,0x03, - 0x55,0x04,0x0B,0x0C,0x1C,0x6D,0x61,0x6E,0x61,0x67,0x65,0x6D,0x65,0x6E,0x74,0x3A, - 0x69,0x64,0x6D,0x73,0x2E,0x67,0x72,0x6F,0x75,0x70,0x2E,0x31,0x37,0x36,0x33,0x39, - 0x39,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, - 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x0B,0x30,0x09,0x06, - 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,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,0xA9,0xD7,0xE0,0x65,0x48,0x36,0x8A, - 0x4B,0x6C,0xBB,0x16,0xAF,0xFD,0x09,0xA5,0x9C,0x30,0xDA,0xC5,0x9B,0x3D,0xD6,0xB4, - 0x8E,0x6B,0xC2,0xF4,0xBF,0x30,0xA7,0xCC,0xF7,0xA1,0x23,0x58,0xA0,0x16,0xE8,0x31, - 0x5F,0xE7,0xD2,0x21,0x3D,0x24,0x3D,0xF4,0x1E,0x82,0x46,0x45,0xA0,0xB8,0x2E,0xD7, - 0xB6,0x86,0xD3,0x2A,0xBC,0x93,0x74,0x44,0xAB,0x1C,0x9F,0x86,0xBF,0x19,0xCE,0xA4, - 0xD0,0xC9,0xB9,0x65,0x84,0x89,0x87,0xDE,0x77,0xDC,0xAE,0x85,0xA9,0xDE,0x5A,0xCF, - 0xAF,0x46,0x80,0x45,0x72,0x68,0x87,0x55,0x5B,0x4D,0x49,0xE2,0x7B,0x25,0x31,0x22, - 0x00,0x87,0xAB,0x72,0xEB,0x9A,0x2D,0x81,0x35,0x0E,0x76,0x82,0x5C,0x99,0x10,0xFB, - 0xD6,0x3F,0x29,0xE8,0xFD,0x2E,0xAD,0xF6,0xF8,0xCF,0xC1,0x99,0x5F,0xDA,0xC1,0xB3, - 0x90,0x70,0xA5,0x4B,0x23,0x4D,0xD6,0x1D,0xC9,0x73,0x27,0xD1,0xAE,0x38,0xA3,0xD0, - 0x71,0x92,0xFF,0x89,0xA8,0xE5,0x51,0x3E,0x2F,0xB6,0xB4,0x02,0x20,0x54,0x62,0xA0, - 0x69,0x6D,0xB6,0x10,0x8D,0xB7,0x13,0x2A,0x94,0x4E,0xED,0x73,0x8C,0x78,0x39,0xF6, - 0x04,0xC0,0xF8,0x7A,0x75,0x2D,0x1E,0x82,0x7E,0x55,0x7B,0xE7,0xA7,0xFA,0x6E,0xB1, - 0x53,0x81,0x75,0xB6,0x19,0xD8,0xD2,0xD3,0x8E,0x30,0x95,0x0D,0xD8,0xC9,0xBA,0x3F, - 0x70,0x23,0xC3,0x7B,0xE2,0x6E,0xA9,0xA8,0x91,0x69,0x89,0x8D,0xEA,0x64,0x5D,0x8E, - 0x49,0x43,0x30,0x99,0xBC,0x54,0x97,0xAC,0xEB,0x98,0x09,0x8C,0xE9,0xA7,0xE8,0xDC, - 0xFC,0xE4,0xBE,0x20,0xDA,0xA1,0x88,0xB6,0x99,0x02,0x03,0x01,0x00,0x01,0xA3,0x82, - 0x02,0x55,0x30,0x82,0x02,0x51,0x30,0x48,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x01,0x01,0x04,0x3C,0x30,0x3A,0x30,0x38,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x30,0x01,0x86,0x2C,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E, - 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30,0x34, - 0x2D,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74,0x63,0x61,0x32,0x67,0x31,0x30,0x31, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x75,0x81,0x7F,0xDF,0xDE, - 0x90,0xE2,0xFB,0x67,0xA8,0x04,0xC9,0x82,0xE1,0x2A,0x13,0x08,0x3D,0xCE,0x8E,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,0xD8,0x7A,0x94,0x44,0x7C,0x90, - 0x70,0x90,0x16,0x9E,0xDD,0x17,0x9C,0x01,0x44,0x03,0x86,0xD6,0x2A,0x29,0x30,0x81, - 0xFF,0x06,0x03,0x55,0x1D,0x20,0x04,0x81,0xF7,0x30,0x81,0xF4,0x30,0x81,0xF1,0x06, - 0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x05,0x0B,0x04,0x30,0x81,0xE2,0x30,0x81, - 0xA4,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30,0x81,0x97,0x0C,0x81, - 0x94,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,0x61,0x73,0x73,0x75,0x6D, - 0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70,0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66, - 0x20,0x61,0x6E,0x79,0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20, - 0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20,0x63,0x6F,0x6E,0x64,0x69,0x74, - 0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x6E,0x64,0x2F, - 0x6F,0x72,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, - 0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20,0x73,0x74,0x61,0x74,0x65,0x6D, - 0x65,0x6E,0x74,0x73,0x2E,0x30,0x39,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02, - 0x01,0x16,0x2D,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,0x72,0x70,0x61, - 0x30,0x37,0x06,0x03,0x55,0x1D,0x1F,0x04,0x30,0x30,0x2E,0x30,0x2C,0xA0,0x2A,0xA0, - 0x28,0x86,0x26,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61,0x70, - 0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x69,0x73,0x74, - 0x63,0x61,0x32,0x67,0x31,0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25, - 0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x4D,0x06,0x03,0x55,0x1D,0x11,0x04, - 0x46,0x30,0x44,0x82,0x42,0x72,0x65,0x76,0x6F,0x6B,0x65,0x64,0x2E,0x67,0x65,0x6F, - 0x74,0x72,0x75,0x73,0x74,0x2D,0x67,0x6C,0x6F,0x62,0x61,0x6C,0x2D,0x63,0x61,0x2E, - 0x74,0x65,0x73,0x74,0x2D,0x70,0x61,0x67,0x65,0x73,0x2E,0x63,0x65,0x72,0x74,0x69, - 0x66,0x69,0x63,0x61,0x74,0x65,0x6D,0x61,0x6E,0x61,0x67,0x65,0x72,0x2E,0x61,0x70, - 0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, - 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xC0,0x5B,0xA6,0xAF,0x2C, - 0x27,0xBA,0x49,0x8D,0x41,0xF6,0xC4,0x02,0xEE,0x9D,0xB1,0x48,0xC3,0x34,0x7B,0xF2, - 0xD2,0x82,0x49,0xA5,0x13,0x5A,0x66,0xAD,0xC9,0x73,0xBF,0x6B,0xC9,0x30,0x86,0xBA, - 0x7A,0xD2,0x9D,0x61,0xFE,0x04,0x07,0x15,0x66,0xC2,0x25,0xF7,0x6C,0x88,0xB1,0x0E, - 0x22,0x11,0xF9,0x26,0xA7,0x4E,0x88,0x96,0x20,0x99,0xA6,0x51,0xEE,0x02,0x96,0xC7, - 0xA4,0xCA,0xD4,0xAB,0xFC,0x5F,0x96,0x16,0x0D,0x8D,0xA0,0xA1,0x17,0x6E,0x77,0x92, - 0xC9,0x64,0xD9,0xA2,0x5A,0x00,0x08,0xA6,0x55,0x73,0x2C,0xDD,0xD3,0x0C,0xA5,0xCA, - 0x68,0x48,0xAE,0xCE,0x5F,0xF2,0x56,0x4A,0x66,0x57,0xB2,0x2D,0xB5,0xC6,0xFF,0x50, - 0xD8,0x36,0x9C,0x31,0x31,0xE8,0xB2,0x07,0xE2,0x7B,0xC0,0xCE,0x72,0xA4,0x60,0x91, - 0xBB,0x84,0xA7,0xA8,0xC0,0x1D,0x42,0xE8,0x1D,0xF5,0xD9,0x6B,0x85,0x67,0x23,0x20, - 0xA6,0xF8,0x0F,0xBA,0x83,0x63,0x49,0xE2,0x79,0x23,0x90,0xFF,0x6B,0xEF,0xFA,0xB4, - 0x04,0xA8,0x99,0x1E,0x5D,0x5A,0xCD,0x8C,0xBC,0x8E,0x30,0x41,0x7E,0xE7,0x4E,0xDB, - 0x6F,0x4E,0xB7,0xBA,0xE0,0x5B,0x31,0xC4,0xD2,0x2D,0xD3,0x5D,0x82,0x95,0x44,0x7D, - 0x11,0x60,0x75,0xCE,0x6D,0x12,0xDA,0x89,0x71,0x23,0x80,0x75,0xC0,0x13,0x67,0x27, - 0xE8,0xE8,0xCA,0xE0,0xE3,0xFC,0x72,0x23,0x98,0xFA,0xF0,0x96,0x05,0x23,0xC9,0x03, - 0xC8,0x29,0xA4,0xB1,0xE5,0x07,0xE6,0xE8,0x09,0x26,0xD1,0x8C,0xAF,0xE0,0x53,0xBB, - 0xB4,0x1E,0x4D,0x5E,0xEA,0x9A,0x1E,0xE9,0x42,0x87,0x9F, -}; - -static unsigned char ist_intermediate_certificate[1092]={ - 0x30,0x82,0x04,0x40,0x30,0x82,0x03,0x28,0xA0,0x03,0x02,0x01,0x02,0x02,0x03,0x02, - 0x3A,0x74,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, - 0x00,0x30,0x42,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, - 0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x0A,0x13,0x0D,0x47,0x65,0x6F,0x54,0x72, - 0x75,0x73,0x74,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04, - 0x03,0x13,0x12,0x47,0x65,0x6F,0x54,0x72,0x75,0x73,0x74,0x20,0x47,0x6C,0x6F,0x62, - 0x61,0x6C,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x36,0x31,0x36,0x31, - 0x35,0x34,0x32,0x30,0x32,0x5A,0x17,0x0D,0x32,0x32,0x30,0x35,0x32,0x30,0x31,0x35, - 0x34,0x32,0x30,0x32,0x5A,0x30,0x62,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x03, - 0x13,0x13,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x53,0x54,0x20,0x43,0x41,0x20,0x32, - 0x20,0x2D,0x20,0x47,0x31,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x13,0x17, - 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, - 0x13,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,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,0xD0,0x93,0xA1,0x1D,0x47,0x43, - 0x20,0x16,0xB2,0x0B,0x6B,0xEB,0xC3,0xD5,0xB4,0xE8,0xC7,0x98,0xCD,0xF3,0xDE,0xBF, - 0xE8,0x4D,0xE9,0xE3,0x36,0x80,0x07,0xFC,0x45,0x1B,0x6A,0x7C,0x45,0x86,0xAE,0x56, - 0xD3,0xA4,0x09,0x7F,0x61,0x0D,0x6B,0x5D,0x7E,0x52,0x6B,0x7D,0xB4,0xC8,0x39,0xC4, - 0xF4,0x67,0x3A,0xF7,0x83,0xCE,0x19,0x6F,0x86,0x2F,0x7E,0x45,0x7E,0x47,0x1C,0x67, - 0x52,0xCA,0x95,0x05,0x5D,0xE2,0x36,0x51,0x85,0xC0,0xD4,0x67,0x80,0x35,0x6F,0x15, - 0xDD,0x3E,0xFD,0x1D,0xD2,0xFD,0x8F,0x34,0x50,0xD8,0xEC,0x76,0x2A,0xBE,0xE3,0xD3, - 0xDA,0xE4,0xFD,0xC8,0xEB,0x28,0x02,0x96,0x11,0x97,0x17,0x61,0x1C,0xE9,0xC4,0x59, - 0x3B,0x42,0xDC,0x32,0xD1,0x09,0x1D,0xDA,0xA6,0xD1,0x43,0x86,0xFF,0x5E,0xB2,0xBC, - 0x8C,0xCF,0x66,0xDB,0x01,0x8B,0x02,0xAE,0x94,0x48,0xF3,0x38,0x8F,0xFD,0xEA,0x32, - 0xA8,0x08,0xEC,0x86,0x97,0x51,0x94,0x24,0x3E,0x49,0x49,0x96,0x53,0xE8,0x79,0xA1, - 0x40,0x81,0xE9,0x05,0xBB,0x93,0x95,0x51,0xFC,0xE3,0xFD,0x7C,0x11,0x4B,0xF7,0x9E, - 0x08,0xB3,0x15,0x49,0x15,0x07,0xF9,0xD1,0x37,0xA0,0x9B,0x4B,0x32,0xF6,0xB5,0xC4, - 0xDC,0x6A,0xD1,0xFC,0x0A,0xED,0xF6,0xE0,0xC5,0x29,0xA0,0xA8,0x8B,0x71,0xFE,0x0D, - 0x92,0xBC,0xFE,0x54,0x70,0x18,0x0A,0x6D,0xC7,0xED,0x0C,0xFB,0xC9,0x2D,0x06,0xC3, - 0x8C,0x85,0xFC,0xCB,0x86,0x5C,0xD6,0x36,0x8E,0x12,0x8B,0x09,0x7F,0xFB,0x19,0x1A, - 0x38,0xD5,0xF0,0x94,0x30,0x7A,0x0F,0xA6,0x8C,0xF3,0x02,0x03,0x01,0x00,0x01,0xA3, - 0x82,0x01,0x1D,0x30,0x82,0x01,0x19,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18, - 0x30,0x16,0x80,0x14,0xC0,0x7A,0x98,0x68,0x8D,0x89,0xFB,0xAB,0x05,0x64,0x0C,0x11, - 0x7D,0xAA,0x7D,0x65,0xB8,0xCA,0xCC,0x4E,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04, - 0x16,0x04,0x14,0xD8,0x7A,0x94,0x44,0x7C,0x90,0x70,0x90,0x16,0x9E,0xDD,0x17,0x9C, - 0x01,0x44,0x03,0x86,0xD6,0x2A,0x29,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01, - 0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x0E,0x06,0x03,0x55, - 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x35,0x06,0x03,0x55, - 0x1D,0x1F,0x04,0x2E,0x30,0x2C,0x30,0x2A,0xA0,0x28,0xA0,0x26,0x86,0x24,0x68,0x74, - 0x74,0x70,0x3A,0x2F,0x2F,0x67,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D, - 0x2F,0x63,0x72,0x6C,0x73,0x2F,0x67,0x74,0x67,0x6C,0x6F,0x62,0x61,0x6C,0x2E,0x63, - 0x72,0x6C,0x30,0x2E,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x22, - 0x30,0x20,0x30,0x1E,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x12, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x67,0x2E,0x73,0x79,0x6D,0x63,0x64,0x2E,0x63, - 0x6F,0x6D,0x30,0x4C,0x06,0x03,0x55,0x1D,0x20,0x04,0x45,0x30,0x43,0x30,0x41,0x06, - 0x0A,0x60,0x86,0x48,0x01,0x86,0xF8,0x45,0x01,0x07,0x36,0x30,0x33,0x30,0x31,0x06, - 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x25,0x68,0x74,0x74,0x70,0x3A, - 0x2F,0x2F,0x77,0x77,0x77,0x2E,0x67,0x65,0x6F,0x74,0x72,0x75,0x73,0x74,0x2E,0x63, - 0x6F,0x6D,0x2F,0x72,0x65,0x73,0x6F,0x75,0x72,0x63,0x65,0x73,0x2F,0x63,0x70,0x73, - 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03, - 0x82,0x01,0x01,0x00,0x16,0x47,0x73,0x6F,0x85,0xA2,0x62,0xE1,0xE7,0x2A,0x76,0xBB, - 0x89,0x95,0x42,0x26,0x97,0xBC,0x4A,0xAC,0xAC,0x70,0x53,0x3A,0x3F,0x31,0x83,0x3D, - 0x3C,0x1C,0xAB,0x9A,0xE2,0xB1,0x5D,0x1C,0x76,0x1A,0xA0,0x3C,0x0C,0x72,0x57,0xBE, - 0xD3,0x9E,0x50,0xE0,0xC8,0x99,0xD6,0x58,0xD7,0x02,0xEA,0xCE,0x0D,0x29,0x54,0x7C, - 0xCD,0xF5,0xC2,0xC6,0x90,0x29,0x55,0xA3,0x6F,0x14,0xA8,0x0B,0x42,0x0D,0x3A,0x98, - 0x6D,0x06,0x78,0x9E,0xF0,0x6A,0xA3,0x1D,0x02,0x0A,0xA2,0x28,0xA4,0x8D,0xC2,0x81, - 0x46,0x3E,0x6D,0x67,0xDA,0xDE,0x3F,0xFE,0x85,0x0E,0x42,0x2A,0x12,0xDE,0xB5,0xB7, - 0xFB,0xB8,0x1B,0xA7,0x96,0xEC,0x77,0x9F,0xEC,0xD4,0x53,0x95,0x7A,0xFF,0x07,0xF4, - 0xF2,0x0A,0x14,0xC0,0x51,0x52,0xB1,0xD6,0x8E,0x50,0x0B,0x1A,0x99,0x5C,0xBC,0x0B, - 0xC9,0xBD,0xED,0xED,0xF8,0x5E,0xC1,0x56,0xDB,0x4D,0x7E,0x23,0xA4,0x11,0xA1,0x2C, - 0xD4,0x1B,0x05,0x9A,0xE4,0x1B,0x52,0xF6,0x7C,0x38,0x99,0x05,0x4B,0xBA,0x72,0x8D, - 0x42,0x89,0x60,0x04,0x66,0x2A,0xF4,0xFD,0x68,0xD7,0x6B,0xF7,0x99,0x41,0x28,0xD6, - 0x6C,0x24,0xAB,0xE6,0x25,0x53,0x2E,0xC8,0x82,0x99,0xE2,0xA2,0x8F,0x23,0xBE,0x30, - 0x83,0xB1,0x27,0x8B,0xFA,0x68,0x7F,0x01,0x49,0xE8,0xC6,0x98,0x6B,0x10,0x2E,0x98, - 0x5E,0x8A,0xD7,0xCA,0x4B,0xB1,0xC7,0xC9,0x58,0x9A,0xD0,0x36,0xDB,0x96,0x95,0xEC, - 0xB6,0x81,0xE4,0xF2,0xCD,0x6F,0x1B,0x79,0x87,0x4C,0x10,0x3C,0x89,0xE4,0x4D,0xFA, - 0x54,0xDC,0xAA,0xA6, -}; - -unsigned char ocsp_smime_leaf_certificate[1338]={ - 0x30,0x82,0x05,0x36,0x30,0x82,0x04,0x1E,0xA0,0x03,0x02,0x01,0x02,0x02,0x0D,0x14, - 0x00,0x01,0x00,0x02,0x9C,0xE1,0xB9,0xE0,0x7C,0xD1,0x7B,0xEC,0x30,0x0D,0x06,0x09, - 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x7C,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03, - 0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E, - 0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04, - 0x0B,0x13,0x1C,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65, - 0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20,0x43,0x41,0x31, - 0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1F,0x54,0x43,0x20,0x54,0x72,0x75, - 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31, - 0x20,0x4C,0x31,0x20,0x43,0x41,0x20,0x49,0x58,0x30,0x1E,0x17,0x0D,0x31,0x30,0x31, - 0x31,0x31,0x32,0x30,0x36,0x33,0x36,0x34,0x35,0x5A,0x17,0x0D,0x31,0x31,0x31,0x31, - 0x31,0x33,0x30,0x36,0x33,0x36,0x34,0x35,0x5A,0x30,0x24,0x31,0x0B,0x30,0x09,0x06, - 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04, - 0x03,0x13,0x0C,0x51,0x75,0x69,0x6E,0x6E,0x20,0x54,0x61,0x79,0x6C,0x6F,0x72,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, - 0xC1,0x11,0xAA,0x04,0xCF,0x04,0xA0,0x07,0xF3,0x43,0x2A,0xB2,0x27,0x1A,0x13,0x35, - 0x97,0x9A,0xBA,0x34,0xE5,0x84,0xF3,0xD5,0xE5,0xD9,0xAB,0x23,0x8D,0xB4,0x7E,0x68, - 0x5C,0xF2,0x9A,0xF1,0x08,0x9B,0x04,0x34,0xC1,0x09,0x14,0x68,0xD8,0x9C,0xC1,0x6C, - 0x27,0xF5,0x92,0x54,0xAF,0x66,0x65,0xF1,0x50,0xAA,0x7E,0xE3,0xFC,0xC1,0xB0,0x3E, - 0xEF,0xAA,0x86,0x58,0x4F,0xE7,0x86,0x0A,0x74,0xA6,0x97,0xBD,0x7D,0xF6,0xCE,0xA6, - 0x8B,0xF7,0xC0,0x90,0x6E,0x50,0x69,0x36,0x65,0x82,0x0F,0x65,0xA7,0x2C,0x16,0xFA, - 0x6C,0xCA,0x54,0x45,0x7C,0x06,0x20,0x72,0xF0,0x00,0x7B,0xD7,0x17,0xCD,0x94,0x64, - 0x6A,0xB7,0x28,0xF3,0x62,0xB1,0x29,0xAE,0x0C,0x8A,0x2F,0x3C,0x06,0x89,0xE8,0x81, - 0x77,0xAD,0x1F,0x65,0xED,0x6F,0x51,0x64,0x65,0x68,0x76,0xD8,0xEE,0xEC,0xA6,0x28, - 0xA9,0x1C,0x4F,0x98,0x4A,0x6D,0xD0,0xC8,0x5C,0x59,0x17,0x9B,0xF8,0x6D,0xF5,0x93, - 0xD3,0x4C,0x2A,0x37,0x80,0x65,0xB4,0x34,0xBA,0x64,0x2F,0xA1,0x8E,0x1C,0x6A,0x88, - 0x7C,0xA3,0xDB,0xDD,0x00,0x9B,0x78,0x51,0x7B,0xA6,0x8D,0xDD,0x43,0x9B,0xB2,0x2E, - 0x4B,0x1E,0xB3,0x34,0x37,0x3F,0x63,0x08,0x8C,0xC8,0xCF,0xD0,0xB0,0x8C,0xBF,0x8F, - 0xA7,0x49,0xBD,0x48,0x1D,0xB5,0x1E,0x6A,0x42,0x48,0x16,0x9A,0x7C,0xD3,0x55,0x6B, - 0xFF,0xD6,0xBA,0x70,0xF3,0x5F,0x1F,0x57,0x16,0xE0,0x1C,0xF1,0x73,0x22,0xD9,0x33, - 0xA7,0x20,0xE8,0xED,0x52,0x2A,0xE9,0x6F,0xCF,0xFB,0x76,0xAC,0xB8,0x5D,0x9B,0xAB, - 0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x02,0x0D,0x30,0x82,0x02,0x09,0x30,0x81,0xA5, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x81,0x98,0x30,0x81,0x95, - 0x30,0x51,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x45,0x68,0x74, - 0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65, - 0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x65,0x72,0x74,0x73,0x65,0x72,0x76, - 0x69,0x63,0x65,0x73,0x2F,0x63,0x61,0x63,0x65,0x72,0x74,0x73,0x2F,0x74,0x63,0x5F, - 0x63,0x6C,0x61,0x73,0x73,0x31,0x5F,0x4C,0x31,0x5F,0x43,0x41,0x5F,0x49,0x58,0x2E, - 0x63,0x72,0x74,0x30,0x40,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86, - 0x34,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x69,0x78,0x2E, - 0x74,0x63,0x63,0x6C,0x61,0x73,0x73,0x31,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65, - 0x72,0x73,0x61,0x6C,0x2D,0x69,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2E,0x64,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, - 0x80,0x14,0xE9,0xB8,0x28,0x1D,0x46,0xCF,0xFC,0xCD,0xF8,0x4E,0x9B,0xC5,0xEE,0x4B, - 0x60,0xEB,0xD8,0x3B,0x3F,0xD1,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF, - 0x04,0x02,0x30,0x00,0x30,0x4A,0x06,0x03,0x55,0x1D,0x20,0x04,0x43,0x30,0x41,0x30, - 0x3F,0x06,0x09,0x2A,0x82,0x14,0x00,0x2C,0x01,0x01,0x01,0x01,0x30,0x32,0x30,0x30, - 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x24,0x68,0x74,0x74,0x70, - 0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2E,0x64,0x65,0x2F,0x67,0x75,0x69,0x64,0x65,0x6C,0x69,0x6E,0x65,0x73, - 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x04,0xF0, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xF8,0x4D,0x7F,0xDE,0xFA, - 0x21,0x2E,0xAF,0x96,0xBB,0xAA,0x9B,0x22,0x56,0x80,0xF0,0x8E,0xD4,0x6A,0x52,0x30, - 0x62,0x06,0x03,0x55,0x1D,0x1F,0x04,0x5B,0x30,0x59,0x30,0x57,0xA0,0x55,0xA0,0x53, - 0x86,0x51,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x69,0x78,0x2E, - 0x74,0x63,0x63,0x6C,0x61,0x73,0x73,0x31,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65, - 0x72,0x73,0x61,0x6C,0x2D,0x69,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x72,0x6C,0x2F,0x76,0x32,0x2F,0x74,0x63,0x5F, - 0x43,0x6C,0x61,0x73,0x73,0x31,0x5F,0x4C,0x31,0x5F,0x43,0x41,0x5F,0x49,0x58,0x2E, - 0x63,0x72,0x6C,0x30,0x33,0x06,0x03,0x55,0x1D,0x25,0x04,0x2C,0x30,0x2A,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x03,0x04,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x07,0x06,0x0A,0x2B,0x06, - 0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x02,0x30,0x1C,0x06,0x03,0x55,0x1D,0x11,0x04, - 0x15,0x30,0x13,0x81,0x11,0x71,0x74,0x61,0x79,0x6C,0x6F,0x72,0x40,0x61,0x70,0x70, - 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, - 0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x0D,0xCF,0x33,0xAB,0x3D,0xD3, - 0xD2,0x06,0x2C,0x20,0x3C,0xEC,0x0C,0xE4,0xA5,0x19,0x86,0xB3,0xA7,0xA9,0xA6,0xE9, - 0xDC,0xB4,0x35,0xBB,0x0D,0x67,0xD5,0xBD,0x5F,0x93,0xD9,0x2E,0xA0,0x05,0x2A,0xED, - 0xAE,0x41,0xD9,0xEE,0x30,0xA8,0x82,0x50,0xD0,0x4B,0x04,0x6B,0x37,0xAE,0xC0,0x10, - 0x89,0x05,0x68,0x82,0x91,0x2B,0x5B,0xE2,0x7D,0xA6,0x87,0xF7,0x26,0x96,0xBA,0x2A, - 0x52,0x03,0x97,0xF6,0x2E,0x0D,0x81,0x65,0x24,0x10,0xD5,0x8C,0xB3,0xCD,0x19,0x58, - 0xAF,0x3A,0x3D,0x2F,0x10,0x30,0x79,0x6A,0xD6,0x08,0x8F,0x8B,0x9D,0x1D,0xF8,0x19, - 0xE4,0x24,0x2B,0xE0,0x7F,0x73,0xE1,0x50,0x9C,0x53,0xE1,0x46,0xC7,0xA7,0xBD,0x71, - 0xCD,0xFF,0x39,0xA0,0x50,0xA5,0xA8,0xD9,0x50,0x39,0x6C,0x36,0x1C,0x13,0x89,0x8A, - 0x0D,0x9D,0x06,0x1B,0xAA,0x59,0x40,0xC1,0xAF,0xED,0x66,0x31,0xB8,0xA0,0x9F,0xCF, - 0xA6,0x8A,0x2E,0xC2,0x1A,0x4B,0xDB,0x62,0x15,0x6E,0x10,0x2F,0x82,0x3C,0xF8,0xA2, - 0x18,0x63,0xCC,0x67,0x13,0x42,0x07,0x43,0xDB,0x20,0x13,0xC7,0xAC,0xCE,0xCB,0xEA, - 0x7E,0x53,0xA6,0x01,0x81,0xB2,0x6E,0x92,0x2B,0x0C,0xF9,0x01,0x2C,0x11,0xC9,0x00, - 0x10,0x58,0x64,0x56,0x91,0xAC,0xAA,0xF6,0xE0,0x73,0xC7,0x59,0xEC,0xCE,0x51,0x7E, - 0xAD,0x9F,0x04,0xA4,0x38,0x74,0x65,0xD0,0x23,0xBD,0x6E,0xDF,0x64,0x79,0xE2,0xA3, - 0x37,0x19,0x2F,0x8C,0x41,0x8B,0x5F,0x6D,0x84,0x61,0x54,0xD1,0x26,0x18,0x70,0xAD, - 0xE5,0xF4,0xCD,0x59,0xED,0x9E,0xE0,0xC9,0x9F,0xD3, -}; - -unsigned char ocsp_smime_CA_certificate[1500]={ - 0x30,0x82,0x05,0xD8,0x30,0x82,0x04,0xC0,0xA0,0x03,0x02,0x01,0x02,0x02,0x0E,0x06, - 0xE8,0x00,0x01,0x00,0x02,0x4A,0x96,0x2D,0x24,0x0C,0xFE,0xC5,0xC9,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x79,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, - 0x6E,0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55, - 0x04,0x0B,0x13,0x1B,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74, - 0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31, - 0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75, - 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73, - 0x61,0x6C,0x20,0x43,0x41,0x20,0x49,0x30,0x1E,0x17,0x0D,0x30,0x39,0x31,0x31,0x30, - 0x33,0x31,0x34,0x30,0x38,0x31,0x39,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x33,0x31, - 0x32,0x31,0x35,0x39,0x35,0x39,0x5A,0x30,0x7C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0A,0x13, - 0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20, - 0x47,0x6D,0x62,0x48,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x13,0x1C,0x54, - 0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x43,0x6C, - 0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20,0x43,0x41,0x31,0x28,0x30,0x26,0x06, - 0x03,0x55,0x04,0x03,0x13,0x1F,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, - 0x6E,0x74,0x65,0x72,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x31,0x20,0x4C,0x31,0x20, - 0x43,0x41,0x20,0x49,0x58,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,0xBB,0xE6,0x90,0x6E,0xCF,0x62,0xE9,0xE9,0x0B,0xAA, - 0xB6,0x10,0xD5,0x47,0xE5,0x7C,0x5D,0x2B,0x27,0x71,0x9A,0x68,0xCD,0x55,0x6D,0xE4, - 0xA2,0xEF,0xE4,0xFE,0xF2,0x7A,0x63,0x11,0xC2,0x57,0x8A,0xC8,0x7D,0xCF,0x8E,0x66, - 0x1F,0x65,0x45,0x4B,0xEB,0x80,0x62,0x69,0xBD,0x46,0x8E,0x8B,0xC5,0x6E,0x5A,0x95, - 0x18,0x2A,0xDE,0xA7,0xF1,0x1F,0x75,0x1A,0x27,0xAB,0x6D,0x32,0x53,0xE3,0xFB,0x4D, - 0x58,0x62,0x2C,0xFF,0x19,0xE5,0xC7,0xA0,0x0D,0x9A,0x2D,0x21,0x88,0x59,0x84,0xCD, - 0x1D,0xF1,0xC3,0xC8,0x8A,0x3E,0xB0,0xE5,0xDE,0x08,0x24,0xCF,0xFC,0x40,0x2C,0xBA, - 0x41,0x23,0x94,0xBB,0x80,0x12,0x89,0x35,0x48,0xB6,0x86,0x04,0xE0,0x01,0x4F,0x8C, - 0xBA,0xA9,0x98,0xFC,0x1C,0x89,0xED,0x1F,0x8A,0xA1,0xC7,0x86,0x98,0x26,0x1E,0x72, - 0x65,0x6B,0xFE,0xCF,0x65,0xD9,0x0C,0x64,0x4B,0x1A,0x09,0xF5,0x43,0x11,0x60,0x66, - 0x26,0xE3,0x33,0x56,0x9A,0xC9,0x3D,0x3E,0x34,0x6A,0x78,0xC6,0xE5,0x50,0x4B,0xC8, - 0xCD,0x88,0xE4,0x39,0x6C,0x50,0x26,0x9E,0x40,0x2C,0xB6,0x3B,0x7C,0x37,0xB2,0xA7, - 0xF5,0xDD,0xDC,0xB3,0x51,0xCB,0xF4,0xDC,0x82,0x02,0xB8,0xD7,0x3A,0xDE,0xDA,0x30, - 0x5C,0x0D,0xF5,0x42,0xDD,0x13,0x69,0x53,0x54,0xE9,0x80,0x26,0x42,0x33,0x1E,0xA5, - 0xD7,0xCC,0x6E,0xCA,0x66,0x09,0x9F,0x86,0xF0,0x3D,0xBE,0xC6,0x8A,0x61,0x10,0xF3, - 0xD1,0xFF,0x5B,0xE4,0xB2,0xDB,0x2D,0xB2,0x65,0x0C,0xA9,0x7D,0x17,0xAC,0xBA,0x27, - 0x4D,0x42,0x5C,0xCE,0x09,0x4F,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x02,0x59,0x30, - 0x82,0x02,0x55,0x30,0x81,0x9A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, - 0x04,0x81,0x8D,0x30,0x81,0x8A,0x30,0x52,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x30,0x02,0x86,0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x74, - 0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x65, - 0x72,0x74,0x73,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x2F,0x63,0x61,0x63,0x65,0x72, - 0x74,0x73,0x2F,0x74,0x63,0x5F,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x5F, - 0x72,0x6F,0x6F,0x74,0x5F,0x49,0x2E,0x63,0x72,0x74,0x30,0x34,0x06,0x08,0x2B,0x06, - 0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x28,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F, - 0x63,0x73,0x70,0x2E,0x74,0x63,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x2D, - 0x49,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65, - 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x92,0xA4,0x75, - 0x2C,0xA4,0x9E,0xBE,0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75, - 0x73,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01, - 0x01,0xFF,0x02,0x01,0x00,0x30,0x52,0x06,0x03,0x55,0x1D,0x20,0x04,0x4B,0x30,0x49, - 0x30,0x06,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x3F,0x06,0x09,0x2A,0x82,0x14,0x00, - 0x2C,0x01,0x01,0x01,0x01,0x30,0x32,0x30,0x30,0x06,0x08,0x2B,0x06,0x01,0x05,0x05, - 0x07,0x02,0x01,0x16,0x24,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E, - 0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x67, - 0x75,0x69,0x64,0x65,0x6C,0x69,0x6E,0x65,0x73,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, - 0x04,0x16,0x04,0x14,0xE9,0xB8,0x28,0x1D,0x46,0xCF,0xFC,0xCD,0xF8,0x4E,0x9B,0xC5, - 0xEE,0x4B,0x60,0xEB,0xD8,0x3B,0x3F,0xD1,0x30,0x81,0xFD,0x06,0x03,0x55,0x1D,0x1F, - 0x04,0x81,0xF5,0x30,0x81,0xF2,0x30,0x81,0xEF,0xA0,0x81,0xEC,0xA0,0x81,0xE9,0x86, - 0x46,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x74,0x63,0x75,0x6E, - 0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x2D,0x49,0x2E,0x74,0x72,0x75,0x73,0x74,0x63, - 0x65,0x6E,0x74,0x65,0x72,0x2E,0x64,0x65,0x2F,0x63,0x72,0x6C,0x2F,0x76,0x32,0x2F, - 0x74,0x63,0x5F,0x75,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x5F,0x72,0x6F,0x6F, - 0x74,0x5F,0x49,0x2E,0x63,0x72,0x6C,0x86,0x81,0x9E,0x6C,0x64,0x61,0x70,0x3A,0x2F, - 0x2F,0x77,0x77,0x77,0x2E,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74,0x65,0x72, - 0x2E,0x64,0x65,0x2F,0x43,0x4E,0x3D,0x54,0x43,0x25,0x32,0x30,0x54,0x72,0x75,0x73, - 0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x25,0x32,0x30,0x55,0x6E,0x69,0x76,0x65,0x72, - 0x73,0x61,0x6C,0x25,0x32,0x30,0x43,0x41,0x25,0x32,0x30,0x49,0x2C,0x4F,0x3D,0x54, - 0x43,0x25,0x32,0x30,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x25, - 0x32,0x30,0x47,0x6D,0x62,0x48,0x2C,0x4F,0x55,0x3D,0x72,0x6F,0x6F,0x74,0x63,0x65, - 0x72,0x74,0x73,0x2C,0x44,0x43,0x3D,0x74,0x72,0x75,0x73,0x74,0x63,0x65,0x6E,0x74, - 0x65,0x72,0x2C,0x44,0x43,0x3D,0x64,0x65,0x3F,0x63,0x65,0x72,0x74,0x69,0x66,0x69, - 0x63,0x61,0x74,0x65,0x52,0x65,0x76,0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x4C,0x69, - 0x73,0x74,0x3F,0x62,0x61,0x73,0x65,0x3F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x39,0xC8,0xC4,0x9B, - 0xEE,0xBE,0x98,0xEE,0x48,0x72,0x6F,0x8D,0xE7,0x71,0xB6,0x0E,0x90,0x8C,0xD3,0xB2, - 0xC1,0x15,0x21,0xA8,0x46,0x90,0x68,0x5F,0x4A,0x04,0xF1,0x3A,0xC9,0x68,0x84,0x21, - 0xD8,0xA5,0xE6,0x04,0x75,0x5D,0x9F,0xD2,0xD4,0xF2,0x4B,0x77,0x43,0x32,0xDC,0x95, - 0xCB,0x60,0xBF,0x02,0x55,0xD0,0xAC,0x1C,0xB0,0xC5,0x14,0x97,0x9B,0x65,0x0A,0xC3, - 0x0F,0xA5,0x1D,0xEC,0xD8,0x49,0x39,0x95,0xB5,0xA9,0xBE,0xFA,0xF4,0x1E,0xAB,0x56, - 0xE7,0xA6,0xE5,0x01,0x08,0x88,0x35,0x5F,0x67,0x05,0xDD,0x44,0x24,0x50,0x12,0x22, - 0x44,0x63,0x79,0xF1,0x9B,0x57,0x69,0xCE,0xAB,0xD6,0x33,0x51,0x4F,0x8D,0xF0,0x70, - 0x3B,0x8E,0xAD,0x51,0x3A,0x17,0x7F,0x35,0x96,0x6B,0x68,0x68,0x63,0xB6,0x1C,0x0A, - 0xC9,0xF8,0xDF,0x1D,0x5E,0xCF,0x2B,0x11,0xA5,0x63,0xED,0xCC,0xD0,0xC6,0xD3,0x20, - 0x6F,0xAA,0xFC,0x68,0x48,0x7E,0x6D,0x1E,0xB8,0x3A,0x45,0xAA,0x12,0x86,0xF3,0xC7, - 0xBD,0x00,0xB5,0xEB,0xFE,0xEA,0x12,0x9F,0x73,0x33,0x78,0xE7,0x28,0x39,0x68,0xD3, - 0xA5,0x6D,0xDA,0x76,0xD1,0x4E,0xE1,0x55,0x95,0x80,0xA6,0xE0,0x1B,0xB8,0xCD,0xAC, - 0x56,0xEF,0x45,0x59,0x47,0x98,0x52,0xDB,0x3A,0x6E,0x26,0xB2,0x31,0x39,0x69,0x75, - 0xB1,0x2E,0x24,0xF0,0xA4,0x9D,0x97,0x88,0x5E,0x33,0x29,0xC6,0xB5,0xBC,0x07,0x40, - 0x3A,0x0C,0x3D,0xBA,0xCF,0x74,0x8C,0x4B,0x4E,0x7A,0x21,0xFA,0x1B,0x38,0xCD,0xC4, - 0x43,0x2F,0x6F,0xB4,0xDF,0x78,0xEE,0x99,0x92,0xE7,0x3A,0x1C, -}; - -unsigned char ocsp_smime_root_certificate[993]={ - 0x30,0x82,0x03,0xDD,0x30,0x82,0x02,0xC5,0xA0,0x03,0x02,0x01,0x02,0x02,0x0E,0x1D, - 0xA2,0x00,0x01,0x00,0x02,0xEC,0xB7,0x60,0x80,0x78,0x8D,0xB6,0x06,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x79,0x31,0x0B, - 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06, - 0x03,0x55,0x04,0x0A,0x13,0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65, - 0x6E,0x74,0x65,0x72,0x20,0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55, - 0x04,0x0B,0x13,0x1B,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74, - 0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31, - 0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75, - 0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73, - 0x61,0x6C,0x20,0x43,0x41,0x20,0x49,0x30,0x1E,0x17,0x0D,0x30,0x36,0x30,0x33,0x32, - 0x32,0x31,0x35,0x35,0x34,0x32,0x38,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x33,0x31, - 0x32,0x32,0x35,0x39,0x35,0x39,0x5A,0x30,0x79,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, - 0x04,0x06,0x13,0x02,0x44,0x45,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0A,0x13, - 0x13,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20, - 0x47,0x6D,0x62,0x48,0x31,0x24,0x30,0x22,0x06,0x03,0x55,0x04,0x0B,0x13,0x1B,0x54, - 0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E,0x74,0x65,0x72,0x20,0x55,0x6E, - 0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41,0x31,0x26,0x30,0x24,0x06,0x03, - 0x55,0x04,0x03,0x13,0x1D,0x54,0x43,0x20,0x54,0x72,0x75,0x73,0x74,0x43,0x65,0x6E, - 0x74,0x65,0x72,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x43,0x41, - 0x20,0x49,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,0xA4,0x77,0x23,0x96,0x44,0xAF,0x90,0xF4,0x31,0xA7,0x10,0xF4,0x26, - 0x87,0x9C,0xF3,0x38,0xD9,0x0F,0x5E,0xDE,0xCF,0x41,0xE8,0x31,0xAD,0xC6,0x74,0x91, - 0x24,0x96,0x78,0x1E,0x09,0xA0,0x9B,0x9A,0x95,0x4A,0x4A,0xF5,0x62,0x7C,0x02,0xA8, - 0xCA,0xAC,0xFB,0x5A,0x04,0x76,0x39,0xDE,0x5F,0xF1,0xF9,0xB3,0xBF,0xF3,0x03,0x58, - 0x55,0xD2,0xAA,0xB7,0xE3,0x04,0x22,0xD1,0xF8,0x94,0xDA,0x22,0x08,0x00,0x8D,0xD3, - 0x7C,0x26,0x5D,0xCC,0x77,0x79,0xE7,0x2C,0x78,0x39,0xA8,0x26,0x73,0x0E,0xA2,0x5D, - 0x25,0x69,0x85,0x4F,0x55,0x0E,0x9A,0xEF,0xC6,0xB9,0x44,0xE1,0x57,0x3D,0xDF,0x1F, - 0x54,0x22,0xE5,0x6F,0x65,0xAA,0x33,0x84,0x3A,0xF3,0xCE,0x7A,0xBE,0x55,0x97,0xAE, - 0x8D,0x12,0x0F,0x14,0x33,0xE2,0x50,0x70,0xC3,0x49,0x87,0x13,0xBC,0x51,0xDE,0xD7, - 0x98,0x12,0x5A,0xEF,0x3A,0x83,0x33,0x92,0x06,0x75,0x8B,0x92,0x7C,0x12,0x68,0x7B, - 0x70,0x6A,0x0F,0xB5,0x9B,0xB6,0x77,0x5B,0x48,0x59,0x9D,0xE4,0xEF,0x5A,0xAD,0xF3, - 0xC1,0x9E,0xD4,0xD7,0x45,0x4E,0xCA,0x56,0x34,0x21,0xBC,0x3E,0x17,0x5B,0x6F,0x77, - 0x0C,0x48,0x01,0x43,0x29,0xB0,0xDD,0x3F,0x96,0x6E,0xE6,0x95,0xAA,0x0C,0xC0,0x20, - 0xB6,0xFD,0x3E,0x36,0x27,0x9C,0xE3,0x5C,0xCF,0x4E,0x81,0xDC,0x19,0xBB,0x91,0x90, - 0x7D,0xEC,0xE6,0x97,0x04,0x1E,0x93,0xCC,0x22,0x49,0xD7,0x97,0x86,0xB6,0x13,0x0A, - 0x3C,0x43,0x23,0x77,0x7E,0xF0,0xDC,0xE6,0xCD,0x24,0x1F,0x3B,0x83,0x9B,0x34,0x3A, - 0x83,0x34,0xE3,0x02,0x03,0x01,0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x1F,0x06,0x03, - 0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x92,0xA4,0x75,0x2C,0xA4,0x9E,0xBE, - 0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75,0x73,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,0x86,0x30,0x1D, - 0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x92,0xA4,0x75,0x2C,0xA4,0x9E,0xBE, - 0x81,0x44,0xEB,0x79,0xFC,0x8A,0xC5,0x95,0xA5,0xEB,0x10,0x75,0x73,0x30,0x0D,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01, - 0x00,0x28,0xD2,0xE0,0x86,0xD5,0xE6,0xF8,0x7B,0xF0,0x97,0xDC,0x22,0x6B,0x3B,0x95, - 0x14,0x56,0x0F,0x11,0x30,0xA5,0x9A,0x4F,0x3A,0xB0,0x3A,0xE0,0x06,0xCB,0x65,0xF5, - 0xED,0xC6,0x97,0x27,0xFE,0x25,0xF2,0x57,0xE6,0x5E,0x95,0x8C,0x3E,0x64,0x60,0x15, - 0x5A,0x7F,0x2F,0x0D,0x01,0xC5,0xB1,0x60,0xFD,0x45,0x35,0xCF,0xF0,0xB2,0xBF,0x06, - 0xD9,0xEF,0x5A,0xBE,0xB3,0x62,0x21,0xB4,0xD7,0xAB,0x35,0x7C,0x53,0x3E,0xA6,0x27, - 0xF1,0xA1,0x2D,0xDA,0x1A,0x23,0x9D,0xCC,0xDD,0xEC,0x3C,0x2D,0x9E,0x27,0x34,0x5D, - 0x0F,0xC2,0x36,0x79,0xBC,0xC9,0x4A,0x62,0x2D,0xED,0x6B,0xD9,0x7D,0x41,0x43,0x7C, - 0xB6,0xAA,0xCA,0xED,0x61,0xB1,0x37,0x82,0x15,0x09,0x1A,0x8A,0x16,0x30,0xD8,0xEC, - 0xC9,0xD6,0x47,0x72,0x78,0x4B,0x10,0x46,0x14,0x8E,0x5F,0x0E,0xAF,0xEC,0xC7,0x2F, - 0xAB,0x10,0xD7,0xB6,0xF1,0x6E,0xEC,0x86,0xB2,0xC2,0xE8,0x0D,0x92,0x73,0xDC,0xA2, - 0xF4,0x0F,0x3A,0xBF,0x61,0x23,0x10,0x89,0x9C,0x48,0x40,0x6E,0x70,0x00,0xB3,0xD3, - 0xBA,0x37,0x44,0x58,0x11,0x7A,0x02,0x6A,0x88,0xF0,0x37,0x34,0xF0,0x19,0xE9,0xAC, - 0xD4,0x65,0x73,0xF6,0x69,0x8C,0x64,0x94,0x3A,0x79,0x85,0x29,0xB0,0x16,0x2B,0x0C, - 0x82,0x3F,0x06,0x9C,0xC7,0xFD,0x10,0x2B,0x9E,0x0F,0x2C,0xB6,0x9E,0xE3,0x15,0xBF, - 0xD9,0x36,0x1C,0xBA,0x25,0x1A,0x52,0x3D,0x1A,0xEC,0x22,0x0C,0x1C,0xE0,0xA4,0xA2, - 0x3D,0xF0,0xE8,0x39,0xCF,0x81,0xC0,0x7B,0xED,0x5D,0x1F,0x6F,0xC5,0xD0,0x0B,0xD7, - 0x98, -}; - -/* subject:/C=US/ST=California/L=Walnut Creek/O=Lucas Garron/CN=revoked.badssl.com */ -/* issuer :/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA */ -uint8_t _probablyRevokedLeaf[]={ - 0x30,0x82,0x06,0xA1,0x30,0x82,0x05,0x89,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x01, - 0xAF,0x1E,0xFB,0xDD,0x5E,0xAE,0x09,0x52,0x32,0x0B,0x24,0xFE,0x6B,0x55,0x68,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x4D, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x03,0x13,0x1E,0x44, - 0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x20,0x53,0x48,0x41,0x32,0x20,0x53,0x65,0x63, - 0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,0x30,0x1E,0x17, - 0x0D,0x31,0x36,0x30,0x39,0x30,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D, - 0x31,0x39,0x30,0x39,0x31,0x31,0x31,0x32,0x30,0x30,0x30,0x30,0x5A,0x30,0x6D,0x31, - 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, - 0x06,0x03,0x55,0x04,0x08,0x13,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69, - 0x61,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x07,0x13,0x0C,0x57,0x61,0x6C,0x6E, - 0x75,0x74,0x20,0x43,0x72,0x65,0x65,0x6B,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04, - 0x0A,0x13,0x0C,0x4C,0x75,0x63,0x61,0x73,0x20,0x47,0x61,0x72,0x72,0x6F,0x6E,0x31, - 0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x13,0x12,0x72,0x65,0x76,0x6F,0x6B,0x65, - 0x64,0x2E,0x62,0x61,0x64,0x73,0x73,0x6C,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,0xC7,0x31,0x65, - 0xE4,0x55,0xCF,0x69,0x90,0x9F,0x6E,0x1F,0xD8,0x6A,0x13,0x7E,0x74,0xBF,0x13,0x3A, - 0x54,0x64,0x0F,0x74,0x24,0x3D,0xDC,0x60,0xB8,0xA7,0x45,0x01,0xB7,0xC8,0x6A,0x03, - 0xAC,0x64,0x4A,0x65,0xF0,0x7C,0x81,0x81,0x83,0x0A,0xD9,0xDD,0x31,0x20,0x82,0x48, - 0xA6,0x33,0x63,0xEE,0x2B,0x74,0xEA,0xB4,0xE6,0xC7,0x1C,0xB2,0x5E,0xE4,0x28,0x3A, - 0x7A,0x3D,0x20,0x19,0x03,0xB7,0x15,0x3F,0x4F,0xC9,0x26,0xEC,0xB7,0xCB,0xBF,0x48, - 0x6E,0x5F,0x34,0x70,0x56,0xC4,0x86,0xC7,0xE3,0x52,0x9A,0x21,0x33,0x2F,0x10,0x13, - 0xF3,0x25,0x0C,0x1E,0x94,0x35,0x2E,0xE8,0xD0,0xD1,0xB5,0xA0,0x77,0x40,0x91,0x2E, - 0xE9,0xBA,0xF8,0xFF,0x4E,0xF5,0xFB,0xF2,0x7A,0x04,0xA7,0xE6,0xC6,0xCE,0x3F,0x0F, - 0x10,0x18,0x32,0xC8,0x06,0xBC,0x15,0xB3,0xBE,0x69,0xAC,0x75,0x7D,0x42,0xA0,0x8C, - 0x2E,0xC3,0xAC,0xE1,0x20,0x4F,0x1E,0x36,0x9C,0x9A,0x2E,0xA2,0xFD,0x79,0x80,0xB6, - 0x62,0xF8,0xC0,0xB2,0x03,0xA9,0x29,0x50,0xCC,0xD5,0x25,0x8A,0x33,0x5E,0xE0,0x78, - 0x13,0x18,0xC0,0x80,0x17,0x09,0x95,0xBD,0xA2,0xFE,0x92,0x15,0x07,0x20,0x7A,0x81, - 0xCE,0xDB,0x0E,0x81,0x29,0x89,0xD4,0xC8,0xEC,0xB3,0xB3,0x79,0x0E,0xF2,0xCE,0x25, - 0xE7,0xEE,0xBE,0x21,0x7D,0xAF,0x0C,0x13,0x94,0x29,0xDE,0x35,0x9A,0x1E,0xD8,0x84, - 0x18,0x5A,0x5C,0x1A,0x94,0x82,0xCE,0x9A,0x61,0xD6,0x9D,0xEC,0xF8,0xEE,0xAD,0x3F, - 0x09,0x5B,0x73,0xEC,0xA2,0x9B,0xFA,0xDC,0x62,0xF1,0x58,0x1F,0x7D,0x02,0x03,0x01, - 0x00,0x01,0xA3,0x82,0x03,0x5B,0x30,0x82,0x03,0x57,0x30,0x1F,0x06,0x03,0x55,0x1D, - 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x0F,0x80,0x61,0x1C,0x82,0x31,0x61,0xD5,0x2F, - 0x28,0xE7,0x8D,0x46,0x38,0xB4,0x2C,0xE1,0xC6,0xD9,0xE2,0x30,0x1D,0x06,0x03,0x55, - 0x1D,0x0E,0x04,0x16,0x04,0x14,0xF4,0x48,0x7D,0x07,0x45,0x1A,0x32,0x07,0x90,0x91, - 0xAC,0x05,0xB8,0x9F,0xA9,0x11,0xF0,0x7E,0x11,0x36,0x30,0x1D,0x06,0x03,0x55,0x1D, - 0x11,0x04,0x16,0x30,0x14,0x82,0x12,0x72,0x65,0x76,0x6F,0x6B,0x65,0x64,0x2E,0x62, - 0x61,0x64,0x73,0x73,0x6C,0x2E,0x63,0x6F,0x6D,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, - 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25, - 0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x6B,0x06,0x03,0x55,0x1D,0x1F,0x04, - 0x64,0x30,0x62,0x30,0x2F,0xA0,0x2D,0xA0,0x2B,0x86,0x29,0x68,0x74,0x74,0x70,0x3A, - 0x2F,0x2F,0x63,0x72,0x6C,0x33,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E, - 0x63,0x6F,0x6D,0x2F,0x73,0x73,0x63,0x61,0x2D,0x73,0x68,0x61,0x32,0x2D,0x67,0x35, - 0x2E,0x63,0x72,0x6C,0x30,0x2F,0xA0,0x2D,0xA0,0x2B,0x86,0x29,0x68,0x74,0x74,0x70, - 0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x34,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74, - 0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x73,0x63,0x61,0x2D,0x73,0x68,0x61,0x32,0x2D,0x67, - 0x35,0x2E,0x63,0x72,0x6C,0x30,0x4C,0x06,0x03,0x55,0x1D,0x20,0x04,0x45,0x30,0x43, - 0x30,0x37,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xFD,0x6C,0x01,0x01,0x30,0x2A,0x30, - 0x28,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74, - 0x70,0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72, - 0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x08,0x06,0x06,0x67,0x81,0x0C, - 0x01,0x02,0x03,0x30,0x7C,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04, - 0x70,0x30,0x6E,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86, - 0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69,0x67, - 0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x46,0x06,0x08,0x2B,0x06,0x01, - 0x05,0x05,0x07,0x30,0x02,0x86,0x3A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x61, - 0x63,0x65,0x72,0x74,0x73,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63, - 0x6F,0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x53,0x48,0x41,0x32,0x53, - 0x65,0x63,0x75,0x72,0x65,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72, - 0x74,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, - 0x82,0x01,0x7E,0x06,0x0A,0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02,0x04, - 0x82,0x01,0x6E,0x04,0x82,0x01,0x6A,0x01,0x68,0x00,0x75,0x00,0xA4,0xB9,0x09,0x90, - 0xB4,0x18,0x58,0x14,0x87,0xBB,0x13,0xA2,0xCC,0x67,0x70,0x0A,0x3C,0x35,0x98,0x04, - 0xF9,0x1B,0xDF,0xB8,0xE3,0x77,0xCD,0x0E,0xC8,0x0D,0xDC,0x10,0x00,0x00,0x01,0x56, - 0xEC,0xA1,0x37,0xDA,0x00,0x00,0x04,0x03,0x00,0x46,0x30,0x44,0x02,0x20,0x3F,0x6C, - 0xA8,0xF5,0xC4,0x7C,0x01,0x4C,0xC3,0x5A,0x28,0x27,0x50,0x47,0x63,0xD9,0xAC,0xE1, - 0xBE,0x2D,0xBF,0x87,0x78,0xCB,0x3A,0x80,0x97,0x24,0x74,0xCD,0x16,0xF7,0x02,0x20, - 0x71,0xFF,0x93,0xA2,0xB5,0x54,0x7E,0x7F,0x53,0x45,0x7F,0x59,0x5A,0x60,0x18,0x21, - 0x5C,0xAB,0x7D,0x1F,0x08,0xB2,0x54,0xA0,0xB3,0xC4,0x88,0xA5,0x83,0xD2,0x63,0x55, - 0x00,0x77,0x00,0x68,0xF6,0x98,0xF8,0x1F,0x64,0x82,0xBE,0x3A,0x8C,0xEE,0xB9,0x28, - 0x1D,0x4C,0xFC,0x71,0x51,0x5D,0x67,0x93,0xD4,0x44,0xD1,0x0A,0x67,0xAC,0xBB,0x4F, - 0x4F,0xFB,0xC4,0x00,0x00,0x01,0x56,0xEC,0xA1,0x37,0xA1,0x00,0x00,0x04,0x03,0x00, - 0x48,0x30,0x46,0x02,0x21,0x00,0xFE,0x59,0x97,0x22,0x4C,0x6C,0x0F,0x39,0x05,0xD9, - 0xE4,0xCA,0x7E,0x3B,0xD3,0xB3,0x47,0x1B,0x61,0x72,0xB6,0x3A,0x4F,0xD6,0xF2,0xA3, - 0x57,0x49,0x48,0x4F,0x6A,0x6D,0x02,0x21,0x00,0x8F,0x14,0x1B,0x3C,0x1B,0x89,0xA3, - 0x1D,0x70,0xEC,0xD4,0xD7,0x11,0xBC,0xF9,0x0B,0x3C,0x60,0xAC,0x8C,0x84,0x73,0x24, - 0x6B,0x0E,0x37,0x6E,0x53,0x7F,0x9D,0x7F,0x34,0x00,0x76,0x00,0x56,0x14,0x06,0x9A, - 0x2F,0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC, - 0x99,0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x56, - 0xEC,0xA1,0x38,0x7F,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x0E,0xBF, - 0x53,0x59,0x17,0x0C,0xEC,0x66,0x0C,0x5E,0x87,0xBB,0x8F,0x5F,0xB6,0x76,0x86,0xF2, - 0x5C,0xFC,0xBC,0xA8,0xB9,0xC0,0xDF,0xBC,0x1A,0x3B,0xEE,0x11,0xF2,0xD0,0x02,0x21, - 0x00,0x87,0x25,0x39,0xE4,0x32,0x99,0x48,0xCA,0x20,0x1B,0x13,0x96,0x1D,0xC3,0x2C, - 0x98,0x6B,0x1B,0xC0,0xCC,0xE5,0x67,0x22,0xBD,0x92,0x14,0xE9,0x68,0xCD,0x95,0x82, - 0x32,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, - 0x03,0x82,0x01,0x01,0x00,0x5A,0xA0,0x49,0x88,0xAD,0x60,0x1F,0x08,0x53,0x4C,0xD9, - 0xB8,0xDC,0xF5,0x40,0x41,0xAD,0xEF,0xC8,0x7B,0x01,0x3B,0x13,0x70,0x44,0x99,0xF6, - 0x5C,0x23,0x46,0xF7,0x3A,0xC8,0x7D,0xC9,0x21,0xAD,0x3A,0x49,0x45,0x82,0x1E,0x5D, - 0x3B,0x1E,0x9B,0x6A,0x0A,0x3E,0x61,0x2D,0xF6,0xB1,0x99,0x74,0x2F,0x91,0xF9,0xD5, - 0xF1,0x9F,0xAE,0x74,0x26,0x8B,0x3C,0xA7,0x8C,0xBE,0x28,0xFE,0xAC,0x3B,0x70,0xAE, - 0x08,0x56,0x71,0xAC,0x55,0x7C,0x40,0x89,0x02,0x2D,0x61,0x2A,0xFD,0x54,0x72,0xBF, - 0x1A,0x5C,0x70,0x19,0x90,0x15,0xA4,0x76,0xA0,0x7F,0x56,0x1C,0xC1,0xF0,0x8D,0x5E, - 0x99,0x3D,0x83,0x41,0x54,0x68,0xE5,0x62,0xC1,0x5A,0xA2,0x64,0x8C,0x01,0x64,0x7A, - 0x23,0xB9,0x3F,0xBF,0x22,0xCF,0x1F,0xC0,0x47,0x80,0x1F,0x94,0xD5,0xF2,0x30,0x84, - 0xFB,0x07,0x02,0xFA,0x5B,0xA0,0xBA,0x09,0x04,0x98,0x4E,0xF3,0x25,0x56,0x4C,0xC4, - 0x7E,0xE0,0x27,0xD8,0xE8,0x32,0x8F,0xB3,0x3C,0x5A,0x92,0x4B,0xC0,0x77,0x2D,0xB0, - 0xE5,0xAE,0x1F,0xAF,0x1D,0x7F,0x21,0x9C,0x65,0x26,0xBE,0x0C,0xBA,0xE8,0x0D,0xC1, - 0xD2,0x67,0xB4,0xB9,0x33,0xD1,0x4A,0xEE,0xFC,0xB8,0xAF,0x03,0x5B,0xC8,0x3E,0xBC, - 0xFA,0x09,0x9D,0x04,0xCE,0x3E,0xA6,0xB5,0xC4,0x74,0x3B,0x31,0x7A,0xF3,0x2C,0x42, - 0xB3,0xC7,0x73,0xDB,0xAA,0x75,0x2E,0x8D,0x8A,0x9E,0x79,0x33,0xBE,0xD7,0xB6,0x14, - 0x9B,0x26,0xAB,0x7B,0x9E,0x14,0xB3,0x55,0xE6,0x4B,0xBB,0x86,0x94,0x11,0x74,0x02, - 0x35,0xB4,0x52,0x70,0x9B, -}; - -/* subject:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA */ -uint8_t _digiCertSha2SubCA[] ={ - 0x30,0x82,0x04,0x94,0x30,0x82,0x03,0x7C,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x01, - 0xFD,0xA3,0xEB,0x6E,0xCA,0x75,0xC8,0x88,0x43,0x8B,0x72,0x4B,0xCF,0xBC,0x91,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x61, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x13,0x17,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, - 0x41,0x30,0x1E,0x17,0x0D,0x31,0x33,0x30,0x33,0x30,0x38,0x31,0x32,0x30,0x30,0x30, - 0x30,0x5A,0x17,0x0D,0x32,0x33,0x30,0x33,0x30,0x38,0x31,0x32,0x30,0x30,0x30,0x30, - 0x5A,0x30,0x4D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, - 0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43, - 0x65,0x72,0x74,0x20,0x49,0x6E,0x63,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x03, - 0x13,0x1E,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x20,0x53,0x48,0x41,0x32,0x20, - 0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41, - 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,0xDC,0xAE,0x58,0x90,0x4D,0xC1,0xC4,0x30,0x15,0x90,0x35,0x5B,0x6E,0x3C,0x82, - 0x15,0xF5,0x2C,0x5C,0xBD,0xE3,0xDB,0xFF,0x71,0x43,0xFA,0x64,0x25,0x80,0xD4,0xEE, - 0x18,0xA2,0x4D,0xF0,0x66,0xD0,0x0A,0x73,0x6E,0x11,0x98,0x36,0x17,0x64,0xAF,0x37, - 0x9D,0xFD,0xFA,0x41,0x84,0xAF,0xC7,0xAF,0x8C,0xFE,0x1A,0x73,0x4D,0xCF,0x33,0x97, - 0x90,0xA2,0x96,0x87,0x53,0x83,0x2B,0xB9,0xA6,0x75,0x48,0x2D,0x1D,0x56,0x37,0x7B, - 0xDA,0x31,0x32,0x1A,0xD7,0xAC,0xAB,0x06,0xF4,0xAA,0x5D,0x4B,0xB7,0x47,0x46,0xDD, - 0x2A,0x93,0xC3,0x90,0x2E,0x79,0x80,0x80,0xEF,0x13,0x04,0x6A,0x14,0x3B,0xB5,0x9B, - 0x92,0xBE,0xC2,0x07,0x65,0x4E,0xFC,0xDA,0xFC,0xFF,0x7A,0xAE,0xDC,0x5C,0x7E,0x55, - 0x31,0x0C,0xE8,0x39,0x07,0xA4,0xD7,0xBE,0x2F,0xD3,0x0B,0x6A,0xD2,0xB1,0xDF,0x5F, - 0xFE,0x57,0x74,0x53,0x3B,0x35,0x80,0xDD,0xAE,0x8E,0x44,0x98,0xB3,0x9F,0x0E,0xD3, - 0xDA,0xE0,0xD7,0xF4,0x6B,0x29,0xAB,0x44,0xA7,0x4B,0x58,0x84,0x6D,0x92,0x4B,0x81, - 0xC3,0xDA,0x73,0x8B,0x12,0x97,0x48,0x90,0x04,0x45,0x75,0x1A,0xDD,0x37,0x31,0x97, - 0x92,0xE8,0xCD,0x54,0x0D,0x3B,0xE4,0xC1,0x3F,0x39,0x5E,0x2E,0xB8,0xF3,0x5C,0x7E, - 0x10,0x8E,0x86,0x41,0x00,0x8D,0x45,0x66,0x47,0xB0,0xA1,0x65,0xCE,0xA0,0xAA,0x29, - 0x09,0x4E,0xF3,0x97,0xEB,0xE8,0x2E,0xAB,0x0F,0x72,0xA7,0x30,0x0E,0xFA,0xC7,0xF4, - 0xFD,0x14,0x77,0xC3,0xA4,0x5B,0x28,0x57,0xC2,0xB3,0xF9,0x82,0xFD,0xB7,0x45,0x58, - 0x9B,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x5A,0x30,0x82,0x01,0x56,0x30,0x12, - 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02, - 0x01,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02, - 0x01,0x86,0x30,0x34,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28, - 0x30,0x26,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x64,0x69,0x67,0x69, - 0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x30,0x7B,0x06,0x03,0x55,0x1D,0x1F,0x04, - 0x74,0x30,0x72,0x30,0x37,0xA0,0x35,0xA0,0x33,0x86,0x31,0x68,0x74,0x74,0x70,0x3A, - 0x2F,0x2F,0x63,0x72,0x6C,0x33,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E, - 0x63,0x6F,0x6D,0x2F,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74,0x47,0x6C,0x6F,0x62, - 0x61,0x6C,0x52,0x6F,0x6F,0x74,0x43,0x41,0x2E,0x63,0x72,0x6C,0x30,0x37,0xA0,0x35, - 0xA0,0x33,0x86,0x31,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x34,0x2E, - 0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x44,0x69,0x67, - 0x69,0x43,0x65,0x72,0x74,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x52,0x6F,0x6F,0x74,0x43, - 0x41,0x2E,0x63,0x72,0x6C,0x30,0x3D,0x06,0x03,0x55,0x1D,0x20,0x04,0x36,0x30,0x34, - 0x30,0x32,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x2A,0x30,0x28,0x06,0x08,0x2B,0x06, - 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F, - 0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D, - 0x2F,0x43,0x50,0x53,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x0F, - 0x80,0x61,0x1C,0x82,0x31,0x61,0xD5,0x2F,0x28,0xE7,0x8D,0x46,0x38,0xB4,0x2C,0xE1, - 0xC6,0xD9,0xE2,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, - 0x03,0xDE,0x50,0x35,0x56,0xD1,0x4C,0xBB,0x66,0xF0,0xA3,0xE2,0x1B,0x1B,0xC3,0x97, - 0xB2,0x3D,0xD1,0x55,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, - 0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x23,0x3E,0xDF,0x4B,0xD2,0x31,0x42,0xA5, - 0xB6,0x7E,0x42,0x5C,0x1A,0x44,0xCC,0x69,0xD1,0x68,0xB4,0x5D,0x4B,0xE0,0x04,0x21, - 0x6C,0x4B,0xE2,0x6D,0xCC,0xB1,0xE0,0x97,0x8F,0xA6,0x53,0x09,0xCD,0xAA,0x2A,0x65, - 0xE5,0x39,0x4F,0x1E,0x83,0xA5,0x6E,0x5C,0x98,0xA2,0x24,0x26,0xE6,0xFB,0xA1,0xED, - 0x93,0xC7,0x2E,0x02,0xC6,0x4D,0x4A,0xBF,0xB0,0x42,0xDF,0x78,0xDA,0xB3,0xA8,0xF9, - 0x6D,0xFF,0x21,0x85,0x53,0x36,0x60,0x4C,0x76,0xCE,0xEC,0x38,0xDC,0xD6,0x51,0x80, - 0xF0,0xC5,0xD6,0xE5,0xD4,0x4D,0x27,0x64,0xAB,0x9B,0xC7,0x3E,0x71,0xFB,0x48,0x97, - 0xB8,0x33,0x6D,0xC9,0x13,0x07,0xEE,0x96,0xA2,0x1B,0x18,0x15,0xF6,0x5C,0x4C,0x40, - 0xED,0xB3,0xC2,0xEC,0xFF,0x71,0xC1,0xE3,0x47,0xFF,0xD4,0xB9,0x00,0xB4,0x37,0x42, - 0xDA,0x20,0xC9,0xEA,0x6E,0x8A,0xEE,0x14,0x06,0xAE,0x7D,0xA2,0x59,0x98,0x88,0xA8, - 0x1B,0x6F,0x2D,0xF4,0xF2,0xC9,0x14,0x5F,0x26,0xCF,0x2C,0x8D,0x7E,0xED,0x37,0xC0, - 0xA9,0xD5,0x39,0xB9,0x82,0xBF,0x19,0x0C,0xEA,0x34,0xAF,0x00,0x21,0x68,0xF8,0xAD, - 0x73,0xE2,0xC9,0x32,0xDA,0x38,0x25,0x0B,0x55,0xD3,0x9A,0x1D,0xF0,0x68,0x86,0xED, - 0x2E,0x41,0x34,0xEF,0x7C,0xA5,0x50,0x1D,0xBF,0x3A,0xF9,0xD3,0xC1,0x08,0x0C,0xE6, - 0xED,0x1E,0x8A,0x58,0x25,0xE4,0xB8,0x77,0xAD,0x2D,0x6E,0xF5,0x52,0xDD,0xB4,0x74, - 0x8F,0xAB,0x49,0x2E,0x9D,0x3B,0x93,0x34,0x28,0x1F,0x78,0xCE,0x94,0xEA,0xC7,0xBD, - 0xD3,0xC9,0x6D,0x1C,0xDE,0x5C,0x32,0xF3, -}; - -/* subject:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA */ -/* issuer :/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA */ -uint8_t _digiCertGlobalRoot[] ={ - 0x30,0x82,0x03,0xAF,0x30,0x82,0x02,0x97,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x08, - 0x3B,0xE0,0x56,0x90,0x42,0x46,0xB1,0xA1,0x75,0x6A,0xC9,0x59,0x91,0xC7,0x4A,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x61, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x15,0x30, - 0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43,0x65,0x72,0x74, - 0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x13,0x10,0x77, - 0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x31, - 0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x13,0x17,0x44,0x69,0x67,0x69,0x43,0x65, - 0x72,0x74,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, - 0x41,0x30,0x1E,0x17,0x0D,0x30,0x36,0x31,0x31,0x31,0x30,0x30,0x30,0x30,0x30,0x30, - 0x30,0x5A,0x17,0x0D,0x33,0x31,0x31,0x31,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30, - 0x5A,0x30,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, - 0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x0A,0x13,0x0C,0x44,0x69,0x67,0x69,0x43, - 0x65,0x72,0x74,0x20,0x49,0x6E,0x63,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B, - 0x13,0x10,0x77,0x77,0x77,0x2E,0x64,0x69,0x67,0x69,0x63,0x65,0x72,0x74,0x2E,0x63, - 0x6F,0x6D,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x13,0x17,0x44,0x69,0x67, - 0x69,0x43,0x65,0x72,0x74,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x52,0x6F,0x6F, - 0x74,0x20,0x43,0x41,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,0x3B,0xE1,0x11,0x72,0xDE,0xA8,0xA4,0xD3,0xA3,0x57, - 0xAA,0x50,0xA2,0x8F,0x0B,0x77,0x90,0xC9,0xA2,0xA5,0xEE,0x12,0xCE,0x96,0x5B,0x01, - 0x09,0x20,0xCC,0x01,0x93,0xA7,0x4E,0x30,0xB7,0x53,0xF7,0x43,0xC4,0x69,0x00,0x57, - 0x9D,0xE2,0x8D,0x22,0xDD,0x87,0x06,0x40,0x00,0x81,0x09,0xCE,0xCE,0x1B,0x83,0xBF, - 0xDF,0xCD,0x3B,0x71,0x46,0xE2,0xD6,0x66,0xC7,0x05,0xB3,0x76,0x27,0x16,0x8F,0x7B, - 0x9E,0x1E,0x95,0x7D,0xEE,0xB7,0x48,0xA3,0x08,0xDA,0xD6,0xAF,0x7A,0x0C,0x39,0x06, - 0x65,0x7F,0x4A,0x5D,0x1F,0xBC,0x17,0xF8,0xAB,0xBE,0xEE,0x28,0xD7,0x74,0x7F,0x7A, - 0x78,0x99,0x59,0x85,0x68,0x6E,0x5C,0x23,0x32,0x4B,0xBF,0x4E,0xC0,0xE8,0x5A,0x6D, - 0xE3,0x70,0xBF,0x77,0x10,0xBF,0xFC,0x01,0xF6,0x85,0xD9,0xA8,0x44,0x10,0x58,0x32, - 0xA9,0x75,0x18,0xD5,0xD1,0xA2,0xBE,0x47,0xE2,0x27,0x6A,0xF4,0x9A,0x33,0xF8,0x49, - 0x08,0x60,0x8B,0xD4,0x5F,0xB4,0x3A,0x84,0xBF,0xA1,0xAA,0x4A,0x4C,0x7D,0x3E,0xCF, - 0x4F,0x5F,0x6C,0x76,0x5E,0xA0,0x4B,0x37,0x91,0x9E,0xDC,0x22,0xE6,0x6D,0xCE,0x14, - 0x1A,0x8E,0x6A,0xCB,0xFE,0xCD,0xB3,0x14,0x64,0x17,0xC7,0x5B,0x29,0x9E,0x32,0xBF, - 0xF2,0xEE,0xFA,0xD3,0x0B,0x42,0xD4,0xAB,0xB7,0x41,0x32,0xDA,0x0C,0xD4,0xEF,0xF8, - 0x81,0xD5,0xBB,0x8D,0x58,0x3F,0xB5,0x1B,0xE8,0x49,0x28,0xA2,0x70,0xDA,0x31,0x04, - 0xDD,0xF7,0xB2,0x16,0xF2,0x4C,0x0A,0x4E,0x07,0xA8,0xED,0x4A,0x3D,0x5E,0xB5,0x7F, - 0xA3,0x90,0xC3,0xAF,0x27,0x02,0x03,0x01,0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x0E, - 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x0F, - 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30, - 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x03,0xDE,0x50,0x35,0x56,0xD1, - 0x4C,0xBB,0x66,0xF0,0xA3,0xE2,0x1B,0x1B,0xC3,0x97,0xB2,0x3D,0xD1,0x55,0x30,0x1F, - 0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x03,0xDE,0x50,0x35,0x56, - 0xD1,0x4C,0xBB,0x66,0xF0,0xA3,0xE2,0x1B,0x1B,0xC3,0x97,0xB2,0x3D,0xD1,0x55,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82, - 0x01,0x01,0x00,0xCB,0x9C,0x37,0xAA,0x48,0x13,0x12,0x0A,0xFA,0xDD,0x44,0x9C,0x4F, - 0x52,0xB0,0xF4,0xDF,0xAE,0x04,0xF5,0x79,0x79,0x08,0xA3,0x24,0x18,0xFC,0x4B,0x2B, - 0x84,0xC0,0x2D,0xB9,0xD5,0xC7,0xFE,0xF4,0xC1,0x1F,0x58,0xCB,0xB8,0x6D,0x9C,0x7A, - 0x74,0xE7,0x98,0x29,0xAB,0x11,0xB5,0xE3,0x70,0xA0,0xA1,0xCD,0x4C,0x88,0x99,0x93, - 0x8C,0x91,0x70,0xE2,0xAB,0x0F,0x1C,0xBE,0x93,0xA9,0xFF,0x63,0xD5,0xE4,0x07,0x60, - 0xD3,0xA3,0xBF,0x9D,0x5B,0x09,0xF1,0xD5,0x8E,0xE3,0x53,0xF4,0x8E,0x63,0xFA,0x3F, - 0xA7,0xDB,0xB4,0x66,0xDF,0x62,0x66,0xD6,0xD1,0x6E,0x41,0x8D,0xF2,0x2D,0xB5,0xEA, - 0x77,0x4A,0x9F,0x9D,0x58,0xE2,0x2B,0x59,0xC0,0x40,0x23,0xED,0x2D,0x28,0x82,0x45, - 0x3E,0x79,0x54,0x92,0x26,0x98,0xE0,0x80,0x48,0xA8,0x37,0xEF,0xF0,0xD6,0x79,0x60, - 0x16,0xDE,0xAC,0xE8,0x0E,0xCD,0x6E,0xAC,0x44,0x17,0x38,0x2F,0x49,0xDA,0xE1,0x45, - 0x3E,0x2A,0xB9,0x36,0x53,0xCF,0x3A,0x50,0x06,0xF7,0x2E,0xE8,0xC4,0x57,0x49,0x6C, - 0x61,0x21,0x18,0xD5,0x04,0xAD,0x78,0x3C,0x2C,0x3A,0x80,0x6B,0xA7,0xEB,0xAF,0x15, - 0x14,0xE9,0xD8,0x89,0xC1,0xB9,0x38,0x6C,0xE2,0x91,0x6C,0x8A,0xFF,0x64,0xB9,0x77, - 0x25,0x57,0x30,0xC0,0x1B,0x24,0xA3,0xE1,0xDC,0xE9,0xDF,0x47,0x7C,0xB5,0xB4,0x24, - 0x08,0x05,0x30,0xEC,0x2D,0xBD,0x0B,0xBF,0x45,0xBF,0x50,0xB9,0xA9,0xF3,0xEB,0x98, - 0x01,0x12,0xAD,0xC8,0x88,0xC6,0x98,0x34,0x5F,0x8D,0x0A,0x3C,0xC6,0xE9,0xD5,0x95, - 0x95,0x6D,0xDE, -}; - -uint8_t _digicertOCSPResponse[] = { - 0x30,0x82,0x01,0xe6,0x0a,0x01,0x00,0xa0,0x82,0x01,0xdf,0x30,0x82,0x01,0xdb,0x06,0x09,0x2b,0x06,0x01, - 0x05,0x05,0x07,0x30,0x01,0x01,0x04,0x82,0x01,0xcc,0x30,0x82,0x01,0xc8,0x30,0x81,0xb1,0xa2,0x16,0x04, - 0x14,0x0f,0x80,0x61,0x1c,0x82,0x31,0x61,0xd5,0x2f,0x28,0xe7,0x8d,0x46,0x38,0xb4,0x2c,0xe1,0xc6,0xd9, - 0xe2,0x18,0x0f,0x32,0x30,0x31,0x38,0x30,0x34,0x32,0x35,0x31,0x37,0x34,0x37,0x34,0x33,0x5a,0x30,0x81, - 0x85,0x30,0x81,0x82,0x30,0x49,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0x10, - 0x5f,0xa6,0x7a,0x80,0x08,0x9d,0xb5,0x27,0x9f,0x35,0xce,0x83,0x0b,0x43,0x88,0x9e,0xa3,0xc7,0x0d,0x04, - 0x14,0x0f,0x80,0x61,0x1c,0x82,0x31,0x61,0xd5,0x2f,0x28,0xe7,0x8d,0x46,0x38,0xb4,0x2c,0xe1,0xc6,0xd9, - 0xe2,0x02,0x10,0x01,0xaf,0x1e,0xfb,0xdd,0x5e,0xae,0x09,0x52,0x32,0x0b,0x24,0xfe,0x6b,0x55,0x68,0xa1, - 0x11,0x18,0x0f,0x32,0x30,0x31,0x36,0x30,0x39,0x30,0x32,0x32,0x31,0x32,0x38,0x34,0x38,0x5a,0x18,0x0f, - 0x32,0x30,0x31,0x38,0x30,0x34,0x32,0x35,0x31,0x37,0x34,0x37,0x34,0x33,0x5a,0xa0,0x11,0x18,0x0f,0x32, - 0x30,0x31,0x38,0x30,0x35,0x30,0x32,0x31,0x37,0x30,0x32,0x34,0x33,0x5a,0x30,0x0d,0x06,0x09,0x2a,0x86, - 0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x9c,0x3d,0xb9,0xc6,0xfd,0x97, - 0x21,0xb0,0x04,0xc1,0x62,0x4b,0xc7,0x74,0x7a,0x37,0x01,0xa6,0x22,0xb2,0xd2,0xce,0xbb,0xd4,0x67,0xcd, - 0xda,0x66,0xb6,0x53,0xbc,0x81,0xd4,0x09,0x9c,0xa0,0x3e,0x95,0x6d,0x90,0x0a,0xe6,0x39,0x24,0xb0,0x42, - 0x17,0xc1,0x02,0x62,0x57,0xc8,0x04,0x07,0x66,0x1f,0xc4,0x75,0x75,0xe6,0x82,0x7e,0xd3,0x28,0x46,0xde, - 0xaa,0xb8,0xd7,0x2d,0xd5,0x17,0x70,0xb7,0xbf,0xd6,0xcc,0xa3,0x14,0xe9,0x5f,0x9d,0x40,0xf2,0x5f,0x29, - 0xb2,0xde,0x8a,0x9f,0x02,0x79,0x2a,0xe9,0xa0,0xc0,0x0f,0xb1,0xc3,0xf8,0xaa,0xb1,0x9d,0xaf,0x15,0x78, - 0xf1,0x98,0x6c,0xd2,0xf2,0x1f,0x8d,0x75,0xd4,0xb6,0x91,0xc4,0xb8,0x13,0x18,0xd2,0x30,0xa1,0xb1,0x1e, - 0x81,0x1a,0xef,0x2a,0x42,0x52,0x2a,0xd4,0xec,0xc5,0x8a,0x87,0x9c,0x7b,0x38,0x81,0xf9,0x6e,0xfe,0x60, - 0x3d,0xc7,0xfe,0x77,0x64,0x99,0x3d,0x1c,0xf5,0x92,0xe9,0xe5,0x45,0xf3,0x7e,0x98,0x74,0xfa,0x5a,0xd9, - 0xf4,0x79,0xf3,0xf7,0x6c,0x99,0xce,0x52,0x47,0xc0,0x4a,0x87,0x20,0xed,0x3b,0x76,0x2a,0x58,0x3f,0x8b, - 0xb3,0xcb,0x9f,0xd4,0x11,0x26,0xc4,0x43,0xce,0xd1,0x6f,0x48,0xe4,0xd0,0x2f,0xa1,0x95,0x5a,0xb9,0x93, - 0x25,0xf9,0xd4,0x1a,0xe9,0x75,0x7d,0xcf,0xfb,0xc5,0xa5,0x78,0x98,0x68,0xfb,0x12,0xbd,0x53,0xdc,0x98, - 0x1d,0xd6,0xc7,0xa1,0x28,0x3f,0x5b,0x82,0x39,0x18,0x85,0xfd,0x91,0x8f,0x80,0xa2,0x30,0xd9,0xee,0xc4, - 0x23,0x48,0x3c,0x50,0x18,0x7e,0xc7,0x1d,0xc1,0x5a -}; - -uint8_t _caissuer_https[] = { - 0x30,0x82,0x04,0x68,0x30,0x82,0x03,0x50,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x7A, - 0x22,0xA1,0x88,0x18,0x9E,0x75,0x77,0xE6,0xEF,0x7E,0xC0,0x33,0x8E,0xE8,0x90,0xE8, - 0x7B,0xC4,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, - 0x00,0x30,0x81,0x81,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, - 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, - 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C, - 0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03, - 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, - 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, - 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x15, - 0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x0C,0x0C,0x54,0x65,0x73,0x74,0x20,0x52,0x6F, - 0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x38,0x30,0x34,0x32,0x38,0x32, - 0x30,0x32,0x31,0x34,0x31,0x5A,0x17,0x0D,0x31,0x39,0x30,0x34,0x32,0x38,0x32,0x30, - 0x32,0x31,0x34,0x31,0x5A,0x30,0x81,0x8D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, - 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A, - 0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03, - 0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, - 0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65, - 0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69, - 0x6E,0x67,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x48,0x54,0x54, - 0x50,0x53,0x20,0x43,0x41,0x49,0x73,0x73,0x75,0x65,0x72,0x20,0x54,0x65,0x73,0x74, - 0x20,0x43,0x65,0x72,0x74,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,0xC1,0x68,0xC2,0x47,0x1E,0x07,0x82,0x66,0x47,0xC9, - 0x5C,0x22,0xDD,0x8B,0x93,0x6A,0xA7,0x22,0x00,0xB8,0xDA,0x8C,0x3C,0x52,0xA7,0x47, - 0x73,0xBB,0x7A,0xD7,0x8C,0x1E,0xAE,0xDA,0x34,0x25,0x4E,0xEB,0x1F,0x33,0x0B,0x8A, - 0xC7,0x6D,0x2A,0x93,0xDB,0x0D,0xD0,0x47,0x85,0x9C,0x14,0xD5,0x23,0xE3,0xE4,0x94, - 0xE0,0x17,0x9F,0x56,0x64,0x8E,0xE0,0x08,0xE9,0x1B,0x4C,0x7C,0x77,0xF9,0x35,0x74, - 0x52,0x43,0x90,0x13,0xFA,0x51,0x9A,0xA2,0x93,0x47,0x94,0xE7,0xBD,0x07,0xE5,0xFB, - 0x67,0x8B,0xF0,0xE2,0x0C,0x97,0xFD,0x29,0x51,0xBD,0x85,0x6C,0xBE,0x36,0xFD,0xDD, - 0xCC,0x99,0x4D,0x68,0x37,0x96,0xB2,0x20,0x85,0x55,0xA5,0x99,0xA4,0x7E,0xD7,0x19, - 0x06,0x15,0x20,0x10,0x50,0x51,0x2E,0x74,0x5C,0x43,0x49,0x94,0x6B,0x0E,0x9E,0xFB, - 0xDF,0xB2,0xEB,0xD9,0x28,0xA8,0xF1,0x25,0x49,0xC8,0xFE,0x3B,0xE1,0x45,0x95,0x47, - 0xD1,0x53,0xCD,0x34,0x9A,0x6F,0xC4,0x3F,0x63,0xC2,0x60,0xC6,0x40,0xBB,0xF7,0x20, - 0x8A,0xB8,0xB7,0xD7,0xC2,0xBB,0x48,0x24,0x64,0xA2,0x4A,0xE4,0x2A,0x17,0x68,0xE2, - 0xAC,0x47,0x2D,0xCC,0xBD,0xB7,0xCE,0x73,0xDF,0x96,0x8C,0x12,0x56,0xE3,0x29,0xE3, - 0x4D,0xB4,0x55,0x28,0xAB,0x28,0x24,0x45,0x7F,0x55,0x66,0xCD,0x46,0x29,0x89,0x58, - 0xFF,0xA6,0xD1,0x67,0xAC,0x50,0xEE,0x55,0x6D,0x6A,0x2A,0xCF,0xD6,0x09,0xE9,0xDA, - 0x22,0xB0,0xAF,0x90,0xD7,0x02,0xB2,0xCE,0x5F,0x09,0x96,0x5E,0x88,0xAE,0xB5,0xB6, - 0xA1,0xC3,0x9D,0x1A,0x2F,0x2D,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xCA,0x30,0x81, - 0xC7,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, - 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30, - 0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x03,0x01,0x30,0x16,0x06,0x03,0x55,0x1D,0x11,0x04,0x0F,0x30,0x0D,0x82, - 0x0B,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03, - 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xDF,0xC7,0x68,0x26,0x64,0x95,0x5D,0x73,0x36, - 0x84,0xE8,0xE3,0x1D,0xC8,0x28,0x5E,0xA8,0x27,0x73,0x8C,0x30,0x1F,0x06,0x03,0x55, - 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xB5,0xA9,0x53,0x08,0x10,0x38,0x1A,0xA5, - 0xB3,0x84,0xC9,0xEE,0xC4,0xAB,0x0F,0xB8,0x5F,0x68,0x10,0xA2,0x30,0x3A,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x2E,0x30,0x2C,0x30,0x2A,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A, - 0x2F,0x2F,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65, - 0x73,0x74,0x43,0x41,0x2E,0x64,0x65,0x72,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xC4,0x48,0xDF,0x5E, - 0x73,0xD1,0x43,0x28,0x7D,0x69,0x71,0x32,0x1F,0xCC,0x1A,0xEB,0x5B,0x98,0x9D,0xCE, - 0xFF,0xCA,0x16,0xA9,0x96,0xE7,0x4D,0xC4,0xAE,0x53,0xE2,0x5D,0xDB,0xDA,0x40,0x80, - 0xE5,0xFB,0xF3,0xD7,0x21,0x9A,0x77,0x1D,0x67,0xFC,0x04,0x62,0x18,0xFF,0x10,0x59, - 0xF4,0xDD,0xF4,0xC6,0x8F,0xB4,0xEF,0x9F,0x05,0xA6,0xF1,0xCB,0x44,0x24,0x02,0x19, - 0x75,0xF9,0x3C,0x28,0x8A,0xAA,0x57,0x6B,0xFF,0x64,0xFF,0xD7,0xE2,0x62,0x67,0x70, - 0x20,0x4D,0xAE,0xD2,0x67,0xED,0x92,0xA4,0xFA,0x8A,0xC3,0x24,0x9C,0x2F,0x4D,0x2C, - 0xA9,0xA5,0x92,0x5E,0x5C,0x6F,0xDB,0xAB,0x96,0xA6,0xB1,0x5B,0xF1,0x8D,0x97,0x08, - 0xBC,0x5B,0x27,0xD5,0x9E,0x2D,0xF0,0x49,0x68,0xA6,0x92,0x00,0x13,0xAD,0x60,0x9E, - 0x78,0x72,0xC2,0x18,0xB8,0xE5,0x9D,0x72,0xA5,0x87,0x61,0xA8,0x95,0x8A,0x2B,0xB2, - 0xCC,0xCA,0x7F,0x1E,0x1E,0xC5,0xFB,0x5A,0x0C,0x77,0x17,0xB0,0xBE,0x7B,0x5A,0x50, - 0x05,0x32,0x40,0x98,0x3A,0x8B,0x22,0x3F,0x3B,0xA5,0xA8,0xA9,0x59,0x3B,0x55,0x92, - 0xD1,0x8A,0x34,0x73,0xA6,0xD6,0x5D,0x5E,0x85,0x59,0x00,0xD5,0x55,0x94,0x80,0xC1, - 0xB9,0xF1,0xCA,0x2B,0xC5,0x96,0xEE,0x49,0x6A,0x2C,0xDD,0x62,0x98,0xB3,0x74,0x09, - 0x09,0xDE,0x3D,0x59,0x5B,0x21,0x76,0x6E,0x27,0x66,0xED,0x7B,0x74,0x7F,0xE7,0xA9, - 0xAE,0xEB,0x40,0x83,0xB9,0xBC,0xE6,0x0C,0x1E,0x53,0xB2,0xEA,0x79,0xC4,0xA9,0x30, - 0x2B,0x1F,0xC4,0x34,0x82,0x3E,0xFC,0x1E,0x2D,0x66,0x75,0xD0, -}; - -#endif /* _SECURITY_SI_23_SECTRUST_OCSP_H_ */ diff --git a/OSX/sec/Security/Regressions/secitem/si-24-sectrust-itms.c b/OSX/sec/Security/Regressions/secitem/si-24-sectrust-itms.c index 5b4fe130..dd4c0c19 100644 --- a/OSX/sec/Security/Regressions/secitem/si-24-sectrust-itms.c +++ b/OSX/sec/Security/Regressions/secitem/si-24-sectrust-itms.c @@ -151,7 +151,7 @@ static void tests(void) "trust is kSecTrustResultUnspecified"); is(SecTrustGetCertificateCount(trust), 2, "cert count is 2"); SecKeyRef pub_key_leaf; - isnt(pub_key_leaf = SecTrustCopyPublicKey(trust), NULL, "get leaf pub key"); + isnt(pub_key_leaf = SecTrustCopyKey(trust), NULL, "get leaf pub key"); if (!pub_key_leaf) { goto errOut; } CFErrorRef error = NULL; ok(SecKeyVerifySignature(pub_key_leaf, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, sha1Data, signature, &error), diff --git a/OSX/sec/Security/Regressions/secitem/si-26-sectrust-copyproperties.c b/OSX/sec/Security/Regressions/secitem/si-26-sectrust-copyproperties.c index 9119beb2..8a1a2856 100644 --- a/OSX/sec/Security/Regressions/secitem/si-26-sectrust-copyproperties.c +++ b/OSX/sec/Security/Regressions/secitem/si-26-sectrust-copyproperties.c @@ -365,7 +365,7 @@ static void print_cert(SecCertificateRef cert, bool verbose) { } print_plist(plist); - CFRelease(plist); + CFReleaseNull(plist); } static void tests(void) @@ -412,12 +412,7 @@ static void tests(void) properties = SecCertificateCopyProperties(leaf); isnt(properties, NULL, "leaf properties returned"); CFReleaseNull(properties); - // Xcode doesn't have a SDK for 10.15.1 so we need to work around this. - // rdar://problem/55890533 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" properties = SecCertificateCopyLocalizedProperties(leaf, true); -#pragma clang diagnostic pop isnt(properties, NULL, "localized leaf properties returned"); CFReleaseNull(properties); diff --git a/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.h b/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.h index f66bb236..e2555dd7 100644 --- a/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.h +++ b/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.h @@ -24,11 +24,11 @@ #ifndef _SECURITY_SI_32_SECTRUST_PINNING_REQUIRED_H_ #define _SECURITY_SI_32_SECTRUST_PINNING_REQUIRED_H_ -/* subject:/CN=profile.ess.apple.com/O=Apple Inc./ST=California/C=US */ +/* subject:/CN=init.ess.apple.com/O=Apple Inc./ST=California/C=US */ /* issuer :/CN=Test Apple Server Authentication CA/OU=Certification Authority/O=Apple Inc./C=US */ uint8_t _ids_test[]={ - 0x30,0x82,0x04,0x76,0x30,0x82,0x03,0x5E,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x24, - 0x1F,0x1C,0x82,0xF4,0x25,0x42,0xB4,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x30,0x82,0x04,0x87,0x30,0x82,0x03,0x6F,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x72, + 0xA1,0xD2,0xCA,0x8B,0x32,0x32,0xCB,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x72,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04, 0x03,0x0C,0x23,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x53,0x65, 0x72,0x76,0x65,0x72,0x20,0x41,0x75,0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74, @@ -36,69 +36,70 @@ uint8_t _ids_test[]={ 0x17,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,0x38,0x30,0x37,0x30,0x31,0x30,0x35,0x33,0x37,0x5A,0x17,0x0D,0x31,0x39,0x30, - 0x39,0x30,0x36,0x30,0x31,0x30,0x35,0x33,0x37,0x5A,0x30,0x57,0x31,0x1E,0x30,0x1C, - 0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x70,0x72,0x6F,0x66,0x69,0x6C,0x65,0x2E,0x65, - 0x73,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x13,0x30,0x11, - 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, - 0x2E,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, - 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, - 0x02,0x55,0x53,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,0xDA,0xEE,0xCE,0x4F,0x0A,0x31,0xF5,0x6A,0x6C,0xD8,0xD8,0xF9, - 0x1E,0x4D,0x85,0x38,0x17,0x42,0x45,0xBA,0xF2,0x8C,0x16,0xC2,0xEC,0x29,0x84,0x88, - 0xC2,0xC2,0x45,0xCB,0x79,0xF6,0x7F,0x89,0x65,0x3D,0x98,0xED,0xE7,0x21,0xA8,0xAB, - 0x4C,0xE2,0x75,0x7C,0x5B,0x26,0x00,0xC4,0x4C,0x81,0xE4,0xFF,0xA4,0xBB,0xA6,0x0F, - 0x80,0x9D,0xD9,0xD5,0xA3,0xD2,0x5C,0xA1,0x25,0xE1,0x9F,0xB5,0x53,0xF3,0x31,0x3B, - 0xCB,0x55,0xC2,0x75,0xFB,0xC7,0x3B,0x3C,0x07,0x6B,0x29,0xAF,0x43,0x90,0x1E,0x9B, - 0xC3,0x47,0x0C,0x09,0xDF,0x07,0x9C,0xA8,0x12,0x3E,0x9E,0xFE,0x29,0xE7,0x11,0x06, - 0xA1,0x1D,0x8C,0xEA,0x99,0x73,0xD5,0x13,0x66,0x51,0x0D,0x3D,0x6B,0x67,0x38,0x68, - 0x04,0x40,0xE8,0x1E,0x50,0x56,0x59,0x77,0x5A,0xF3,0x12,0xAC,0x2B,0x93,0xF8,0xBC, - 0x87,0xA6,0x70,0x3F,0xB8,0x8F,0xE2,0xEC,0x38,0x5F,0xB4,0x73,0xE6,0x95,0x38,0xD1, - 0x31,0x16,0xFE,0xFF,0x77,0x01,0xD2,0xD0,0x2F,0xF4,0xF7,0x3A,0x21,0x5B,0xA8,0x36, - 0xC4,0xE4,0x58,0x26,0x3D,0x6F,0xFF,0xA0,0x39,0x45,0x83,0xCB,0x66,0xF5,0x4C,0xC6, - 0x43,0x67,0x1C,0x58,0x72,0x5B,0xCC,0xAA,0x15,0x91,0x4D,0xE6,0x24,0xF6,0x18,0xFE, - 0xF5,0xEF,0x75,0xB4,0x5B,0xF1,0x86,0x2F,0x67,0x0A,0x5B,0x7D,0x8E,0x22,0x1B,0x2F, - 0xFA,0xE2,0xB1,0x41,0x37,0x4D,0x26,0xD6,0x9B,0x13,0x66,0x5F,0xE5,0xCD,0x4B,0xC9, - 0x91,0x62,0xF9,0x98,0x8E,0x7F,0xB6,0x6F,0x7A,0xFF,0x95,0xF1,0x0B,0x1C,0x1F,0xFB, - 0xD1,0x49,0xB7,0xFD,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x29,0x30,0x82,0x01, - 0x25,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,0xA8,0xCA,0x7A,0x9B, - 0xA8,0x37,0x71,0x9E,0x3D,0xEC,0x5A,0xAB,0x66,0x2E,0xDC,0xD7,0x14,0x3D,0x7B,0xF2, - 0x30,0x52,0x06,0x03,0x55,0x1D,0x11,0x04,0x4B,0x30,0x49,0x82,0x18,0x6F,0x70,0x65, - 0x6E,0x6D,0x61,0x72,0x6B,0x65,0x74,0x2E,0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C, - 0x65,0x2E,0x63,0x6F,0x6D,0x82,0x16,0x69,0x64,0x65,0x6E,0x74,0x69,0x74,0x79,0x2E, - 0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x82,0x15,0x70, - 0x72,0x6F,0x66,0x69,0x6C,0x65,0x2E,0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65, - 0x2E,0x63,0x6F,0x6D,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06, - 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x49,0x06,0x03,0x55,0x1D,0x1F, - 0x04,0x42,0x30,0x40,0x30,0x3E,0xA0,0x3C,0xA0,0x3A,0x86,0x38,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,0x73,0x65,0x72,0x76,0x65,0x72,0x61,0x75,0x74,0x68,0x63,0x61,0x31, - 0x2E,0x63,0x72,0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x3F, - 0x0C,0x0D,0xC7,0x17,0x81,0x02,0x61,0x50,0x18,0xFC,0xAF,0xBD,0xA0,0xA8,0x4E,0x78, - 0xA7,0xFB,0xF1,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, - 0x02,0x05,0xA0,0x30,0x11,0x06,0x0B,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x1B, - 0x04,0x02,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, - 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x53,0x88,0x1A,0x2C,0x60,0xFB, - 0x15,0x08,0x83,0x06,0xE4,0xF7,0x23,0x38,0x50,0xA6,0xD3,0xA7,0xBD,0x06,0xB4,0xAF, - 0x87,0x4F,0x13,0xC6,0x1B,0x79,0x2C,0x80,0x30,0x7E,0x23,0x0D,0x4E,0x6A,0xC3,0x9B, - 0xF8,0x73,0x1E,0x7B,0xD7,0x14,0xB0,0x5F,0xA8,0xEC,0xB4,0x0D,0xBD,0x3B,0x40,0x87, - 0x9A,0x4D,0x1D,0x2D,0x8F,0x00,0xCE,0x72,0xDE,0xAF,0x2E,0x73,0x82,0x54,0xBA,0x0E, - 0x3A,0xC2,0xAB,0x7C,0x09,0xE8,0xBE,0x0B,0x26,0x0F,0xC3,0x80,0xCD,0x9C,0x85,0x09, - 0xA3,0xD3,0xB5,0xCE,0x7D,0x63,0xB3,0x33,0x32,0x06,0xD9,0xAE,0xA9,0x7D,0x1E,0x2F, - 0xF9,0x1B,0x60,0x3F,0x1F,0xFA,0x57,0x17,0xC6,0x5A,0x28,0x44,0x24,0x36,0xF4,0x77, - 0xE6,0x91,0x7D,0xED,0x45,0x28,0x59,0x3E,0xA1,0x03,0x3E,0x45,0x3F,0x41,0x8E,0x62, - 0x0A,0x21,0xD8,0x47,0xED,0xFA,0x53,0x4F,0x07,0x7D,0xF6,0xFC,0xE1,0x98,0xC0,0x0C, - 0xAA,0x68,0xD2,0xB7,0xCD,0x7D,0xF5,0x55,0xD7,0x56,0x55,0x78,0x56,0x80,0x8A,0x30, - 0x89,0x30,0x2C,0xA9,0x8A,0x71,0xD1,0x4E,0x05,0x4A,0x5E,0xDB,0x23,0x2F,0xC9,0xA1, - 0x45,0xF9,0xF1,0x16,0xE1,0x72,0xA5,0xD7,0xB1,0x32,0xB3,0x90,0x4B,0xF8,0x72,0xD6, - 0xF3,0x65,0x84,0x0F,0xB6,0x23,0x41,0x4D,0xE3,0xDD,0xC0,0x5B,0xB7,0xF8,0x1C,0xF2, - 0x1F,0xB5,0x5D,0xD0,0xFB,0xB9,0x7D,0x0D,0x34,0xC4,0x61,0x42,0x8E,0xD4,0xED,0x4C, - 0xA4,0x83,0x9C,0x8D,0xBA,0xE3,0x49,0x45,0x07,0xE4,0x0E,0x0E,0x01,0x10,0x93,0xCF, - 0x49,0x39,0x4C,0x1C,0x0A,0x88,0xC3,0x2E,0x7C,0x64, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x32,0x30, + 0x30,0x39,0x31,0x33,0x32,0x33,0x34,0x30,0x31,0x37,0x5A,0x17,0x0D,0x32,0x31,0x31, + 0x30,0x31,0x33,0x32,0x33,0x34,0x30,0x31,0x37,0x5A,0x30,0x54,0x31,0x1B,0x30,0x19, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x69,0x6E,0x69,0x74,0x2E,0x65,0x73,0x73,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, + 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,0xA0,0x86,0xAC,0xB1,0xE9,0xAE,0xD2,0x94,0x23,0x46,0x80,0x95,0x7E,0x25,0x89, + 0x43,0x0F,0x8B,0xA2,0x60,0x49,0xCB,0x1C,0xA4,0x33,0x3C,0x7E,0x27,0x7C,0xA2,0x04, + 0x88,0x90,0xD0,0x1D,0xCA,0x67,0x6F,0xFE,0xF0,0xB9,0x68,0xF9,0x7A,0x7E,0xD3,0xA2, + 0x96,0x27,0xFD,0x42,0x1F,0x67,0x27,0x72,0x31,0x68,0x71,0x98,0x71,0x58,0x62,0x05, + 0x83,0xCC,0xC8,0x48,0x96,0x3C,0x96,0x73,0x13,0x4C,0x5B,0x22,0x12,0xBF,0x42,0xEB, + 0x1F,0x4B,0x7F,0x2F,0xC9,0x92,0x08,0x41,0x2A,0xFD,0xF9,0xA7,0xF2,0x36,0xC6,0x7D, + 0xAB,0x25,0xA1,0x5B,0x26,0x30,0x7F,0x4A,0x19,0xEE,0xDB,0x26,0x5C,0x22,0x68,0x1D, + 0xFC,0x81,0x7D,0x1B,0x76,0xFA,0x98,0x16,0xDE,0x3B,0xC3,0x6F,0x8B,0x14,0x01,0xDF, + 0xD8,0x34,0x37,0x4A,0x2A,0x2A,0xE9,0xCE,0x78,0x58,0x40,0x41,0x14,0x1F,0xDD,0x86, + 0x30,0xD3,0xBD,0xA5,0x02,0x5E,0xFD,0x40,0xDF,0x2D,0xDA,0x6C,0x1C,0xD8,0x7F,0x92, + 0xBB,0xA4,0xF9,0x8B,0x3A,0xDE,0xAE,0xA7,0x23,0x5C,0x2B,0x9C,0x2F,0x9A,0xFD,0x0E, + 0xF5,0xFE,0x40,0x7F,0x5C,0x7C,0xA9,0x01,0xE2,0x11,0x21,0x96,0xFA,0xEF,0x2B,0x0C, + 0x95,0x7E,0x96,0x2D,0xA0,0xA9,0x15,0x7A,0x82,0x25,0x83,0x12,0xD6,0x83,0x0A,0x91, + 0xA5,0xD7,0xF2,0xCB,0xC3,0x18,0x4E,0xF4,0xA1,0xA1,0x0A,0xD1,0x7E,0x88,0x1C,0xB1, + 0x10,0xA9,0x83,0xE3,0xAD,0xF7,0xFF,0xEA,0xDC,0x20,0xEB,0x74,0x94,0xE0,0x89,0xDF, + 0x34,0x25,0x28,0x58,0xE9,0xC8,0x93,0x84,0x2D,0x24,0xB0,0xDC,0xD2,0x46,0x09,0x63, + 0x5F,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x3D,0x30,0x82,0x01,0x39,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,0xA8,0xCA,0x7A,0x9B,0xA8,0x37,0x71, + 0x9E,0x3D,0xEC,0x5A,0xAB,0x66,0x2E,0xDC,0xD7,0x14,0x3D,0x7B,0xF2,0x30,0x66,0x06, + 0x03,0x55,0x1D,0x11,0x04,0x5F,0x30,0x5D,0x82,0x15,0x70,0x72,0x6F,0x66,0x69,0x6C, + 0x65,0x2E,0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x82, + 0x18,0x6F,0x70,0x65,0x6E,0x6D,0x61,0x72,0x6B,0x65,0x74,0x2E,0x65,0x73,0x73,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x82,0x16,0x69,0x64,0x65,0x6E,0x74, + 0x69,0x74,0x79,0x2E,0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F, + 0x6D,0x82,0x12,0x69,0x6E,0x69,0x74,0x2E,0x65,0x73,0x73,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x49,0x06,0x03,0x55,0x1D, + 0x1F,0x04,0x42,0x30,0x40,0x30,0x3E,0xA0,0x3C,0xA0,0x3A,0x86,0x38,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,0x73,0x65,0x72,0x76,0x65,0x72,0x61,0x75,0x74,0x68,0x63,0x61, + 0x31,0x2E,0x63,0x72,0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, + 0x74,0x05,0xFF,0xDB,0xBE,0x4A,0xC9,0x3B,0x54,0x77,0xAE,0x4E,0x60,0xB2,0xD1,0x47, + 0x70,0xCE,0x35,0xDB,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, + 0x03,0x02,0x05,0xA0,0x30,0x11,0x06,0x0B,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06, + 0x1B,0x04,0x02,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xAB,0x83,0x22,0x06,0x14, + 0x92,0x90,0x4F,0xFF,0x87,0x9F,0xF5,0x69,0xFE,0x87,0x14,0xAD,0x58,0x47,0x86,0x17, + 0x48,0x90,0xAA,0x34,0x37,0x23,0x7E,0x37,0x93,0x5D,0xCA,0xFF,0xEF,0x97,0x13,0x2B, + 0xFF,0x82,0x51,0xCA,0x87,0xF0,0xE1,0x1C,0x8C,0x95,0xE3,0x96,0x2D,0x69,0x6B,0x8C, + 0xFA,0xCC,0x57,0x20,0x35,0x98,0x31,0x83,0x30,0xF3,0x62,0xE8,0xD0,0xAB,0xBE,0xE3, + 0xFB,0x68,0xB4,0xBD,0x10,0xFC,0xDD,0x4B,0x5A,0x07,0x51,0x91,0x29,0xA6,0x6F,0x84, + 0x42,0xD8,0xAE,0xF2,0x3A,0xD2,0xA2,0xB4,0xB6,0xAB,0x32,0x24,0xE3,0xFD,0x57,0x8E, + 0x53,0xDD,0x53,0x7D,0x6E,0xE4,0x76,0x80,0x13,0xB9,0xF4,0x12,0x03,0xB4,0xB6,0x6D, + 0x3C,0xCA,0x9C,0x08,0x37,0xF2,0xD8,0x97,0x62,0x1C,0xC9,0xFF,0x4B,0x8E,0x7A,0xA4, + 0x07,0x66,0x98,0xB9,0x95,0xB2,0xA2,0xD4,0xF1,0x4E,0x0B,0xC9,0xC1,0xEB,0x10,0x21, + 0xA3,0xFD,0x69,0xF4,0x64,0xF0,0x55,0x7E,0xFB,0x3C,0x5D,0x4A,0xF2,0x65,0xB1,0x67, + 0x68,0x59,0xE6,0xE1,0x9F,0x93,0xDD,0x2A,0x44,0x76,0x85,0x16,0x82,0x6A,0x1E,0xA6, + 0x37,0xE8,0xD0,0x16,0x73,0x03,0xBE,0x88,0xBC,0x50,0x97,0xA3,0xC2,0xB9,0x65,0xF1, + 0x64,0x92,0x57,0x04,0xAD,0xE6,0x77,0x3F,0x1B,0xA4,0xE3,0xF2,0xBE,0x41,0xA6,0x66, + 0x9E,0xC6,0xF5,0x07,0xE8,0x9B,0x13,0x34,0x06,0x55,0x45,0x37,0x88,0x65,0x4F,0x4C, + 0x11,0xE0,0x02,0xD7,0xE8,0xC3,0x1B,0x4D,0xCD,0x31,0x59,0x55,0x90,0xA3,0x6A,0x40, + 0x31,0xAD,0x92,0x86,0xFE,0x53,0xC5,0xB8,0x5E,0xA3,0x02, }; /* subject:/CN=Test Apple Server Authentication CA/OU=Certification Authority/O=Apple Inc./C=US */ diff --git a/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.m b/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.m index 4e44d314..d5536538 100644 --- a/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.m +++ b/OSX/sec/Security/Regressions/secitem/si-32-sectrust-pinning-required.m @@ -47,7 +47,7 @@ static void setup_globals(void) { certs = @[(__bridge id)leaf,(__bridge id)intermediate]; root = @[(__bridge id)rootcert]; - verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:560000000.0]; //September 30, 2018 at 4:33:20 AM PDT + verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:622000000.0]; //September 16, 2020 at 6:46:40 PM PDT CFReleaseNull(leaf); CFReleaseNull(intermediate); @@ -84,11 +84,12 @@ static void tests(void) { SecPolicyRef policy = NULL; - policy = SecPolicyCreateSSL(true, CFSTR("openmarket.ess.apple.com")); + // init domains are excluded from IDS pinning rules + policy = SecPolicyCreateSSL(true, CFSTR("init.ess.apple.com")); SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); is(test_with_policy(policy), kSecTrustResultRecoverableTrustFailure, "Unpinned connection succeeeded when pinning required"); - policy = SecPolicyCreateAppleIDSServiceContext(CFSTR("openmarket.ess.apple.com"), NULL); + policy = SecPolicyCreateAppleIDSServiceContext(CFSTR("init.ess.apple.com"), NULL); SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); is(test_with_policy(policy), kSecTrustResultUnspecified, "Policy pinned connection failed when pinning required"); @@ -97,14 +98,14 @@ static void tests(void) is(test_with_policy(policy), kSecTrustResultUnspecified, "Systemwide hostname pinned connection failed when pinning required"); NSDictionary *policy_properties = @{ - (__bridge NSString *)kSecPolicyName : @"openmarket.ess.apple.com", + (__bridge NSString *)kSecPolicyName : @"init.ess.apple.com", (__bridge NSString *)kSecPolicyPolicyName : @"IDS", }; policy = SecPolicyCreateWithProperties(kSecPolicyAppleSSL, (__bridge CFDictionaryRef)policy_properties); SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); is(test_with_policy(policy), kSecTrustResultUnspecified, "Systemwide policy name pinned connection failed when pinning required"); - policy = SecPolicyCreateSSL(true, CFSTR("openmarket.ess.apple.com")); + policy = SecPolicyCreateSSL(true, CFSTR("init.ess.apple.com")); SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); is(test_with_policy_exception(policy, true), kSecTrustResultUnspecified, "Unpinned connection failed when pinning exception set"); diff --git a/OSX/sec/Security/Regressions/secitem/si-34-cms-timestamp.m b/OSX/sec/Security/Regressions/secitem/si-34-cms-timestamp.m index af261c72..d06ddf5b 100644 --- a/OSX/sec/Security/Regressions/secitem/si-34-cms-timestamp.m +++ b/OSX/sec/Security/Regressions/secitem/si-34-cms-timestamp.m @@ -174,18 +174,16 @@ exit: CFReleaseNull(identity); } -static int ping_host(char *host_name){ - +static int ping_host(char *host_name) { struct sockaddr_in pin; struct hostent *nlp_host; + struct in_addr addr; int sd; - int port; - int retries = 5; - - port=80; + int port = 80; + int retries = 5; // tries 5 times then gived up + char **h_addr_list = NULL; - //tries 5 times then give up - while ((nlp_host=gethostbyname(host_name))==0 && retries--){ + while ((nlp_host=gethostbyname(host_name)) == 0 && retries--) { printf("Resolve Error! (%s) %d\n", host_name, h_errno); sleep(1); } @@ -196,20 +194,23 @@ static int ping_host(char *host_name){ bzero(&pin,sizeof(pin)); pin.sin_family=AF_INET; pin.sin_addr.s_addr=htonl(INADDR_ANY); - pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr; + h_addr_list = malloc(nlp_host->h_length * sizeof(char *)); + memcpy(h_addr_list, nlp_host->h_addr_list, nlp_host->h_length * sizeof(char *)); + memcpy(&addr, h_addr_list[0], sizeof(struct in_addr)); + pin.sin_addr.s_addr=addr.s_addr; pin.sin_port=htons(port); sd=socket(AF_INET,SOCK_STREAM,0); - if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){ + if (connect(sd,(struct sockaddr*)&pin,sizeof(pin)) == -1) { printf("connect error! (%s) %d\n", host_name, errno); close(sd); + free(h_addr_list); return 0; } - else{ - close(sd); - return 1; - } + close(sd); + free(h_addr_list); + return 1; } int si_34_cms_timestamp(int argc, char * const *argv) { diff --git a/OSX/sec/Security/Regressions/secitem/si-66-smime.c b/OSX/sec/Security/Regressions/secitem/si-66-smime.c index 0ad24d90..6e61e2db 100644 --- a/OSX/sec/Security/Regressions/secitem/si-66-smime.c +++ b/OSX/sec/Security/Regressions/secitem/si-66-smime.c @@ -1805,6 +1805,79 @@ unsigned char __9148843_bin[] = { }; unsigned int __9148843_bin_len = 4326; +/* subject:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root */ +/* issuer :/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root */ +const uint8_t __9148843_root[] = { + 0x30,0x82,0x04,0x36,0x30,0x82,0x03,0x1E,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x01, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30, + 0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x53,0x45,0x31,0x14, + 0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x41,0x64,0x64,0x54,0x72,0x75,0x73, + 0x74,0x20,0x41,0x42,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C, + 0x20,0x54,0x54,0x50,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x22,0x30,0x20, + 0x06,0x03,0x55,0x04,0x03,0x13,0x19,0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x20, + 0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x43,0x41,0x20,0x52,0x6F,0x6F,0x74, + 0x30,0x1E,0x17,0x0D,0x30,0x30,0x30,0x35,0x33,0x30,0x31,0x30,0x34,0x38,0x33,0x38, + 0x5A,0x17,0x0D,0x32,0x30,0x30,0x35,0x33,0x30,0x31,0x30,0x34,0x38,0x33,0x38,0x5A, + 0x30,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x53,0x45,0x31, + 0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x41,0x64,0x64,0x54,0x72,0x75, + 0x73,0x74,0x20,0x41,0x42,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,0x1D, + 0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61, + 0x6C,0x20,0x54,0x54,0x50,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x22,0x30, + 0x20,0x06,0x03,0x55,0x04,0x03,0x13,0x19,0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74, + 0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x43,0x41,0x20,0x52,0x6F,0x6F, + 0x74,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,0xB7,0xF7,0x1A,0x33,0xE6,0xF2,0x00,0x04,0x2D,0x39,0xE0,0x4E,0x5B,0xED, + 0x1F,0xBC,0x6C,0x0F,0xCD,0xB5,0xFA,0x23,0xB6,0xCE,0xDE,0x9B,0x11,0x33,0x97,0xA4, + 0x29,0x4C,0x7D,0x93,0x9F,0xBD,0x4A,0xBC,0x93,0xED,0x03,0x1A,0xE3,0x8F,0xCF,0xE5, + 0x6D,0x50,0x5A,0xD6,0x97,0x29,0x94,0x5A,0x80,0xB0,0x49,0x7A,0xDB,0x2E,0x95,0xFD, + 0xB8,0xCA,0xBF,0x37,0x38,0x2D,0x1E,0x3E,0x91,0x41,0xAD,0x70,0x56,0xC7,0xF0,0x4F, + 0x3F,0xE8,0x32,0x9E,0x74,0xCA,0xC8,0x90,0x54,0xE9,0xC6,0x5F,0x0F,0x78,0x9D,0x9A, + 0x40,0x3C,0x0E,0xAC,0x61,0xAA,0x5E,0x14,0x8F,0x9E,0x87,0xA1,0x6A,0x50,0xDC,0xD7, + 0x9A,0x4E,0xAF,0x05,0xB3,0xA6,0x71,0x94,0x9C,0x71,0xB3,0x50,0x60,0x0A,0xC7,0x13, + 0x9D,0x38,0x07,0x86,0x02,0xA8,0xE9,0xA8,0x69,0x26,0x18,0x90,0xAB,0x4C,0xB0,0x4F, + 0x23,0xAB,0x3A,0x4F,0x84,0xD8,0xDF,0xCE,0x9F,0xE1,0x69,0x6F,0xBB,0xD7,0x42,0xD7, + 0x6B,0x44,0xE4,0xC7,0xAD,0xEE,0x6D,0x41,0x5F,0x72,0x5A,0x71,0x08,0x37,0xB3,0x79, + 0x65,0xA4,0x59,0xA0,0x94,0x37,0xF7,0x00,0x2F,0x0D,0xC2,0x92,0x72,0xDA,0xD0,0x38, + 0x72,0xDB,0x14,0xA8,0x45,0xC4,0x5D,0x2A,0x7D,0xB7,0xB4,0xD6,0xC4,0xEE,0xAC,0xCD, + 0x13,0x44,0xB7,0xC9,0x2B,0xDD,0x43,0x00,0x25,0xFA,0x61,0xB9,0x69,0x6A,0x58,0x23, + 0x11,0xB7,0xA7,0x33,0x8F,0x56,0x75,0x59,0xF5,0xCD,0x29,0xD7,0x46,0xB7,0x0A,0x2B, + 0x65,0xB6,0xD3,0x42,0x6F,0x15,0xB2,0xB8,0x7B,0xFB,0xEF,0xE9,0x5D,0x53,0xD5,0x34, + 0x5A,0x27,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xDC,0x30,0x81,0xD9,0x30,0x1D,0x06, + 0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xAD,0xBD,0x98,0x7A,0x34,0xB4,0x26,0xF7, + 0xFA,0xC4,0x26,0x54,0xEF,0x03,0xBD,0xE0,0x24,0xCB,0x54,0x1A,0x30,0x0B,0x06,0x03, + 0x55,0x1D,0x0F,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13, + 0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x81,0x99,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x81,0x91,0x30,0x81,0x8E,0x80,0x14,0xAD,0xBD,0x98,0x7A,0x34,0xB4, + 0x26,0xF7,0xFA,0xC4,0x26,0x54,0xEF,0x03,0xBD,0xE0,0x24,0xCB,0x54,0x1A,0xA1,0x73, + 0xA4,0x71,0x30,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x53, + 0x45,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x41,0x64,0x64,0x54, + 0x72,0x75,0x73,0x74,0x20,0x41,0x42,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, + 0x13,0x1D,0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x20,0x45,0x78,0x74,0x65,0x72, + 0x6E,0x61,0x6C,0x20,0x54,0x54,0x50,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31, + 0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x03,0x13,0x19,0x41,0x64,0x64,0x54,0x72,0x75, + 0x73,0x74,0x20,0x45,0x78,0x74,0x65,0x72,0x6E,0x61,0x6C,0x20,0x43,0x41,0x20,0x52, + 0x6F,0x6F,0x74,0x82,0x01,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, + 0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xB0,0x9B,0xE0,0x85,0x25,0xC2, + 0xD6,0x23,0xE2,0x0F,0x96,0x06,0x92,0x9D,0x41,0x98,0x9C,0xD9,0x84,0x79,0x81,0xD9, + 0x1E,0x5B,0x14,0x07,0x23,0x36,0x65,0x8F,0xB0,0xD8,0x77,0xBB,0xAC,0x41,0x6C,0x47, + 0x60,0x83,0x51,0xB0,0xF9,0x32,0x3D,0xE7,0xFC,0xF6,0x26,0x13,0xC7,0x80,0x16,0xA5, + 0xBF,0x5A,0xFC,0x87,0xCF,0x78,0x79,0x89,0x21,0x9A,0xE2,0x4C,0x07,0x0A,0x86,0x35, + 0xBC,0xF2,0xDE,0x51,0xC4,0xD2,0x96,0xB7,0xDC,0x7E,0x4E,0xEE,0x70,0xFD,0x1C,0x39, + 0xEB,0x0C,0x02,0x51,0x14,0x2D,0x8E,0xBD,0x16,0xE0,0xC1,0xDF,0x46,0x75,0xE7,0x24, + 0xAD,0xEC,0xF4,0x42,0xB4,0x85,0x93,0x70,0x10,0x67,0xBA,0x9D,0x06,0x35,0x4A,0x18, + 0xD3,0x2B,0x7A,0xCC,0x51,0x42,0xA1,0x7A,0x63,0xD1,0xE6,0xBB,0xA1,0xC5,0x2B,0xC2, + 0x36,0xBE,0x13,0x0D,0xE6,0xBD,0x63,0x7E,0x79,0x7B,0xA7,0x09,0x0D,0x40,0xAB,0x6A, + 0xDD,0x8F,0x8A,0xC3,0xF6,0xF6,0x8C,0x1A,0x42,0x05,0x51,0xD4,0x45,0xF5,0x9F,0xA7, + 0x62,0x21,0x68,0x15,0x20,0x43,0x3C,0x99,0xE7,0x7C,0xBD,0x24,0xD8,0xA9,0x91,0x17, + 0x73,0x88,0x3F,0x56,0x1B,0x31,0x38,0x18,0xB4,0x71,0x0F,0x9A,0xCD,0xC8,0x0E,0x9E, + 0x8E,0x2E,0x1B,0xE1,0x8C,0x98,0x83,0xCB,0x1F,0x31,0xF1,0x44,0x4C,0xC6,0x04,0x73, + 0x49,0x76,0x60,0x0F,0xC7,0xF8,0xBD,0x17,0x80,0x6B,0x2E,0xE9,0xCC,0x4C,0x0E,0x5A, + 0x9A,0x79,0x0F,0x20,0x0A,0x2E,0xD5,0x9E,0x63,0x26,0x1E,0x55,0x92,0x94,0xD8,0x82, + 0x17,0x5A,0x7B,0xD0,0xBC,0xC7,0x8F,0x4E,0x86,0x04, +}; + unsigned char __9639569_bin[] = { 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x02, 0x31, 0x82, 0x02, 0x60, @@ -2627,13 +2700,18 @@ static void tests(void) __9148843_txt, __9148843_txt_len, kCFAllocatorNull); ok_status(SecCMSVerifySignedData(sig, eml, policy, &trust, NULL, NULL, NULL), "validate message, not signer"); - // set date to Thu, 17 Mar 2011 00:59:48 +0000 + // SecCMS sets date to Thu, 17 Mar 2011 00:59:48 +0000 + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, __9148843_root, sizeof(__9148843_root)); + CFArrayRef anchor = CFArrayCreate(NULL, (const void **)&root, 1, &kCFTypeArrayCallBacks); + ok_status(SecTrustSetAnchorCertificates(trust, anchor)); ok_status(SecTrustEvaluate(trust, &result), "validate signer"); is_status(result, kSecTrustResultUnspecified, "valid"); CFReleaseNull(eml); CFReleaseNull(sig); CFReleaseNull(policy); CFReleaseNull(trust); + CFReleaseNull(root); + CFReleaseNull(anchor); CFDataRef msg = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, __9639569_bin, __9639569_bin_len, kCFAllocatorNull); CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0); diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist.c b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist.c deleted file mode 100644 index e263aff7..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2011-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@ - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "si-67-sectrust-blocklist/Global Trustee.cer.h" -#include "si-67-sectrust-blocklist/login.yahoo.com.1.cer.h" -#include "si-67-sectrust-blocklist/UTN-USERFirst-Hardware.cer.h" -#include "si-67-sectrust-blocklist/login.yahoo.com.2.cer.h" -#include "si-67-sectrust-blocklist/addons.mozilla.org.cer.h" -#include "si-67-sectrust-blocklist/login.yahoo.com.cer.h" -#include "si-67-sectrust-blocklist/login.live.com.cer.h" -#include "si-67-sectrust-blocklist/mail.google.com.cer.h" -#include "si-67-sectrust-blocklist/login.skype.com.cer.h" -#include "si-67-sectrust-blocklist/www.google.com.cer.h" - -#include "shared_regressions.h" - -static void validate_one_cert(uint8_t *data, size_t len, int chain_length, SecTrustResultType trust_result) -{ - SecTrustRef trust; - SecCertificateRef cert; - SecPolicyRef policy = SecPolicyCreateSSL(false, NULL); - CFArrayRef certs; - - isnt(cert = SecCertificateCreateWithBytes(NULL, data, len), - NULL, "create cert"); - certs = CFArrayCreate(NULL, (const void **)&cert, 1, NULL); - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "create trust with single cert"); - //CFDateRef date = CFDateCreate(NULL, 1301008576); - //ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - //CFRelease(date); - - SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is(SecTrustGetCertificateCount(trust), chain_length, "cert count"); - is_status(trustResult, trust_result, "correct trustResult"); - CFRelease(trust); - CFRelease(policy); - CFRelease(certs); - CFRelease(cert); -} - -static void tests(void) -{ - validate_one_cert(Global_Trustee_cer, sizeof(Global_Trustee_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_yahoo_com_1_cer, sizeof(login_yahoo_com_1_cer), 2, kSecTrustResultFatalTrustFailure); - /* this is the root, which isn't ok for ssl and fails here, but at the - same time it proves that kSecTrustResultFatalTrustFailure isn't - returned for policy failures that aren't blocklisting */ - validate_one_cert(login_yahoo_com_2_cer, sizeof(login_yahoo_com_2_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(addons_mozilla_org_cer, sizeof(addons_mozilla_org_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_yahoo_com_cer, sizeof(login_yahoo_com_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_live_com_cer, sizeof(login_live_com_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(mail_google_com_cer, sizeof(mail_google_com_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_skype_com_cer, sizeof(login_skype_com_cer), 2, kSecTrustResultFatalTrustFailure); - validate_one_cert(www_google_com_cer, sizeof(www_google_com_cer), 2, kSecTrustResultFatalTrustFailure); -} - -static int ping_host(char *host_name){ - - struct sockaddr_in pin; - struct hostent *nlp_host; - int sd; - int port; - int retries = 5; - - port=80; - - while ((nlp_host=gethostbyname(host_name))==0 && retries--){ - printf("Resolve Error! (%s) %d\n", host_name, h_errno); - sleep(1); - } - - if(nlp_host==0) - return 0; - - bzero(&pin,sizeof(pin)); - pin.sin_family=AF_INET; - pin.sin_addr.s_addr=htonl(INADDR_ANY); - pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr; - pin.sin_port=htons(port); - - sd=socket(AF_INET,SOCK_STREAM,0); - - if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){ - printf("connect error! (%s) %d\n", host_name, errno); - close(sd); - return 0; - } - else{ - close(sd); - return 1; - } -} - -int si_67_sectrust_blocklist(int argc, char *const *argv) -{ - char *hosts[] = { - "EVSecure-ocsp.verisign.com", - "EVIntl-ocsp.verisign.com", - "EVIntl-aia.verisign.com", - "ocsp.comodoca.com", - "crt.comodoca.com", - }; - - unsigned host_cnt = 0; - - plan_tests(45); - - for (host_cnt = 0; host_cnt < sizeof(hosts)/sizeof(hosts[0]); host_cnt ++) - if(ping_host(hosts[host_cnt]) == 0){ - printf("Accessing specific server (%s) failed, check the network!\n", hosts[host_cnt]); - return 0; - } - - tests(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/Global Trustee.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/Global Trustee.cer.h deleted file mode 100644 index 4253e078..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/Global Trustee.cer.h +++ /dev/null @@ -1,150 +0,0 @@ -unsigned char Global_Trustee_cer[] = { - 0x30, 0x82, 0x06, 0xdd, 0x30, 0x82, 0x05, 0xc5, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xd8, 0xf3, 0x5f, 0x4e, 0xb7, 0x87, 0x2b, 0x2d, - 0xab, 0x06, 0x92, 0xe3, 0x15, 0x38, 0x2f, 0xb0, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xe3, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x0e, 0x30, 0x0c, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x05, 0x54, 0x61, 0x6d, 0x70, 0x61, 0x31, - 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, 0x53, 0x65, - 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, 0x31, 0x30, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x47, - 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, - 0x65, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0e, - 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, - 0x65, 0x65, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, - 0x1f, 0x48, 0x6f, 0x73, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, - 0x54, 0x49, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, - 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, - 0x6e, 0x75, 0x6d, 0x53, 0x53, 0x4c, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x0e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, - 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x30, 0x82, 0x02, 0x22, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, - 0x82, 0x02, 0x01, 0x00, 0xd9, 0x74, 0xf2, 0xaa, 0x41, 0x1d, 0xdf, 0xf5, - 0xc2, 0x16, 0x43, 0x49, 0x5c, 0x29, 0xbf, 0xb6, 0x89, 0x74, 0x29, 0xbc, - 0x9c, 0x8d, 0x0c, 0x46, 0x4f, 0x59, 0x7e, 0xb2, 0x41, 0x17, 0x66, 0x34, - 0x0c, 0x65, 0x89, 0xe1, 0x6c, 0x25, 0xe3, 0x86, 0x0a, 0x9e, 0x22, 0x45, - 0x22, 0x8c, 0xdd, 0x9d, 0xe6, 0xa3, 0x95, 0xde, 0xdc, 0x88, 0x02, 0x55, - 0x5c, 0xe3, 0x5b, 0x91, 0x75, 0xeb, 0x26, 0x69, 0x63, 0xb9, 0x2e, 0xc6, - 0xca, 0x2e, 0x27, 0xdf, 0x88, 0xba, 0x02, 0x20, 0x6e, 0xfe, 0xb9, 0x0b, - 0x29, 0xd7, 0xa7, 0xd6, 0xd7, 0x48, 0x1a, 0x1c, 0xce, 0xdd, 0x1f, 0xa9, - 0x27, 0x0e, 0x62, 0x4f, 0xa1, 0x96, 0x1e, 0xdd, 0x54, 0x3a, 0x34, 0x63, - 0x4a, 0x76, 0xf5, 0x77, 0x7d, 0x59, 0x67, 0xd8, 0x10, 0xd4, 0xb5, 0x0f, - 0x3a, 0x43, 0x22, 0x98, 0xdb, 0xf4, 0x09, 0xc4, 0x0a, 0x70, 0xce, 0xdd, - 0x90, 0xd4, 0x2f, 0xef, 0x74, 0x13, 0xc3, 0xcd, 0xc2, 0x89, 0x39, 0x62, - 0x15, 0x9d, 0xe6, 0x74, 0xa8, 0xe8, 0x9b, 0xf0, 0x63, 0x6e, 0x9c, 0x89, - 0xb6, 0x0e, 0xad, 0x9b, 0xf7, 0xcc, 0x82, 0xe8, 0xe8, 0x2d, 0xb8, 0x0b, - 0xda, 0x22, 0xec, 0x49, 0x85, 0x07, 0x88, 0x99, 0x98, 0x3f, 0xf4, 0x74, - 0xa9, 0x09, 0xf7, 0x81, 0x7c, 0x97, 0x0b, 0x59, 0x99, 0x18, 0x72, 0x8b, - 0xdb, 0x94, 0x82, 0x2b, 0xa7, 0xe8, 0xaa, 0x6b, 0x97, 0xbf, 0x88, 0x7e, - 0x75, 0xb0, 0x8b, 0x45, 0x45, 0x0c, 0xc7, 0xa8, 0x09, 0xea, 0x1b, 0x41, - 0x58, 0x30, 0x3b, 0x5f, 0x78, 0x65, 0x15, 0x34, 0xd2, 0xe4, 0x3c, 0x34, - 0x0d, 0x1d, 0xd8, 0x64, 0x3c, 0x8a, 0xa5, 0x56, 0x49, 0x99, 0x28, 0x2d, - 0x4b, 0xf2, 0xcf, 0xcd, 0xd9, 0x6e, 0x49, 0x64, 0x9b, 0xa9, 0x79, 0x90, - 0x77, 0x55, 0xa9, 0x08, 0x1b, 0xad, 0x1a, 0x74, 0x9e, 0xe0, 0x03, 0x93, - 0x0a, 0x09, 0xb7, 0xad, 0xa7, 0xb4, 0x5c, 0xef, 0x83, 0x6c, 0xb7, 0x9a, - 0xb4, 0xc6, 0x68, 0x40, 0x80, 0x1d, 0x42, 0xd1, 0x6e, 0x79, 0x9b, 0xa9, - 0x19, 0x21, 0x9a, 0x9c, 0xf9, 0x86, 0x2d, 0x00, 0xd1, 0x34, 0xfe, 0xe0, - 0xb6, 0xf9, 0x55, 0xb6, 0xf5, 0x26, 0xc5, 0x95, 0x16, 0xa5, 0x7c, 0x73, - 0x9f, 0x0a, 0x29, 0x89, 0xac, 0x3a, 0x98, 0xf7, 0x9b, 0x74, 0x67, 0xb7, - 0x90, 0xb7, 0x5d, 0x09, 0x23, 0x6a, 0x6a, 0xed, 0x2c, 0x10, 0xee, 0x53, - 0x0a, 0x10, 0xf0, 0x16, 0x1f, 0x57, 0xb3, 0xb1, 0x0d, 0x79, 0x91, 0x19, - 0xb0, 0xeb, 0xcd, 0x30, 0x3f, 0xa0, 0x14, 0x5f, 0xb3, 0xc6, 0xfd, 0x5c, - 0x33, 0xa7, 0xb0, 0xff, 0x98, 0xb0, 0x55, 0x8c, 0xb9, 0xa5, 0xf2, 0x6f, - 0x47, 0x24, 0x49, 0x21, 0x69, 0xcc, 0x42, 0xa2, 0x51, 0x00, 0x40, 0x85, - 0x8c, 0x82, 0x82, 0xab, 0x32, 0xa5, 0xcb, 0x9a, 0xdc, 0xd0, 0xd9, 0x18, - 0x0d, 0xdf, 0x19, 0xf4, 0xaf, 0x83, 0x0d, 0xc1, 0x3e, 0x31, 0xdb, 0x24, - 0x48, 0xb6, 0x75, 0x80, 0xa1, 0xe1, 0xc9, 0x77, 0x64, 0x1e, 0xa7, 0xe5, - 0x8b, 0x7f, 0x15, 0x4d, 0x4b, 0xa7, 0xc2, 0xd0, 0xed, 0x79, 0x95, 0x5e, - 0x91, 0x31, 0xec, 0x18, 0xff, 0x4e, 0x9f, 0x48, 0x14, 0xea, 0x75, 0xba, - 0x21, 0xce, 0x29, 0x76, 0xe9, 0x1f, 0x4e, 0x51, 0x87, 0x2e, 0xb3, 0xcc, - 0x04, 0x60, 0xba, 0x23, 0x1f, 0x1f, 0x65, 0xb2, 0x0a, 0xb8, 0xd5, 0x6e, - 0x8f, 0x4b, 0x42, 0x89, 0x47, 0xa9, 0x81, 0x90, 0x5b, 0x2b, 0xb2, 0xb6, - 0xae, 0xe6, 0xa0, 0x70, 0x7b, 0x78, 0x90, 0x0a, 0x7a, 0xc5, 0xe5, 0xe7, - 0xc5, 0xfb, 0x0a, 0xf6, 0x2f, 0x69, 0x8c, 0x8c, 0x1f, 0x57, 0xe0, 0x06, - 0x99, 0xff, 0x11, 0xd5, 0x52, 0x32, 0x20, 0x97, 0x27, 0x98, 0xee, 0x65, - 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xd4, 0x30, 0x82, 0x01, - 0xd0, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, - 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, 0x43, 0x95, 0x5d, - 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, 0x45, 0x30, 0x1d, - 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb7, 0xc3, 0xde, - 0x1a, 0x43, 0xed, 0x41, 0x97, 0xa9, 0x8f, 0x29, 0x78, 0x9c, 0x03, 0xb9, - 0xac, 0x40, 0x42, 0x00, 0xac, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, - 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c, 0x06, - 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, - 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, 0x03, 0x55, 0x1d, - 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, 0x2b, 0x06, 0x01, - 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, 0x30, 0x2b, 0x30, - 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, - 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63, - 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, 0x03, 0x55, 0x1d, - 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, 0xa0, 0x34, 0x86, - 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, - 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, - 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, - 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, 0x86, 0x30, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, - 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x55, 0x54, 0x4e, - 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, - 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, - 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, - 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, 0x64, 0x64, 0x54, - 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x41, - 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, - 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, - 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x19, 0x06, 0x03, 0x55, 0x1d, - 0x11, 0x04, 0x12, 0x30, 0x10, 0x82, 0x0e, 0x67, 0x6c, 0x6f, 0x62, 0x61, - 0x6c, 0x20, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, - 0x03, 0x82, 0x01, 0x01, 0x00, 0x8f, 0xba, 0x75, 0xba, 0x39, 0xd4, 0x26, - 0xd3, 0x70, 0x0f, 0xc4, 0xb3, 0x02, 0xa7, 0xc5, 0x12, 0x23, 0x71, 0xc9, - 0xfe, 0x63, 0xe9, 0xa3, 0x62, 0x78, 0x24, 0x44, 0x4f, 0xd4, 0xb9, 0x11, - 0x3e, 0x1f, 0xc7, 0x28, 0xe7, 0x55, 0x6b, 0xee, 0xf4, 0xe1, 0x00, 0x91, - 0x86, 0x8a, 0xc9, 0x09, 0x6b, 0x9f, 0x2e, 0xa4, 0x45, 0x39, 0xd1, 0x61, - 0x62, 0x5e, 0x93, 0xa5, 0x05, 0x45, 0x78, 0x9f, 0x60, 0x12, 0x2c, 0xf4, - 0x6c, 0x65, 0x65, 0x0d, 0xcc, 0x46, 0x34, 0x8b, 0x28, 0xba, 0xa0, 0xc6, - 0xf4, 0x99, 0x71, 0x64, 0xf3, 0x22, 0x76, 0xac, 0x4f, 0xf3, 0x62, 0xc9, - 0xa7, 0x33, 0x5a, 0x07, 0x1f, 0x3d, 0xc9, 0x86, 0x80, 0xdc, 0xdb, 0x04, - 0x2f, 0x87, 0x27, 0xe8, 0xbf, 0x48, 0x44, 0x81, 0xc0, 0xf0, 0x49, 0x23, - 0x6e, 0x1f, 0xe5, 0xe4, 0x03, 0x86, 0x24, 0x13, 0xa2, 0x85, 0x62, 0x7c, - 0x58, 0x04, 0xca, 0xe6, 0x8d, 0x13, 0x72, 0x0a, 0xba, 0x56, 0x44, 0xa2, - 0x0f, 0xbc, 0xfb, 0xa0, 0x3d, 0x0d, 0x2a, 0x7f, 0xfb, 0x9e, 0xa9, 0x09, - 0x3d, 0xb7, 0x5a, 0xd4, 0x8a, 0x8d, 0xe1, 0x25, 0xe8, 0xa4, 0x09, 0x84, - 0x70, 0xad, 0x12, 0x44, 0xb9, 0xcf, 0xb9, 0x33, 0x7a, 0xba, 0x5c, 0xe6, - 0x4b, 0xa6, 0xbb, 0x05, 0x06, 0x98, 0xff, 0xf2, 0x98, 0x52, 0x7b, 0x77, - 0x80, 0x27, 0x4a, 0xd9, 0xe2, 0xfa, 0xb9, 0x52, 0xd4, 0xfb, 0xfb, 0xe6, - 0xd6, 0x2d, 0x9e, 0x8f, 0xc1, 0x15, 0x44, 0x8d, 0x9b, 0x74, 0x2f, 0xee, - 0x94, 0x5a, 0x4e, 0xd3, 0xc4, 0x8b, 0x8a, 0xac, 0x43, 0x9d, 0x73, 0xf6, - 0xae, 0x0c, 0x87, 0x89, 0xad, 0x87, 0xc9, 0xc9, 0xc7, 0xdd, 0xba, 0x14, - 0x60, 0x7a, 0xf8, 0xb5, 0x35, 0x9d, 0xc2, 0x8d, 0xc6, 0x96, 0x81, 0x0d, - 0xa9, 0x52, 0x8a, 0x29, 0x40, 0x04, 0xe9, 0x19, 0xb4 -}; -unsigned int Global_Trustee_cer_len = 1761; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/UTN-USERFirst-Hardware.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/UTN-USERFirst-Hardware.cer.h deleted file mode 100644 index 320e0e37..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/UTN-USERFirst-Hardware.cer.h +++ /dev/null @@ -1,99 +0,0 @@ -unsigned char UTN_USERFirst_Hardware_cer[] = { - 0x30, 0x82, 0x04, 0x74, 0x30, 0x82, 0x03, 0x5c, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x10, 0x44, 0xbe, 0x0c, 0x8b, 0x50, 0x00, 0x24, 0xb4, 0x11, - 0xd3, 0x36, 0x2a, 0xfe, 0x65, 0x0a, 0xfd, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, - 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, - 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, - 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, - 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, - 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, - 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, 0x0d, - 0x39, 0x39, 0x30, 0x37, 0x30, 0x39, 0x31, 0x38, 0x31, 0x30, 0x34, 0x32, - 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x37, 0x30, 0x39, 0x31, 0x38, 0x31, - 0x39, 0x32, 0x32, 0x5a, 0x30, 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, - 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, - 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, - 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, - 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 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, 0xb1, - 0xf7, 0xc3, 0x38, 0x3f, 0xb4, 0xa8, 0x7f, 0xcf, 0x39, 0x82, 0x51, 0x67, - 0xd0, 0x6d, 0x9f, 0xd2, 0xff, 0x58, 0xf3, 0xe7, 0x9f, 0x2b, 0xec, 0x0d, - 0x89, 0x54, 0x99, 0xb9, 0x38, 0x99, 0x16, 0xf7, 0xe0, 0x21, 0x79, 0x48, - 0xc2, 0xbb, 0x61, 0x74, 0x12, 0x96, 0x1d, 0x3c, 0x6a, 0x72, 0xd5, 0x3c, - 0x10, 0x67, 0x3a, 0x39, 0xed, 0x2b, 0x13, 0xcd, 0x66, 0xeb, 0x95, 0x09, - 0x33, 0xa4, 0x6c, 0x97, 0xb1, 0xe8, 0xc6, 0xec, 0xc1, 0x75, 0x79, 0x9c, - 0x46, 0x5e, 0x8d, 0xab, 0xd0, 0x6a, 0xfd, 0xb9, 0x2a, 0x55, 0x17, 0x10, - 0x54, 0xb3, 0x19, 0xf0, 0x9a, 0xf6, 0xf1, 0xb1, 0x5d, 0xb6, 0xa7, 0x6d, - 0xfb, 0xe0, 0x71, 0x17, 0x6b, 0xa2, 0x88, 0xfb, 0x00, 0xdf, 0xfe, 0x1a, - 0x31, 0x77, 0x0c, 0x9a, 0x01, 0x7a, 0xb1, 0x32, 0xe3, 0x2b, 0x01, 0x07, - 0x38, 0x6e, 0xc3, 0xa5, 0x5e, 0x23, 0xbc, 0x45, 0x9b, 0x7b, 0x50, 0xc1, - 0xc9, 0x30, 0x8f, 0xdb, 0xe5, 0x2b, 0x7a, 0xd3, 0x5b, 0xfb, 0x33, 0x40, - 0x1e, 0xa0, 0xd5, 0x98, 0x17, 0xbc, 0x8b, 0x87, 0xc3, 0x89, 0xd3, 0x5d, - 0xa0, 0x8e, 0xb2, 0xaa, 0xaa, 0xf6, 0x8e, 0x69, 0x88, 0x06, 0xc5, 0xfa, - 0x89, 0x21, 0xf3, 0x08, 0x9d, 0x69, 0x2e, 0x09, 0x33, 0x9b, 0x29, 0x0d, - 0x46, 0x0f, 0x8c, 0xcc, 0x49, 0x34, 0xb0, 0x69, 0x51, 0xbd, 0xf9, 0x06, - 0xcd, 0x68, 0xad, 0x66, 0x4c, 0xbc, 0x3e, 0xac, 0x61, 0xbd, 0x0a, 0x88, - 0x0e, 0xc8, 0xdf, 0x3d, 0xee, 0x7c, 0x04, 0x4c, 0x9d, 0x0a, 0x5e, 0x6b, - 0x91, 0xd6, 0xee, 0xc7, 0xed, 0x28, 0x8d, 0xab, 0x4d, 0x87, 0x89, 0x73, - 0xd0, 0x6e, 0xa4, 0xd0, 0x1e, 0x16, 0x8b, 0x14, 0xe1, 0x76, 0x44, 0x03, - 0x7f, 0x63, 0xac, 0xe4, 0xcd, 0x49, 0x9c, 0xc5, 0x92, 0xf4, 0xab, 0x32, - 0xa1, 0x48, 0x5b, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xb9, 0x30, - 0x81, 0xb6, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, - 0x02, 0x01, 0xc6, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, - 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, - 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, - 0x28, 0x98, 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, - 0xd2, 0xc3, 0x45, 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, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, - 0x6c, 0x30, 0x31, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x2a, 0x30, 0x28, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x05, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x03, 0x06, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x03, 0x07, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, - 0x47, 0x19, 0x0f, 0xde, 0x74, 0xc6, 0x99, 0x97, 0xaf, 0xfc, 0xad, 0x28, - 0x5e, 0x75, 0x8e, 0xeb, 0x2d, 0x67, 0xee, 0x4e, 0x7b, 0x2b, 0xd7, 0x0c, - 0xff, 0xf6, 0xde, 0xcb, 0x55, 0xa2, 0x0a, 0xe1, 0x4c, 0x54, 0x65, 0x93, - 0x60, 0x6b, 0x9f, 0x12, 0x9c, 0xad, 0x5e, 0x83, 0x2c, 0xeb, 0x5a, 0xae, - 0xc0, 0xe4, 0x2d, 0xf4, 0x00, 0x63, 0x1d, 0xb8, 0xc0, 0x6c, 0xf2, 0xcf, - 0x49, 0xbb, 0x4d, 0x93, 0x6f, 0x06, 0xa6, 0x0a, 0x22, 0xb2, 0x49, 0x62, - 0x08, 0x4e, 0xff, 0xc8, 0xc8, 0x14, 0xb2, 0x88, 0x16, 0x5d, 0xe7, 0x01, - 0xe4, 0x12, 0x95, 0xe5, 0x45, 0x34, 0xb3, 0x8b, 0x69, 0xbd, 0xcf, 0xb4, - 0x85, 0x8f, 0x75, 0x51, 0x9e, 0x7d, 0x3a, 0x38, 0x3a, 0x14, 0x48, 0x12, - 0xc6, 0xfb, 0xa7, 0x3b, 0x1a, 0x8d, 0x0d, 0x82, 0x40, 0x07, 0xe8, 0x04, - 0x08, 0x90, 0xa1, 0x89, 0xcb, 0x19, 0x50, 0xdf, 0xca, 0x1c, 0x01, 0xbc, - 0x1d, 0x04, 0x19, 0x7b, 0x10, 0x76, 0x97, 0x3b, 0xee, 0x90, 0x90, 0xca, - 0xc4, 0x0e, 0x1f, 0x16, 0x6e, 0x75, 0xef, 0x33, 0xf8, 0xd3, 0x6f, 0x5b, - 0x1e, 0x96, 0xe3, 0xe0, 0x74, 0x77, 0x74, 0x7b, 0x8a, 0xa2, 0x6e, 0x2d, - 0xdd, 0x76, 0xd6, 0x39, 0x30, 0x82, 0xf0, 0xab, 0x9c, 0x52, 0xf2, 0x2a, - 0xc7, 0xaf, 0x49, 0x5e, 0x7e, 0xc7, 0x68, 0xe5, 0x82, 0x81, 0xc8, 0x6a, - 0x27, 0xf9, 0x27, 0x88, 0x2a, 0xd5, 0x58, 0x50, 0x95, 0x1f, 0xf0, 0x3b, - 0x1c, 0x57, 0xbb, 0x7d, 0x14, 0x39, 0x62, 0x2b, 0x9a, 0xc9, 0x94, 0x92, - 0x2a, 0xa3, 0x22, 0x0c, 0xff, 0x89, 0x26, 0x7d, 0x5f, 0x23, 0x2b, 0x47, - 0xd7, 0x15, 0x1d, 0xa9, 0x6a, 0x9e, 0x51, 0x0d, 0x2a, 0x51, 0x9e, 0x81, - 0xf9, 0xd4, 0x3b, 0x5e, 0x70, 0x12, 0x7f, 0x10, 0x32, 0x9c, 0x1e, 0xbb, - 0x9d, 0xf8, 0x66, 0xa8 -}; -unsigned int UTN_USERFirst_Hardware_cer_len = 1144; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/addons.mozilla.org.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/addons.mozilla.org.cer.h deleted file mode 100644 index ae288d3f..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/addons.mozilla.org.cer.h +++ /dev/null @@ -1,131 +0,0 @@ -unsigned char addons_mozilla_org_cer[] = { - 0x30, 0x82, 0x05, 0xf8, 0x30, 0x82, 0x04, 0xe0, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0x92, 0x39, 0xd5, 0x34, 0x8f, 0x40, 0xd1, 0x69, - 0x5a, 0x74, 0x54, 0x70, 0xe1, 0xf2, 0x3f, 0x43, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xe2, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, - 0x68, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, - 0x53, 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, - 0x31, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, - 0x65, 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, - 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, - 0x4c, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, - 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x2e, 0x6d, 0x6f, 0x7a, 0x69, 0x6c, - 0x6c, 0x61, 0x2e, 0x6f, 0x72, 0x67, 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, 0xab, 0xc6, 0x6d, 0x36, 0xf3, 0x15, 0x73, 0x78, 0x83, - 0x73, 0xce, 0x74, 0x85, 0xd5, 0xae, 0xec, 0xb2, 0xf0, 0xe0, 0x24, 0x1f, - 0x13, 0x83, 0xb8, 0x20, 0xac, 0xbb, 0x9a, 0xfe, 0x88, 0xbb, 0xab, 0xa1, - 0x1d, 0x0b, 0x1f, 0x45, 0x00, 0xaa, 0x49, 0xb7, 0x35, 0x37, 0x0c, 0x6a, - 0xef, 0x47, 0x4c, 0xb9, 0xd1, 0xbe, 0xe3, 0x57, 0x12, 0x04, 0x8d, 0x92, - 0xc7, 0xb6, 0xec, 0x01, 0xbc, 0xb6, 0xda, 0xc7, 0x81, 0x38, 0x20, 0xad, - 0x72, 0x85, 0xe6, 0x0e, 0xfc, 0x81, 0x6c, 0x07, 0xad, 0x68, 0x76, 0x38, - 0xc5, 0x44, 0xd7, 0xcc, 0xc6, 0x4a, 0xc5, 0x97, 0x3e, 0x64, 0xf4, 0x51, - 0xe6, 0xf0, 0x7e, 0xb2, 0xec, 0x56, 0xf7, 0x25, 0x82, 0x4d, 0x49, 0x98, - 0xcb, 0x16, 0x98, 0xdd, 0x23, 0xf1, 0x89, 0x91, 0xd1, 0x17, 0x97, 0x40, - 0x99, 0x26, 0xd6, 0xe2, 0xa2, 0x2b, 0x5e, 0xdf, 0xbd, 0x89, 0xf2, 0x1b, - 0x1a, 0x53, 0x2d, 0xcc, 0x50, 0x41, 0x7a, 0xd0, 0x3d, 0x2a, 0x0c, 0x55, - 0x70, 0x14, 0x01, 0xe9, 0x58, 0x49, 0x10, 0x7a, 0x0b, 0x93, 0x82, 0x8b, - 0xe1, 0x1e, 0xed, 0x3a, 0x80, 0x10, 0x82, 0xce, 0x96, 0x8a, 0x34, 0xf0, - 0xcc, 0xd7, 0xd3, 0xb9, 0xb4, 0x50, 0x87, 0x55, 0x54, 0x09, 0xb8, 0x9d, - 0x42, 0x28, 0x55, 0x00, 0xe5, 0x8c, 0x35, 0x54, 0xbf, 0xdd, 0x25, 0x91, - 0x46, 0xb7, 0x0d, 0xe5, 0x5d, 0x83, 0xa8, 0xe5, 0x8b, 0xfb, 0x84, 0xe4, - 0x3c, 0xae, 0x76, 0xda, 0xc4, 0x43, 0x2b, 0x5b, 0x74, 0x0b, 0xf8, 0xbe, - 0x5d, 0x68, 0xf1, 0x78, 0x5b, 0xb5, 0xce, 0x7d, 0xf1, 0x5d, 0x99, 0x40, - 0xda, 0xca, 0xee, 0x38, 0x81, 0x50, 0xbe, 0x98, 0xa1, 0x6c, 0xb8, 0x24, - 0xad, 0xf3, 0xaf, 0x8c, 0x0f, 0xd7, 0x11, 0x28, 0x2c, 0x84, 0x18, 0x4c, - 0x7d, 0xb5, 0xd9, 0x8f, 0x30, 0xb5, 0x1b, 0x02, 0x03, 0x01, 0x00, 0x01, - 0xa3, 0x82, 0x01, 0xf0, 0x30, 0x82, 0x01, 0xec, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, - 0x26, 0x1b, 0x28, 0x98, 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, - 0x9d, 0x4b, 0xd2, 0xc3, 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0xdd, 0x80, 0xd2, 0x54, 0x3d, 0xf7, 0x4c, 0x70, - 0xca, 0xa3, 0xb0, 0xdd, 0x34, 0x7a, 0x32, 0xe4, 0xe8, 0x3b, 0x5a, 0x3b, - 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, - 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, - 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, - 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, - 0x02, 0x30, 0x46, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, - 0x30, 0x3b, 0x06, 0x0c, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, - 0x02, 0x01, 0x03, 0x04, 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, - 0x73, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, - 0x53, 0x30, 0x7b, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, - 0x30, 0x38, 0xa0, 0x36, 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, - 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, - 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, - 0xa0, 0x34, 0xa0, 0x32, 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, - 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, - 0x6e, 0x65, 0x74, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, - 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x55, 0x54, 0x4e, 0x41, 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, - 0x24, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, - 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, - 0x6d, 0x30, 0x35, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x2e, 0x30, 0x2c, - 0x82, 0x12, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x2e, 0x6d, 0x6f, 0x7a, - 0x69, 0x6c, 0x6c, 0x61, 0x2e, 0x6f, 0x72, 0x67, 0x82, 0x16, 0x77, 0x77, - 0x77, 0x2e, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x2e, 0x6d, 0x6f, 0x7a, - 0x69, 0x6c, 0x6c, 0x61, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x01, 0x00, 0x33, 0x3b, 0x63, 0x15, 0xfc, 0xb1, 0xec, 0x14, - 0x2c, 0x93, 0xdd, 0x75, 0x94, 0xde, 0x81, 0x5a, 0xd9, 0x4e, 0x99, 0xbe, - 0xfb, 0x4a, 0xa4, 0x39, 0x55, 0x4d, 0xa1, 0x40, 0x7a, 0xde, 0x13, 0x2a, - 0x87, 0xa9, 0x37, 0xcf, 0xe8, 0xd5, 0xfb, 0xad, 0xd1, 0x7b, 0x6d, 0x6f, - 0x8c, 0x20, 0x87, 0x82, 0x54, 0xe6, 0x57, 0x49, 0xbc, 0x20, 0x28, 0x84, - 0xcd, 0xd6, 0x01, 0xd9, 0x93, 0x8b, 0x17, 0x6e, 0x23, 0x66, 0xe5, 0x84, - 0xc8, 0x80, 0x3f, 0xc6, 0xa1, 0x70, 0x80, 0xe4, 0xec, 0x4d, 0x1d, 0xf9, - 0xfc, 0x91, 0x5a, 0x73, 0x62, 0x29, 0x9a, 0xf7, 0x20, 0x1c, 0x61, 0xe0, - 0x8b, 0x39, 0x9f, 0xca, 0xbc, 0x7e, 0x8d, 0xdd, 0xbc, 0xd9, 0xb1, 0xe3, - 0x9f, 0x9e, 0xdf, 0x15, 0x53, 0x91, 0x21, 0x52, 0x0b, 0xd9, 0x1a, 0x23, - 0x0f, 0x66, 0x36, 0xdb, 0xac, 0x93, 0x96, 0x4a, 0xa3, 0xa5, 0x22, 0xcf, - 0x29, 0xf7, 0xa2, 0x99, 0xa8, 0xf6, 0xb6, 0xd9, 0x40, 0xae, 0xd9, 0x7e, - 0xb6, 0xf6, 0x58, 0x2e, 0x9b, 0xac, 0x36, 0xca, 0x64, 0x8f, 0x65, 0x52, - 0xdc, 0x86, 0x9c, 0x82, 0xab, 0x6e, 0x50, 0x4b, 0xda, 0x5f, 0xfa, 0x05, - 0x00, 0x88, 0x30, 0x0e, 0xde, 0x8d, 0x56, 0xbf, 0x81, 0x47, 0x8d, 0x3d, - 0x06, 0xe2, 0xb2, 0x62, 0x92, 0x67, 0x8f, 0x9e, 0xc8, 0x9a, 0xb2, 0xe5, - 0x06, 0xb8, 0x70, 0x24, 0xb8, 0x77, 0x7c, 0x23, 0x0a, 0x38, 0xc3, 0x79, - 0x08, 0xd8, 0xb1, 0x51, 0x9d, 0xac, 0x95, 0x11, 0xc7, 0x40, 0x17, 0x9e, - 0xa3, 0x1c, 0x8f, 0xf2, 0x11, 0xa7, 0x68, 0x27, 0xda, 0x49, 0x05, 0x84, - 0x18, 0x7c, 0x58, 0x2d, 0x01, 0x67, 0x5c, 0xe5, 0x9f, 0xa1, 0x29, 0xbb, - 0x4a, 0x39, 0x45, 0x2f, 0xbf, 0x11, 0xaa, 0x79, 0xa2, 0xed, 0xb4, 0xd4, - 0xb5, 0x65, 0x43, 0xb7, 0x93, 0x46, 0x8a, 0xd3 -}; -unsigned int addons_mozilla_org_cer_len = 1532; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.live.com.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.live.com.cer.h deleted file mode 100644 index fb39259f..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.live.com.cer.h +++ /dev/null @@ -1,130 +0,0 @@ -unsigned char login_live_com_cer[] = { - 0x30, 0x82, 0x05, 0xec, 0x30, 0x82, 0x04, 0xd4, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xb0, 0xb7, 0x13, 0x3e, 0xd0, 0x96, 0xf9, 0xb5, - 0x6f, 0xae, 0x91, 0xc8, 0x74, 0xbd, 0x3a, 0xc0, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xde, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, - 0x68, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, - 0x53, 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, - 0x31, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, - 0x65, 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, - 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, - 0x4c, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, - 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x6c, 0x69, 0x76, 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, 0xf3, - 0xfc, 0x2b, 0x2f, 0xef, 0xe1, 0xad, 0x59, 0xf0, 0x42, 0x3c, 0xc2, 0xf1, - 0x82, 0xbf, 0x2c, 0x41, 0x93, 0xd1, 0xf6, 0x98, 0x33, 0x95, 0x4c, 0xbc, - 0x62, 0xf1, 0x95, 0x58, 0x08, 0xb6, 0xe9, 0x7b, 0x77, 0x48, 0xb0, 0xd3, - 0xdc, 0x17, 0x3f, 0xbc, 0x6e, 0xe6, 0xec, 0x1e, 0xec, 0x8d, 0x17, 0xfe, - 0x1c, 0x24, 0xc6, 0x3e, 0x67, 0x3d, 0x92, 0x95, 0xa2, 0x30, 0xc0, 0xa7, - 0x57, 0x20, 0xcf, 0x70, 0x88, 0x97, 0x4a, 0x05, 0x93, 0x79, 0x93, 0x42, - 0x97, 0x2f, 0x3e, 0xff, 0xc4, 0x14, 0x14, 0x28, 0xa2, 0x13, 0x36, 0xb4, - 0xf8, 0xee, 0xbe, 0x1d, 0xbc, 0x78, 0x5d, 0x61, 0x93, 0x5f, 0xeb, 0x88, - 0xd7, 0xd1, 0xe4, 0x2b, 0x9a, 0xcd, 0x58, 0xe2, 0x07, 0x45, 0x9f, 0x4f, - 0xb8, 0xb9, 0x40, 0x6a, 0x33, 0x2c, 0x5b, 0x21, 0x03, 0x5a, 0x4a, 0x94, - 0xf2, 0x7a, 0x97, 0x59, 0x1b, 0xa8, 0xb5, 0x42, 0xd8, 0x83, 0x00, 0xaa, - 0x34, 0xcc, 0xa7, 0x76, 0xd0, 0x47, 0x03, 0x5f, 0x05, 0xaf, 0x3b, 0xe1, - 0xb9, 0xa1, 0x34, 0x25, 0xb7, 0x6c, 0x5f, 0x9a, 0x30, 0x84, 0x98, 0xc2, - 0xc2, 0xd7, 0xf2, 0xb8, 0x42, 0x4a, 0x10, 0x55, 0xbd, 0xfa, 0x53, 0x81, - 0x5d, 0x8d, 0x68, 0x66, 0x45, 0x2c, 0x52, 0x7e, 0xe5, 0xc4, 0x04, 0xc3, - 0x54, 0xe7, 0xc3, 0x39, 0xda, 0x7a, 0x4a, 0xc5, 0xb9, 0x98, 0x82, 0x20, - 0xe1, 0x2c, 0x60, 0x57, 0xbf, 0xba, 0xf2, 0x46, 0x00, 0xbc, 0x5f, 0x3a, - 0xdc, 0xe3, 0x33, 0x97, 0xf8, 0x4a, 0x98, 0xb9, 0xec, 0x33, 0x4f, 0x2d, - 0x60, 0x6c, 0x15, 0x92, 0xa6, 0x81, 0x4a, 0x0b, 0xe9, 0xec, 0x76, 0x70, - 0x34, 0x31, 0x17, 0x70, 0xe6, 0x70, 0x4b, 0x8e, 0x8b, 0xd3, 0x75, 0xcb, - 0x78, 0x49, 0xab, 0x66, 0x9b, 0x86, 0x9f, 0x8f, 0xa9, 0xc4, 0x01, 0xe8, - 0xca, 0x1b, 0xe7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xe8, - 0x30, 0x82, 0x01, 0xe4, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, - 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0xd4, 0x64, 0xf6, 0xa9, 0xe8, 0xa5, 0x7e, 0xd7, 0xbf, 0x63, 0x52, 0x03, - 0x83, 0x53, 0xdb, 0xc5, 0x41, 0x8d, 0xea, 0x80, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, - 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, - 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, - 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, - 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, - 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, - 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, - 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, - 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x2d, 0x06, - 0x03, 0x55, 0x1d, 0x11, 0x04, 0x26, 0x30, 0x24, 0x82, 0x0e, 0x6c, 0x6f, - 0x67, 0x69, 0x6e, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x82, 0x12, 0x77, 0x77, 0x77, 0x2e, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2e, - 0x6c, 0x69, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x01, 0x00, 0x54, 0xe3, 0xa4, 0x9a, 0x24, 0xd2, 0xf3, 0x1d, - 0x42, 0xad, 0x1b, 0xf0, 0x1e, 0xab, 0xfb, 0xda, 0xd5, 0xaa, 0xe9, 0xcf, - 0x5a, 0xb3, 0x1e, 0x57, 0x7b, 0x31, 0xf2, 0x6e, 0x57, 0x4b, 0x31, 0xaf, - 0x33, 0xbb, 0xb6, 0x0d, 0x15, 0xc7, 0x5e, 0x59, 0x01, 0xce, 0x44, 0xb5, - 0xb7, 0xbf, 0x09, 0xc9, 0xd5, 0xdc, 0x69, 0x84, 0xe9, 0xc5, 0x1a, 0xb7, - 0xf0, 0x3e, 0xd4, 0xc0, 0x24, 0xbd, 0x29, 0x5f, 0xb4, 0xe9, 0xd6, 0x58, - 0xeb, 0x45, 0x11, 0x89, 0x34, 0x34, 0xd3, 0x11, 0xeb, 0x34, 0xce, 0x2a, - 0x4f, 0x00, 0x3d, 0xf6, 0x72, 0xef, 0x69, 0x66, 0xc0, 0x9f, 0x9a, 0xac, - 0x7e, 0x70, 0x50, 0xac, 0x55, 0x47, 0xda, 0xbe, 0x43, 0x5b, 0xec, 0x8b, - 0xc8, 0xc5, 0x23, 0x84, 0xc9, 0x9f, 0xb6, 0x52, 0x08, 0xcf, 0x91, 0x1b, - 0x2f, 0x80, 0x69, 0xe6, 0x34, 0x33, 0xe6, 0xb3, 0x9f, 0xa4, 0xe5, 0x0d, - 0x9a, 0x15, 0xf9, 0x57, 0xfc, 0x0b, 0xa9, 0x41, 0x0b, 0xf5, 0xff, 0x58, - 0x41, 0x92, 0x22, 0x27, 0x66, 0x12, 0x06, 0xc7, 0x2a, 0xd8, 0x59, 0xa7, - 0xc6, 0xdf, 0x44, 0x12, 0x4f, 0xc0, 0xa8, 0x7f, 0xa7, 0x41, 0xc8, 0xc8, - 0x69, 0xff, 0xba, 0x05, 0x2e, 0x97, 0xad, 0x3b, 0xd0, 0xeb, 0xf3, 0x15, - 0x6d, 0x7e, 0x1b, 0xe5, 0xba, 0xdd, 0x34, 0xbe, 0x22, 0x11, 0xec, 0x68, - 0x98, 0x33, 0x81, 0x02, 0x6a, 0x0b, 0x13, 0x55, 0x79, 0x31, 0x75, 0x4e, - 0x3a, 0xc8, 0xb6, 0x13, 0xbd, 0x97, 0x6f, 0x37, 0x0a, 0x0b, 0x2d, 0x88, - 0x0e, 0xde, 0x67, 0x90, 0xc2, 0xb3, 0xca, 0x20, 0xca, 0x9a, 0x51, 0xf4, - 0x64, 0x3e, 0xdb, 0xf4, 0x2e, 0x45, 0xf2, 0xc7, 0x47, 0x17, 0xa8, 0xf4, - 0xfa, 0x90, 0x5a, 0x7f, 0x80, 0xa6, 0x82, 0xac, 0xe4, 0x6c, 0x81, 0x46, - 0xbb, 0x52, 0x85, 0x20, 0x24, 0xf8, 0x80, 0xea -}; -unsigned int login_live_com_cer_len = 1520; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.skype.com.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.skype.com.cer.h deleted file mode 100644 index 0ffd13ab..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.skype.com.cer.h +++ /dev/null @@ -1,130 +0,0 @@ -unsigned char login_skype_com_cer[] = { - 0x30, 0x82, 0x05, 0xef, 0x30, 0x82, 0x04, 0xd7, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xe9, 0x02, 0x8b, 0x95, 0x78, 0xe4, 0x15, 0xdc, - 0x1a, 0x71, 0x0a, 0x2b, 0x88, 0x15, 0x44, 0x47, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xdf, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, - 0x68, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, - 0x53, 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, - 0x31, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, - 0x65, 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, - 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, - 0x4c, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, - 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x73, 0x6b, 0x79, 0x70, 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, - 0xb0, 0x78, 0x99, 0x86, 0x0e, 0xa2, 0x73, 0x23, 0xd4, 0x5a, 0xc3, 0x49, - 0xeb, 0xb1, 0x36, 0x8c, 0x7c, 0xca, 0x84, 0xae, 0x3c, 0xaf, 0x38, 0x88, - 0x28, 0x99, 0x8d, 0x2d, 0x58, 0x13, 0xb1, 0x97, 0x78, 0x3e, 0x52, 0x20, - 0x67, 0xac, 0x5b, 0x73, 0x98, 0x6c, 0x32, 0x55, 0xc9, 0x70, 0xd1, 0xd9, - 0xaa, 0x15, 0xe8, 0x2e, 0x26, 0x85, 0x81, 0xbc, 0x56, 0xe4, 0xbc, 0x80, - 0x63, 0xdb, 0x4e, 0xd7, 0xf5, 0x02, 0xbe, 0x51, 0x63, 0x1e, 0x3c, 0xdb, - 0xdf, 0xd7, 0x00, 0x5d, 0x5a, 0xb9, 0xe5, 0x7b, 0x6a, 0xea, 0x38, 0x20, - 0xb2, 0x3b, 0xb6, 0xee, 0x75, 0x54, 0x84, 0xf9, 0xa6, 0xca, 0x38, 0x70, - 0xdd, 0xbf, 0xb0, 0xff, 0xa5, 0x85, 0x5d, 0xb4, 0x41, 0xfe, 0xdd, 0x3d, - 0xd9, 0x2a, 0xe1, 0x30, 0x43, 0x1a, 0x98, 0x79, 0x93, 0xa0, 0x5f, 0xe0, - 0x67, 0x6c, 0x95, 0xfa, 0x3e, 0x7a, 0xae, 0x71, 0x7b, 0xe3, 0x6d, 0x88, - 0x42, 0x3f, 0x25, 0xd4, 0xee, 0xbe, 0x68, 0x68, 0xac, 0xad, 0xac, 0x60, - 0xe0, 0x20, 0xa3, 0x39, 0x83, 0xb9, 0x5b, 0x28, 0xa3, 0x93, 0x6d, 0xa1, - 0xbd, 0x76, 0x0a, 0xe3, 0xeb, 0xae, 0x87, 0x27, 0x0e, 0x54, 0x8f, 0xb4, - 0x48, 0x0c, 0x9a, 0x54, 0xf4, 0x5d, 0x8e, 0x37, 0x50, 0xdc, 0x5e, 0xa4, - 0x8b, 0x6b, 0x4b, 0xdc, 0xa6, 0xf3, 0x34, 0xbe, 0x77, 0x59, 0x22, 0x88, - 0xff, 0x19, 0x2b, 0x6d, 0x76, 0x64, 0x73, 0xda, 0x0c, 0x87, 0x07, 0x2b, - 0x9a, 0x37, 0x3a, 0xd0, 0xe2, 0x8c, 0xf6, 0x36, 0x32, 0x6b, 0x9a, 0x79, - 0xcc, 0xd2, 0x3b, 0x93, 0x6f, 0x1a, 0x4d, 0x6c, 0xe6, 0xc1, 0x9d, 0x40, - 0xac, 0x2d, 0x74, 0xc3, 0xbe, 0xea, 0x5c, 0x73, 0x65, 0x01, 0x29, 0xb1, - 0x2a, 0xbf, 0x70, 0x59, 0xc1, 0xce, 0xc6, 0xc3, 0xa2, 0xc8, 0x45, 0x5f, - 0xba, 0x67, 0x3d, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, - 0xea, 0x30, 0x82, 0x01, 0xe6, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, - 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, - 0x98, 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, - 0xc3, 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, - 0x14, 0xd5, 0x8e, 0x5a, 0x51, 0x13, 0xb4, 0x29, 0x0d, 0x31, 0xb6, 0x1c, - 0x8d, 0x3e, 0x51, 0x51, 0x31, 0x0a, 0x33, 0xaa, 0x81, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, - 0xa0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, - 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, - 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, - 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, - 0x0c, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, - 0x04, 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, - 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, - 0x64, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, - 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, - 0x36, 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, - 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, - 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, - 0x32, 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, - 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, - 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, - 0x63, 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, - 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, - 0x41, 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, - 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x2f, - 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x28, 0x30, 0x26, 0x82, 0x0f, 0x6c, - 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x73, 0x6b, 0x79, 0x70, 0x65, 0x2e, 0x63, - 0x6f, 0x6d, 0x82, 0x13, 0x77, 0x77, 0x77, 0x2e, 0x6c, 0x6f, 0x67, 0x69, - 0x6e, 0x2e, 0x73, 0x6b, 0x79, 0x70, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x08, 0xf2, 0x81, 0x75, 0x91, - 0xbb, 0xce, 0x12, 0x04, 0x18, 0xc2, 0x4d, 0x5a, 0xfb, 0x46, 0x90, 0x0a, - 0x54, 0x44, 0xf4, 0xf2, 0xdd, 0x07, 0x81, 0xf0, 0x1f, 0xa6, 0x7a, 0x6f, - 0x9f, 0xcf, 0xb8, 0x0e, 0x2c, 0x4f, 0x9c, 0xc4, 0x9a, 0xf5, 0xa8, 0xf6, - 0xba, 0xa4, 0xc9, 0x7a, 0x5d, 0xb1, 0xe2, 0x5a, 0xca, 0x3c, 0xfa, 0x60, - 0xa8, 0x68, 0x3e, 0xcb, 0xba, 0x2d, 0xe2, 0xcd, 0xd6, 0xb6, 0xe4, 0x92, - 0x3c, 0x69, 0xad, 0x57, 0xea, 0xa8, 0x2f, 0x38, 0x10, 0x84, 0x72, 0xe5, - 0x68, 0x71, 0xed, 0xbe, 0xeb, 0x6e, 0x18, 0xef, 0x63, 0x7a, 0xbe, 0xe7, - 0x24, 0xff, 0xc0, 0x63, 0xfd, 0x58, 0x3b, 0x4c, 0x81, 0x92, 0xd8, 0x29, - 0xab, 0x8e, 0x35, 0x5d, 0xd7, 0xd3, 0x09, 0x6b, 0x85, 0xd3, 0xd5, 0x73, - 0x05, 0x44, 0xe2, 0xe5, 0xbb, 0x83, 0x53, 0x10, 0xcb, 0xf2, 0xcf, 0xb7, - 0x6e, 0xe1, 0x69, 0xb7, 0xa1, 0x92, 0x64, 0xc5, 0xcf, 0xcd, 0x82, 0xbb, - 0x36, 0xa0, 0x38, 0xad, 0xd7, 0x24, 0xdf, 0x53, 0xfc, 0x3f, 0x62, 0xb7, - 0xb7, 0xd5, 0xc7, 0x57, 0xe3, 0x93, 0x31, 0x70, 0x8e, 0x24, 0x89, 0x86, - 0xca, 0x63, 0x2b, 0x39, 0xba, 0x5d, 0xd9, 0x6a, 0x60, 0xec, 0xa1, 0x4e, - 0x8a, 0xfe, 0x53, 0xf8, 0x5e, 0x92, 0xdf, 0x2f, 0x5c, 0x26, 0x17, 0x6d, - 0x03, 0x7d, 0x02, 0x0f, 0x0f, 0xaa, 0x43, 0x67, 0x6d, 0xb0, 0x62, 0xbf, - 0x7e, 0x53, 0xdd, 0xcc, 0xec, 0x78, 0x73, 0x95, 0xe5, 0xa5, 0xf6, 0x00, - 0xa3, 0x04, 0xfd, 0x3f, 0x04, 0x2a, 0xb3, 0x98, 0xc5, 0xb7, 0x03, 0x1c, - 0xdb, 0xc9, 0x50, 0xab, 0xb0, 0x05, 0x1d, 0x1e, 0xbe, 0x56, 0xb4, 0xcf, - 0x3e, 0x42, 0x13, 0x94, 0x9e, 0xf9, 0xe7, 0x01, 0x81, 0xa5, 0x78, 0x6f, - 0x0c, 0x7a, 0x76, 0xac, 0x05, 0x86, 0xec, 0xac, 0xc2, 0x11, 0xac -}; -unsigned int login_skype_com_cer_len = 1523; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.1.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.1.cer.h deleted file mode 100644 index 5c1a3ee2..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.1.cer.h +++ /dev/null @@ -1,129 +0,0 @@ -unsigned char login_yahoo_com_1_cer[] = { - 0x30, 0x82, 0x05, 0xd9, 0x30, 0x82, 0x04, 0xc1, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x10, 0x39, 0x2a, 0x43, 0x4f, 0x0e, 0x07, 0xdf, 0x1f, 0x8a, - 0xa3, 0x05, 0xde, 0x34, 0xe0, 0xc2, 0x29, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, - 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, - 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, - 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, - 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, - 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, - 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, 0x35, - 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xdf, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, - 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, 0x37, - 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, 0x46, - 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, 0x53, - 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, 0x31, - 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, - 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, 0x65, - 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, 0x26, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, - 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, 0x4c, - 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x6c, - 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 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, 0xa1, - 0xa4, 0x05, 0x3d, 0xed, 0x85, 0x45, 0x93, 0x8a, 0x18, 0x4d, 0xc6, 0x03, - 0x00, 0x57, 0xe2, 0x40, 0x77, 0xf0, 0x1c, 0xeb, 0xd0, 0x19, 0xdf, 0x22, - 0x5d, 0x08, 0x7f, 0xd1, 0x07, 0x3c, 0x41, 0x89, 0x46, 0x17, 0xa3, 0x09, - 0xfa, 0xfc, 0xf8, 0xa9, 0x04, 0xd1, 0x96, 0x8f, 0xab, 0xd7, 0x4f, 0x3c, - 0xf9, 0xad, 0x18, 0xa9, 0x74, 0x81, 0xc4, 0x57, 0x0a, 0x3a, 0x26, 0x16, - 0xce, 0x62, 0x3e, 0xbc, 0x3f, 0x6c, 0x21, 0xee, 0x93, 0x8d, 0xcb, 0x0d, - 0xa0, 0x1f, 0x9a, 0x96, 0xd0, 0x8f, 0xad, 0xf5, 0x93, 0x93, 0x82, 0xee, - 0x72, 0x0c, 0xa1, 0x75, 0x15, 0xa3, 0x7b, 0x84, 0x56, 0xb8, 0xad, 0xff, - 0x52, 0x11, 0x71, 0x84, 0xbc, 0x3a, 0x30, 0x0b, 0x7e, 0x98, 0xa8, 0xe1, - 0xa8, 0x3f, 0x37, 0x52, 0xd0, 0xf1, 0x7c, 0x6f, 0x90, 0xd8, 0x45, 0x0a, - 0xac, 0x39, 0x72, 0x6a, 0x61, 0xd5, 0xbb, 0xc3, 0x8c, 0xf9, 0xc2, 0xcc, - 0xdf, 0xfd, 0x3a, 0x71, 0xb9, 0xaf, 0xbc, 0xdc, 0x3a, 0xdc, 0x0c, 0xb6, - 0xb1, 0xd2, 0xd1, 0x89, 0xbb, 0x41, 0xb6, 0xf2, 0xde, 0x57, 0xd5, 0x15, - 0xdf, 0xfc, 0xfd, 0xe2, 0x31, 0xc5, 0xdf, 0xca, 0xc1, 0xd8, 0x8f, 0x2c, - 0xbf, 0xf0, 0x0e, 0x5b, 0x71, 0xe0, 0x34, 0x71, 0xc3, 0xc5, 0x4d, 0x7d, - 0x7a, 0xd4, 0xfa, 0xed, 0x30, 0x4b, 0x2f, 0xea, 0xb6, 0x2e, 0x9e, 0x93, - 0x3c, 0xe2, 0x3a, 0xf8, 0x42, 0xa2, 0x1a, 0xee, 0xdc, 0xdf, 0xcd, 0x0f, - 0xa9, 0xf6, 0x79, 0x84, 0x1a, 0x8e, 0x6c, 0x02, 0xb6, 0x86, 0xe5, 0xbf, - 0x51, 0x6a, 0x66, 0xf8, 0xf3, 0x9c, 0xd3, 0x59, 0x0c, 0x7b, 0xa5, 0x99, - 0x78, 0xcd, 0x7c, 0x99, 0xfa, 0xc6, 0x96, 0x47, 0xd8, 0x32, 0xd4, 0x74, - 0x76, 0x0e, 0x77, 0x4b, 0x20, 0x74, 0xa4, 0xb7, 0x89, 0x75, 0x92, 0x4a, - 0xb4, 0x5b, 0x55, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xd5, - 0x30, 0x82, 0x01, 0xd1, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, - 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x86, 0x49, 0x45, 0xfc, 0x33, 0x19, 0x33, 0xd4, 0x04, 0xed, 0x27, 0x61, - 0xee, 0xe8, 0x01, 0xc9, 0x0c, 0x7f, 0x2f, 0x7e, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, - 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, - 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, - 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, - 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, - 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, - 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, - 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, - 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1a, 0x06, - 0x03, 0x55, 0x1d, 0x11, 0x04, 0x13, 0x30, 0x11, 0x82, 0x0f, 0x6c, 0x6f, - 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, 0x6f, - 0x6d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x57, 0x62, 0xe1, - 0x77, 0xeb, 0xfc, 0x1f, 0xbf, 0x88, 0x53, 0xaf, 0x58, 0xd3, 0xd4, 0xd6, - 0x6d, 0x67, 0x30, 0x17, 0x40, 0xbe, 0xe0, 0x1f, 0x64, 0xde, 0x87, 0x15, - 0xcc, 0xe0, 0xa4, 0x56, 0xa9, 0xd1, 0x9f, 0xf9, 0x01, 0xfe, 0x02, 0xb1, - 0xb1, 0xea, 0xe2, 0x5f, 0xee, 0x71, 0x16, 0x31, 0xf9, 0x08, 0xd5, 0xc2, - 0xd7, 0x9a, 0x9b, 0xb2, 0x5a, 0x38, 0xd7, 0xa9, 0x7f, 0xe9, 0x87, 0x6b, - 0x31, 0xf9, 0x0b, 0xac, 0xd9, 0xfd, 0x50, 0x71, 0xe0, 0xdb, 0x82, 0x92, - 0x0f, 0x81, 0x9c, 0x8d, 0x77, 0xe9, 0xeb, 0x2e, 0xea, 0xd4, 0x23, 0x41, - 0x87, 0xec, 0x2d, 0xb2, 0x78, 0xb3, 0x8e, 0xb1, 0x67, 0xd2, 0xee, 0x71, - 0x03, 0x08, 0x12, 0x99, 0xb3, 0x02, 0x29, 0x6f, 0xde, 0x8b, 0xde, 0xc1, - 0xa9, 0x03, 0x0a, 0x5a, 0x33, 0x1c, 0x3d, 0x11, 0x03, 0xc6, 0x48, 0x0c, - 0x98, 0x9c, 0x15, 0x2e, 0xd9, 0xa6, 0x85, 0x52, 0xe7, 0x05, 0x8a, 0xae, - 0x30, 0x23, 0xeb, 0xed, 0x28, 0x6c, 0x60, 0xe9, 0x2d, 0x7f, 0x8f, 0x47, - 0x8b, 0x2f, 0xd0, 0xdc, 0xe6, 0xbb, 0x0f, 0x7e, 0x5f, 0xf2, 0x48, 0x81, - 0x8e, 0x50, 0x04, 0x63, 0xb1, 0x51, 0x80, 0x75, 0x9a, 0xa9, 0xb6, 0x10, - 0x1c, 0x10, 0x5f, 0x6f, 0x18, 0x6f, 0xe0, 0x0e, 0x96, 0x45, 0xce, 0xee, - 0xf1, 0xb5, 0x20, 0xdb, 0xef, 0xda, 0x6e, 0xc8, 0x95, 0xe3, 0xf6, 0x45, - 0xfd, 0xca, 0xfc, 0xa5, 0x5f, 0x49, 0x6d, 0x06, 0x1e, 0xd2, 0xde, 0x61, - 0x3d, 0x15, 0x7d, 0x37, 0xe5, 0x1c, 0x35, 0x8e, 0x06, 0xc2, 0x6b, 0xf7, - 0xb4, 0xa8, 0x28, 0x2c, 0x31, 0xcb, 0xaa, 0xb4, 0xa7, 0x97, 0x4f, 0x9d, - 0x8a, 0xf6, 0xaf, 0x7e, 0x37, 0xb9, 0x7b, 0x3d, 0xdf, 0x92, 0x66, 0x8b, - 0x8f, 0x4e, 0x9d, 0xc6, 0x36, 0xe7, 0x5c, 0xa6, 0xab, 0x12, 0x0f, 0xd6, - 0xcf -}; -unsigned int login_yahoo_com_1_cer_len = 1501; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.2.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.2.cer.h deleted file mode 100644 index 107dd15a..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.2.cer.h +++ /dev/null @@ -1,129 +0,0 @@ -unsigned char login_yahoo_com_2_cer[] = { - 0x30, 0x82, 0x05, 0xd9, 0x30, 0x82, 0x04, 0xc1, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x10, 0x3e, 0x75, 0xce, 0xd4, 0x6b, 0x69, 0x30, 0x21, 0x21, - 0x88, 0x30, 0xae, 0x86, 0xa8, 0x2a, 0x71, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, - 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, - 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, - 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, - 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, - 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, - 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, 0x35, - 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xdf, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, - 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, 0x37, - 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, 0x46, - 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, 0x53, - 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, 0x31, - 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, - 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, 0x65, - 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, 0x26, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, - 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, 0x4c, - 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x6c, - 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 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, 0xa1, - 0xa4, 0x05, 0x3d, 0xed, 0x85, 0x45, 0x93, 0x8a, 0x18, 0x4d, 0xc6, 0x03, - 0x00, 0x57, 0xe2, 0x40, 0x77, 0xf0, 0x1c, 0xeb, 0xd0, 0x19, 0xdf, 0x22, - 0x5d, 0x08, 0x7f, 0xd1, 0x07, 0x3c, 0x41, 0x89, 0x46, 0x17, 0xa3, 0x09, - 0xfa, 0xfc, 0xf8, 0xa9, 0x04, 0xd1, 0x96, 0x8f, 0xab, 0xd7, 0x4f, 0x3c, - 0xf9, 0xad, 0x18, 0xa9, 0x74, 0x81, 0xc4, 0x57, 0x0a, 0x3a, 0x26, 0x16, - 0xce, 0x62, 0x3e, 0xbc, 0x3f, 0x6c, 0x21, 0xee, 0x93, 0x8d, 0xcb, 0x0d, - 0xa0, 0x1f, 0x9a, 0x96, 0xd0, 0x8f, 0xad, 0xf5, 0x93, 0x93, 0x82, 0xee, - 0x72, 0x0c, 0xa1, 0x75, 0x15, 0xa3, 0x7b, 0x84, 0x56, 0xb8, 0xad, 0xff, - 0x52, 0x11, 0x71, 0x84, 0xbc, 0x3a, 0x30, 0x0b, 0x7e, 0x98, 0xa8, 0xe1, - 0xa8, 0x3f, 0x37, 0x52, 0xd0, 0xf1, 0x7c, 0x6f, 0x90, 0xd8, 0x45, 0x0a, - 0xac, 0x39, 0x72, 0x6a, 0x61, 0xd5, 0xbb, 0xc3, 0x8c, 0xf9, 0xc2, 0xcc, - 0xdf, 0xfd, 0x3a, 0x71, 0xb9, 0xaf, 0xbc, 0xdc, 0x3a, 0xdc, 0x0c, 0xb6, - 0xb1, 0xd2, 0xd1, 0x89, 0xbb, 0x41, 0xb6, 0xf2, 0xde, 0x57, 0xd5, 0x15, - 0xdf, 0xfc, 0xfd, 0xe2, 0x31, 0xc5, 0xdf, 0xca, 0xc1, 0xd8, 0x8f, 0x2c, - 0xbf, 0xf0, 0x0e, 0x5b, 0x71, 0xe0, 0x34, 0x71, 0xc3, 0xc5, 0x4d, 0x7d, - 0x7a, 0xd4, 0xfa, 0xed, 0x30, 0x4b, 0x2f, 0xea, 0xb6, 0x2e, 0x9e, 0x93, - 0x3c, 0xe2, 0x3a, 0xf8, 0x42, 0xa2, 0x1a, 0xee, 0xdc, 0xdf, 0xcd, 0x0f, - 0xa9, 0xf6, 0x79, 0x84, 0x1a, 0x8e, 0x6c, 0x02, 0xb6, 0x86, 0xe5, 0xbf, - 0x51, 0x6a, 0x66, 0xf8, 0xf3, 0x9c, 0xd3, 0x59, 0x0c, 0x7b, 0xa5, 0x99, - 0x78, 0xcd, 0x7c, 0x99, 0xfa, 0xc6, 0x96, 0x47, 0xd8, 0x32, 0xd4, 0x74, - 0x76, 0x0e, 0x77, 0x4b, 0x20, 0x74, 0xa4, 0xb7, 0x89, 0x75, 0x92, 0x4a, - 0xb4, 0x5b, 0x55, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xd5, - 0x30, 0x82, 0x01, 0xd1, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, - 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x86, 0x49, 0x45, 0xfc, 0x33, 0x19, 0x33, 0xd4, 0x04, 0xed, 0x27, 0x61, - 0xee, 0xe8, 0x01, 0xc9, 0x0c, 0x7f, 0x2f, 0x7e, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, - 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, - 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, - 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, - 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, - 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, - 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, - 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, - 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1a, 0x06, - 0x03, 0x55, 0x1d, 0x11, 0x04, 0x13, 0x30, 0x11, 0x82, 0x0f, 0x6c, 0x6f, - 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, 0x6f, - 0x6d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x53, 0x69, 0x98, - 0x8e, 0x28, 0x4e, 0x9c, 0x2b, 0x5b, 0x1d, 0xcc, 0x6b, 0x77, 0x28, 0x3d, - 0xbb, 0xfa, 0xa5, 0x4e, 0x7e, 0x56, 0x29, 0xa4, 0xea, 0x10, 0xe2, 0xf4, - 0xe6, 0x2d, 0x06, 0xd1, 0x84, 0xdb, 0x23, 0xce, 0x97, 0xf3, 0x68, 0xb6, - 0x0f, 0x3a, 0xde, 0x15, 0x0b, 0x24, 0x1d, 0x91, 0xe3, 0x6c, 0x2e, 0x30, - 0xb7, 0xe9, 0x70, 0xb0, 0xc3, 0x46, 0x80, 0xf0, 0xd3, 0xb1, 0x51, 0xbf, - 0x4f, 0xd6, 0x78, 0xa0, 0xfc, 0xac, 0xc6, 0xcf, 0x31, 0x04, 0x63, 0xe2, - 0x34, 0x55, 0x05, 0x4a, 0x3d, 0xf6, 0x30, 0xba, 0xf3, 0x33, 0xe5, 0xba, - 0xd2, 0x96, 0xf3, 0xd5, 0xb1, 0xb6, 0x93, 0x89, 0x1a, 0xa4, 0x68, 0xbe, - 0x7e, 0xed, 0x63, 0xb4, 0x1a, 0x48, 0xc0, 0x53, 0xe4, 0xa3, 0xf0, 0x39, - 0x0c, 0x32, 0x92, 0xc7, 0x43, 0x0d, 0x1a, 0x71, 0xed, 0xd0, 0x46, 0x93, - 0xbf, 0x93, 0x62, 0x6c, 0x33, 0x4b, 0xcd, 0x36, 0x0d, 0x69, 0x5e, 0xbb, - 0x6c, 0x96, 0x99, 0x21, 0x69, 0xc4, 0x4b, 0x67, 0x72, 0xdb, 0x6c, 0x6a, - 0xb8, 0xf7, 0x68, 0xed, 0xc5, 0x8f, 0xad, 0x63, 0x65, 0x95, 0x0a, 0x4c, - 0xe0, 0xf9, 0x0f, 0x7e, 0x37, 0x3d, 0xaa, 0xd4, 0x93, 0xba, 0x67, 0x09, - 0xc3, 0xa5, 0xa4, 0x0d, 0x03, 0x5a, 0x6d, 0xd5, 0x0b, 0xfe, 0xf0, 0x40, - 0x14, 0xb4, 0xf6, 0xb8, 0x69, 0x7c, 0x6d, 0xc2, 0x32, 0x4b, 0x9f, 0xb5, - 0x1a, 0xe7, 0x46, 0xae, 0x4c, 0x5a, 0x2b, 0xaa, 0x7a, 0x5e, 0x90, 0x57, - 0x95, 0xfa, 0xdb, 0x66, 0x02, 0x20, 0x1e, 0x6a, 0x69, 0x66, 0x15, 0x9c, - 0xc2, 0xb6, 0xf5, 0xbc, 0x50, 0xb5, 0xfd, 0x45, 0xc7, 0x1f, 0x68, 0xb4, - 0x47, 0x59, 0xac, 0xc4, 0x1b, 0x28, 0x93, 0x4e, 0x52, 0x53, 0x12, 0x03, - 0x58, 0x4b, 0x71, 0x83, 0x9f, 0x66, 0xe6, 0xac, 0x79, 0x48, 0xfe, 0xfe, - 0x47 -}; -unsigned int login_yahoo_com_2_cer_len = 1501; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.cer.h deleted file mode 100644 index 4f5ba040..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/login.yahoo.com.cer.h +++ /dev/null @@ -1,130 +0,0 @@ -unsigned char login_yahoo_com_cer[] = { - 0x30, 0x82, 0x05, 0xef, 0x30, 0x82, 0x04, 0xd7, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xd7, 0x55, 0x8f, 0xda, 0xf5, 0xf1, 0x10, 0x5b, - 0xb2, 0x13, 0x28, 0x2b, 0x70, 0x77, 0x29, 0xa3, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xdf, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, - 0x68, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, - 0x53, 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, - 0x31, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, - 0x65, 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, - 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, - 0x4c, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, - 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 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, - 0xa1, 0xa4, 0x05, 0x3d, 0xed, 0x85, 0x45, 0x93, 0x8a, 0x18, 0x4d, 0xc6, - 0x03, 0x00, 0x57, 0xe2, 0x40, 0x77, 0xf0, 0x1c, 0xeb, 0xd0, 0x19, 0xdf, - 0x22, 0x5d, 0x08, 0x7f, 0xd1, 0x07, 0x3c, 0x41, 0x89, 0x46, 0x17, 0xa3, - 0x09, 0xfa, 0xfc, 0xf8, 0xa9, 0x04, 0xd1, 0x96, 0x8f, 0xab, 0xd7, 0x4f, - 0x3c, 0xf9, 0xad, 0x18, 0xa9, 0x74, 0x81, 0xc4, 0x57, 0x0a, 0x3a, 0x26, - 0x16, 0xce, 0x62, 0x3e, 0xbc, 0x3f, 0x6c, 0x21, 0xee, 0x93, 0x8d, 0xcb, - 0x0d, 0xa0, 0x1f, 0x9a, 0x96, 0xd0, 0x8f, 0xad, 0xf5, 0x93, 0x93, 0x82, - 0xee, 0x72, 0x0c, 0xa1, 0x75, 0x15, 0xa3, 0x7b, 0x84, 0x56, 0xb8, 0xad, - 0xff, 0x52, 0x11, 0x71, 0x84, 0xbc, 0x3a, 0x30, 0x0b, 0x7e, 0x98, 0xa8, - 0xe1, 0xa8, 0x3f, 0x37, 0x52, 0xd0, 0xf1, 0x7c, 0x6f, 0x90, 0xd8, 0x45, - 0x0a, 0xac, 0x39, 0x72, 0x6a, 0x61, 0xd5, 0xbb, 0xc3, 0x8c, 0xf9, 0xc2, - 0xcc, 0xdf, 0xfd, 0x3a, 0x71, 0xb9, 0xaf, 0xbc, 0xdc, 0x3a, 0xdc, 0x0c, - 0xb6, 0xb1, 0xd2, 0xd1, 0x89, 0xbb, 0x41, 0xb6, 0xf2, 0xde, 0x57, 0xd5, - 0x15, 0xdf, 0xfc, 0xfd, 0xe2, 0x31, 0xc5, 0xdf, 0xca, 0xc1, 0xd8, 0x8f, - 0x2c, 0xbf, 0xf0, 0x0e, 0x5b, 0x71, 0xe0, 0x34, 0x71, 0xc3, 0xc5, 0x4d, - 0x7d, 0x7a, 0xd4, 0xfa, 0xed, 0x30, 0x4b, 0x2f, 0xea, 0xb6, 0x2e, 0x9e, - 0x93, 0x3c, 0xe2, 0x3a, 0xf8, 0x42, 0xa2, 0x1a, 0xee, 0xdc, 0xdf, 0xcd, - 0x0f, 0xa9, 0xf6, 0x79, 0x84, 0x1a, 0x8e, 0x6c, 0x02, 0xb6, 0x86, 0xe5, - 0xbf, 0x51, 0x6a, 0x66, 0xf8, 0xf3, 0x9c, 0xd3, 0x59, 0x0c, 0x7b, 0xa5, - 0x99, 0x78, 0xcd, 0x7c, 0x99, 0xfa, 0xc6, 0x96, 0x47, 0xd8, 0x32, 0xd4, - 0x74, 0x76, 0x0e, 0x77, 0x4b, 0x20, 0x74, 0xa4, 0xb7, 0x89, 0x75, 0x92, - 0x4a, 0xb4, 0x5b, 0x55, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, - 0xea, 0x30, 0x82, 0x01, 0xe6, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, - 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, - 0x98, 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, - 0xc3, 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, - 0x14, 0x86, 0x49, 0x45, 0xfc, 0x33, 0x19, 0x33, 0xd4, 0x04, 0xed, 0x27, - 0x61, 0xee, 0xe8, 0x01, 0xc9, 0x0c, 0x7f, 0x2f, 0x7e, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, - 0xa0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, - 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, - 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, - 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, - 0x0c, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, - 0x04, 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, - 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, - 0x64, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, - 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, - 0x36, 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x63, 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, - 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, - 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, - 0x32, 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, - 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, - 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, - 0x63, 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, - 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, - 0x41, 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, - 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x2f, - 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x28, 0x30, 0x26, 0x82, 0x0f, 0x6c, - 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, - 0x6f, 0x6d, 0x82, 0x13, 0x77, 0x77, 0x77, 0x2e, 0x6c, 0x6f, 0x67, 0x69, - 0x6e, 0x2e, 0x79, 0x61, 0x68, 0x6f, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x3d, 0x57, 0xc9, 0x48, 0x24, - 0x5c, 0xee, 0x64, 0x81, 0xf5, 0xae, 0xbe, 0x55, 0x29, 0x16, 0xff, 0x2a, - 0x2f, 0x84, 0xed, 0xd9, 0xf8, 0xa3, 0x03, 0xc8, 0x30, 0x66, 0xbb, 0xc8, - 0xd4, 0x81, 0x2d, 0x21, 0xf7, 0x08, 0xf7, 0xac, 0x96, 0x42, 0x9a, 0x41, - 0x75, 0x7a, 0xba, 0x5d, 0x10, 0x23, 0xcb, 0x92, 0x42, 0x61, 0xfa, 0x8a, - 0xda, 0x6d, 0x65, 0x34, 0x19, 0xe5, 0xa9, 0xd6, 0x2d, 0x13, 0x78, 0xd7, - 0x81, 0x44, 0x92, 0xa9, 0x6e, 0x80, 0x63, 0x15, 0xcb, 0xfe, 0x35, 0x1f, - 0x02, 0xd1, 0x8a, 0x14, 0xb0, 0xa8, 0xcc, 0x94, 0x20, 0x3b, 0xa8, 0x1a, - 0xf0, 0x5d, 0x36, 0x50, 0xdb, 0x0d, 0xae, 0xe9, 0x64, 0xe4, 0xf6, 0x8d, - 0x69, 0x7d, 0x30, 0xc8, 0x14, 0x17, 0x00, 0x4a, 0xe5, 0xa6, 0x35, 0xfb, - 0x7d, 0x0d, 0x22, 0x9d, 0x79, 0x76, 0x52, 0x2c, 0xbc, 0x97, 0x06, 0x88, - 0x9a, 0x15, 0xf4, 0x73, 0xe6, 0xf1, 0xf5, 0x98, 0xa5, 0xcd, 0x07, 0x44, - 0x91, 0xb8, 0xa7, 0x68, 0x67, 0x45, 0xd2, 0x72, 0x11, 0x60, 0xe2, 0x71, - 0xb7, 0x50, 0x55, 0xe2, 0x8a, 0xa9, 0x0d, 0xd6, 0x92, 0xee, 0x04, 0x2a, - 0x8b, 0x30, 0xa0, 0xa2, 0x05, 0x46, 0x34, 0x6d, 0x92, 0xc6, 0x3b, 0xaa, - 0x4d, 0xa0, 0xd0, 0xab, 0x01, 0x19, 0x0a, 0x32, 0xb7, 0xe8, 0xe3, 0xcf, - 0xf1, 0xd2, 0x97, 0x49, 0x7b, 0xac, 0xa4, 0x97, 0xf7, 0xf0, 0x57, 0xae, - 0x63, 0x77, 0x9a, 0x7f, 0x96, 0xda, 0x4d, 0xfd, 0xbe, 0xdc, 0x07, 0x36, - 0xe3, 0x25, 0xbd, 0x89, 0x79, 0x8e, 0x29, 0x12, 0x13, 0x8b, 0x88, 0x07, - 0xfb, 0x6b, 0xdb, 0xa4, 0xcd, 0xb3, 0x2d, 0x27, 0xe9, 0xd4, 0xca, 0x60, - 0xd7, 0x85, 0x53, 0xfb, 0x74, 0xc6, 0x5c, 0x35, 0x8c, 0x70, 0x1f, 0xf9, - 0xb2, 0xb7, 0x92, 0x27, 0x20, 0xc7, 0x94, 0xd5, 0x67, 0x14, 0x30 -}; -unsigned int login_yahoo_com_cer_len = 1523; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/mail.google.com.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/mail.google.com.cer.h deleted file mode 100644 index 21f5c081..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/mail.google.com.cer.h +++ /dev/null @@ -1,130 +0,0 @@ -unsigned char mail_google_com_cer[] = { - 0x30, 0x82, 0x05, 0xee, 0x30, 0x82, 0x04, 0xd6, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x10, 0x04, 0x7e, 0xcb, 0xe9, 0xfc, 0xa5, 0x5f, 0x7b, 0xd0, - 0x9e, 0xae, 0x36, 0xe1, 0x0c, 0xae, 0x1e, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, - 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, - 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, - 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, - 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, - 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, - 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, 0x35, - 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xdf, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, 0x0c, - 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, 0x37, - 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, 0x46, - 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, 0x53, - 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, 0x31, - 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, - 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, 0x65, - 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, 0x26, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, - 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, 0x4c, - 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x6d, - 0x61, 0x69, 0x6c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 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, 0xb0, - 0x73, 0xf0, 0xf2, 0x04, 0xee, 0xc2, 0xa2, 0x46, 0xca, 0x34, 0x2a, 0xaa, - 0xbb, 0x60, 0x23, 0xd1, 0x11, 0x76, 0x1f, 0x1f, 0x3a, 0xd0, 0x65, 0x83, - 0x4e, 0x9a, 0x45, 0xa8, 0x43, 0x70, 0x85, 0x76, 0xf0, 0x1f, 0x87, 0x00, - 0x02, 0x1f, 0x6e, 0x3b, 0x17, 0x17, 0xc4, 0xb5, 0xe9, 0x19, 0x46, 0xa2, - 0x92, 0x25, 0x8d, 0x62, 0x2a, 0xb4, 0x63, 0x30, 0x1f, 0xb9, 0x85, 0xf8, - 0x35, 0xe1, 0x16, 0x5a, 0x76, 0x49, 0xcc, 0x50, 0x48, 0x53, 0x39, 0x59, - 0x89, 0xd6, 0x84, 0x02, 0xfb, 0x9a, 0xec, 0x1b, 0xc7, 0x51, 0xd5, 0x76, - 0x95, 0x90, 0xd4, 0x3a, 0x2a, 0xb8, 0xa6, 0xde, 0x02, 0x4d, 0x06, 0xfb, - 0xcd, 0xed, 0xa5, 0x46, 0x41, 0x5f, 0x55, 0x74, 0xe5, 0xec, 0x7e, 0x40, - 0xdc, 0x50, 0x9c, 0xb5, 0xe4, 0x35, 0x5d, 0x1e, 0x68, 0x20, 0xf8, 0xe9, - 0xde, 0xa3, 0x6a, 0x28, 0xbf, 0x41, 0xd2, 0xa1, 0xb3, 0xe2, 0x25, 0x8d, - 0x0c, 0x1b, 0xca, 0x3d, 0x93, 0x0c, 0x18, 0xae, 0xdf, 0xc5, 0xbc, 0xfd, - 0xbc, 0x82, 0xba, 0x68, 0x00, 0xd7, 0x16, 0x32, 0x71, 0x9f, 0x65, 0xb5, - 0x11, 0xda, 0x68, 0x59, 0xd0, 0xa6, 0x57, 0x64, 0x1b, 0xc9, 0xfe, 0x98, - 0xe5, 0xf5, 0xa5, 0x65, 0xea, 0xe1, 0xdb, 0xee, 0xf4, 0xb3, 0x9d, 0xb3, - 0x8e, 0xea, 0x87, 0xae, 0x16, 0xd2, 0x1e, 0xa0, 0x7c, 0x7c, 0x69, 0x3f, - 0x29, 0x16, 0x85, 0x01, 0x53, 0xa7, 0x6c, 0xf1, 0x60, 0xab, 0xdd, 0xa2, - 0xfc, 0x25, 0x47, 0xd4, 0x32, 0xd1, 0x12, 0xdd, 0xf7, 0x48, 0x12, 0xe0, - 0xfc, 0x9c, 0xa2, 0x77, 0x98, 0xe9, 0x89, 0x99, 0xb8, 0xf8, 0x38, 0xf1, - 0x8c, 0x06, 0xc2, 0x7a, 0x23, 0x36, 0x6d, 0x9b, 0x9d, 0xcd, 0x30, 0xc8, - 0xc7, 0x34, 0x17, 0x1e, 0xbb, 0x7d, 0x42, 0xc8, 0xab, 0xe7, 0x15, 0x16, - 0xf6, 0x73, 0xb5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xea, - 0x30, 0x82, 0x01, 0xe6, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, - 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x18, 0x2a, 0xa2, 0xc8, 0xd4, 0x7a, 0x3f, 0x7b, 0xad, 0x04, 0x8b, 0xbd, - 0x6f, 0x9e, 0x10, 0x46, 0x13, 0x78, 0x71, 0x9d, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, - 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, - 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, - 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, - 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, - 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, - 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, - 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, - 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x2f, 0x06, - 0x03, 0x55, 0x1d, 0x11, 0x04, 0x28, 0x30, 0x26, 0x82, 0x0f, 0x6d, 0x61, - 0x69, 0x6c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x82, 0x13, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x61, 0x69, 0x6c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x67, 0x06, 0x08, 0x0a, 0x27, 0xc5, - 0x93, 0x6e, 0x02, 0xf2, 0xde, 0x17, 0x3f, 0xd0, 0xd3, 0x1b, 0x7c, 0xff, - 0xb5, 0xcd, 0x7a, 0xc7, 0x77, 0xc7, 0xbe, 0xdf, 0x12, 0xca, 0x19, 0xde, - 0xb0, 0x13, 0x57, 0x0c, 0x03, 0x91, 0xc4, 0x79, 0x52, 0xcf, 0x7f, 0xb7, - 0x5e, 0x55, 0x20, 0x84, 0x49, 0xdd, 0xf5, 0xd0, 0x29, 0x2f, 0x0e, 0x04, - 0xda, 0x59, 0x9e, 0x0e, 0x13, 0x9f, 0xf4, 0xc0, 0x32, 0x9b, 0xff, 0xa1, - 0x11, 0x24, 0x2a, 0x97, 0xa3, 0xf2, 0x3f, 0x3d, 0x2a, 0x6b, 0xa8, 0xad, - 0x8c, 0x19, 0x75, 0x95, 0x0e, 0x1d, 0x25, 0xfd, 0x4f, 0xc4, 0x7a, 0x15, - 0xc3, 0x1d, 0xc7, 0x13, 0x40, 0xc8, 0x0d, 0xbe, 0x97, 0x60, 0x72, 0xa6, - 0xfe, 0x25, 0xbe, 0x8f, 0xec, 0xd5, 0xa6, 0x86, 0xc3, 0x21, 0x5c, 0x59, - 0x52, 0xd9, 0x6a, 0x0b, 0x5c, 0x9f, 0x4b, 0xde, 0xb5, 0xf9, 0xec, 0xe2, - 0xf4, 0xc5, 0xcc, 0x62, 0x53, 0x76, 0x89, 0x65, 0xe4, 0x29, 0xda, 0xb7, - 0xbf, 0x96, 0xe0, 0x60, 0x8d, 0x0d, 0xb7, 0x09, 0x55, 0xd6, 0x40, 0x55, - 0x1d, 0xc1, 0xf2, 0x96, 0x21, 0x75, 0xaf, 0x89, 0x86, 0x1f, 0x5d, 0x81, - 0x97, 0x29, 0x28, 0x1e, 0x29, 0xd7, 0x96, 0xc1, 0x20, 0x03, 0x32, 0x7b, - 0x00, 0x3b, 0x6a, 0x37, 0x17, 0x5a, 0xa3, 0xb3, 0x1a, 0x6f, 0x32, 0x3b, - 0x6e, 0xf1, 0xa3, 0x5d, 0xab, 0xab, 0xcc, 0x2a, 0xcb, 0x30, 0x0c, 0x1f, - 0x35, 0x23, 0x8b, 0x69, 0x44, 0x5c, 0xea, 0xac, 0x28, 0x60, 0xed, 0xab, - 0x6b, 0x63, 0x9e, 0xf6, 0x92, 0xbc, 0xbd, 0x9a, 0x5a, 0x26, 0x4c, 0xc5, - 0x98, 0xb8, 0x0e, 0x19, 0x3e, 0xfc, 0x05, 0x31, 0xe3, 0x16, 0xd9, 0xfd, - 0x90, 0x05, 0x03, 0x86, 0xc6, 0x57, 0x01, 0x1f, 0x7f, 0x78, 0xa0, 0xcf, - 0x33, 0x6a, 0xaa, 0x66, 0x6b, 0x22, 0xd0, 0xa7, 0x49, 0x23 -}; -unsigned int mail_google_com_cer_len = 1522; diff --git a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/www.google.com.cer.h b/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/www.google.com.cer.h deleted file mode 100644 index 0754b97f..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-67-sectrust-blocklist/www.google.com.cer.h +++ /dev/null @@ -1,129 +0,0 @@ -unsigned char www_google_com_cer[] = { - 0x30, 0x82, 0x05, 0xe4, 0x30, 0x82, 0x04, 0xcc, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xf5, 0xc8, 0x6a, 0xf3, 0x61, 0x62, 0xf1, 0x3a, - 0x64, 0xf5, 0x4f, 0x6d, 0xc9, 0x58, 0x7c, 0x06, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, - 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, - 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, - 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x31, 0x30, 0x33, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x31, 0x34, 0x32, 0x33, - 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x81, 0xde, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0e, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x04, 0x11, 0x13, 0x05, 0x33, 0x38, 0x34, 0x37, - 0x37, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, - 0x46, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, - 0x68, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x09, 0x13, 0x0e, - 0x53, 0x65, 0x61, 0x20, 0x56, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65, 0x20, - 0x31, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4c, 0x74, 0x64, 0x2e, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x54, - 0x65, 0x63, 0x68, 0x20, 0x44, 0x65, 0x70, 0x74, 0x2e, 0x31, 0x28, 0x30, - 0x26, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1f, 0x48, 0x6f, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x47, 0x54, 0x49, 0x20, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0b, 0x50, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x75, 0x6d, 0x53, 0x53, - 0x4c, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, - 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 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, 0xb0, - 0x73, 0xf0, 0xf2, 0x04, 0xee, 0xc2, 0xa2, 0x46, 0xca, 0x34, 0x2a, 0xaa, - 0xbb, 0x60, 0x23, 0xd1, 0x11, 0x76, 0x1f, 0x1f, 0x3a, 0xd0, 0x65, 0x83, - 0x4e, 0x9a, 0x45, 0xa8, 0x43, 0x70, 0x85, 0x76, 0xf0, 0x1f, 0x87, 0x00, - 0x02, 0x1f, 0x6e, 0x3b, 0x17, 0x17, 0xc4, 0xb5, 0xe9, 0x19, 0x46, 0xa2, - 0x92, 0x25, 0x8d, 0x62, 0x2a, 0xb4, 0x63, 0x30, 0x1f, 0xb9, 0x85, 0xf8, - 0x35, 0xe1, 0x16, 0x5a, 0x76, 0x49, 0xcc, 0x50, 0x48, 0x53, 0x39, 0x59, - 0x89, 0xd6, 0x84, 0x02, 0xfb, 0x9a, 0xec, 0x1b, 0xc7, 0x51, 0xd5, 0x76, - 0x95, 0x90, 0xd4, 0x3a, 0x2a, 0xb8, 0xa6, 0xde, 0x02, 0x4d, 0x06, 0xfb, - 0xcd, 0xed, 0xa5, 0x46, 0x41, 0x5f, 0x55, 0x74, 0xe5, 0xec, 0x7e, 0x40, - 0xdc, 0x50, 0x9c, 0xb5, 0xe4, 0x35, 0x5d, 0x1e, 0x68, 0x20, 0xf8, 0xe9, - 0xde, 0xa3, 0x6a, 0x28, 0xbf, 0x41, 0xd2, 0xa1, 0xb3, 0xe2, 0x25, 0x8d, - 0x0c, 0x1b, 0xca, 0x3d, 0x93, 0x0c, 0x18, 0xae, 0xdf, 0xc5, 0xbc, 0xfd, - 0xbc, 0x82, 0xba, 0x68, 0x00, 0xd7, 0x16, 0x32, 0x71, 0x9f, 0x65, 0xb5, - 0x11, 0xda, 0x68, 0x59, 0xd0, 0xa6, 0x57, 0x64, 0x1b, 0xc9, 0xfe, 0x98, - 0xe5, 0xf5, 0xa5, 0x65, 0xea, 0xe1, 0xdb, 0xee, 0xf4, 0xb3, 0x9d, 0xb3, - 0x8e, 0xea, 0x87, 0xae, 0x16, 0xd2, 0x1e, 0xa0, 0x7c, 0x7c, 0x69, 0x3f, - 0x29, 0x16, 0x85, 0x01, 0x53, 0xa7, 0x6c, 0xf1, 0x60, 0xab, 0xdd, 0xa2, - 0xfc, 0x25, 0x47, 0xd4, 0x32, 0xd1, 0x12, 0xdd, 0xf7, 0x48, 0x12, 0xe0, - 0xfc, 0x9c, 0xa2, 0x77, 0x98, 0xe9, 0x89, 0x99, 0xb8, 0xf8, 0x38, 0xf1, - 0x8c, 0x06, 0xc2, 0x7a, 0x23, 0x36, 0x6d, 0x9b, 0x9d, 0xcd, 0x30, 0xc8, - 0xc7, 0x34, 0x17, 0x1e, 0xbb, 0x7d, 0x42, 0xc8, 0xab, 0xe7, 0x15, 0x16, - 0xf6, 0x73, 0xb5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xe0, - 0x30, 0x82, 0x01, 0xdc, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, 0x9d, 0x4b, 0xd2, 0xc3, - 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x18, 0x2a, 0xa2, 0xc8, 0xd4, 0x7a, 0x3f, 0x7b, 0xad, 0x04, 0x8b, 0xbd, - 0x6f, 0x9e, 0x10, 0x46, 0x13, 0x78, 0x71, 0x9d, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, - 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, - 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, - 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0x06, 0x0c, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x01, 0x03, 0x04, - 0x30, 0x2b, 0x30, 0x29, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x02, 0x01, 0x16, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x30, 0x7b, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x74, 0x30, 0x72, 0x30, 0x38, 0xa0, 0x36, - 0xa0, 0x34, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, - 0x72, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, - 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, - 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x36, 0xa0, 0x34, 0xa0, 0x32, - 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x2f, - 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x71, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x65, 0x30, 0x63, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2f, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x6f, 0x64, - 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x41, - 0x64, 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x24, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x63, 0x6f, 0x6d, - 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x25, 0x06, - 0x03, 0x55, 0x1d, 0x11, 0x04, 0x1e, 0x30, 0x1c, 0x82, 0x0e, 0x77, 0x77, - 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x82, 0x0a, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x71, 0xc0, 0x99, 0x3f, - 0x5e, 0xf6, 0xbd, 0x33, 0xff, 0x9e, 0x16, 0xcb, 0xa8, 0xbf, 0xdd, 0x70, - 0xf9, 0xd2, 0x53, 0x3b, 0x36, 0xae, 0xc9, 0x17, 0xc8, 0xae, 0x5e, 0x4d, - 0xdd, 0x62, 0xf7, 0xb7, 0xd3, 0x3e, 0x77, 0xa3, 0xfe, 0xc0, 0x7b, 0x32, - 0xb5, 0xc9, 0x94, 0x05, 0x52, 0x50, 0xf2, 0x5f, 0x3d, 0x79, 0x84, 0x49, - 0x4f, 0x5d, 0x6c, 0xb0, 0xd7, 0x59, 0xbd, 0xd4, 0x6c, 0x88, 0xfa, 0xfc, - 0xc5, 0x65, 0x86, 0xeb, 0x28, 0x52, 0xa2, 0x42, 0xf6, 0x7c, 0xbc, 0x6a, - 0xc7, 0x07, 0x2e, 0x25, 0xd1, 0x90, 0x62, 0x20, 0xc6, 0x8d, 0x51, 0xc2, - 0x2c, 0x45, 0x39, 0x4e, 0x03, 0xda, 0xf7, 0x18, 0xe8, 0xcc, 0x0a, 0x3a, - 0xd9, 0x45, 0xd8, 0x6c, 0x6e, 0x34, 0x8b, 0x62, 0x9c, 0x4e, 0x15, 0xf9, - 0x43, 0xee, 0xe5, 0x97, 0xc0, 0x3f, 0xad, 0x35, 0x13, 0xc5, 0x2b, 0x06, - 0xc7, 0x41, 0xfd, 0xe2, 0xf7, 0x7e, 0x45, 0xad, 0x9b, 0xd1, 0xe1, 0x66, - 0xed, 0xf8, 0x7a, 0x4b, 0x94, 0x39, 0x7a, 0x2f, 0xeb, 0xe8, 0x3f, 0x43, - 0xd8, 0x35, 0xd6, 0x56, 0xfa, 0x74, 0xe7, 0x6d, 0xe6, 0xed, 0xac, 0x65, - 0x84, 0xfe, 0xd0, 0x4d, 0x06, 0x12, 0xde, 0xda, 0x59, 0x00, 0x3c, 0x09, - 0x5c, 0xcf, 0x88, 0x4b, 0xe8, 0x3d, 0xb4, 0x15, 0x21, 0x92, 0xcc, 0x6d, - 0xa6, 0x51, 0xe2, 0x8e, 0x97, 0xf1, 0xf4, 0x82, 0x46, 0xcb, 0xc4, 0x53, - 0x5e, 0xda, 0x5c, 0x9d, 0x65, 0x92, 0x01, 0x65, 0x89, 0x00, 0xe5, 0xb6, - 0x99, 0xff, 0x26, 0x40, 0xf1, 0x2f, 0x19, 0x31, 0x08, 0x1a, 0xb1, 0x67, - 0x55, 0x86, 0x0d, 0xae, 0x35, 0x33, 0x86, 0xbc, 0x97, 0x48, 0x92, 0xd7, - 0x96, 0x60, 0xf8, 0xce, 0xfc, 0x96, 0xeb, 0x87, 0xc4, 0x73, 0xcc, 0x94, - 0x9b, 0x58, 0x5b, 0xf3, 0x7a, 0xa4, 0x27, 0x13, 0xd6, 0x4f, 0xf4, 0x69 -}; -unsigned int www_google_com_cer_len = 1512; diff --git a/OSX/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c b/OSX/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c deleted file mode 100644 index 006dc95c..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c +++ /dev/null @@ -1,1007 +0,0 @@ -/* - * Copyright (c) 2013-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@ - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -static const UInt8 kSignedPList[] = { - 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, - 0x80, 0x02, 0x01, 0x01, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x36, 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, - 0xd1, 0x01, 0x02, 0x53, 0x66, 0x6f, 0x6f, 0x53, 0x62, 0x61, 0x72, 0x08, 0x0b, 0x0f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x80, 0x30, 0x82, 0x07, 0xab, 0x30, 0x82, 0x05, 0x93, 0xa0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x08, 0x04, 0x2e, 0x97, 0xbb, 0x62, 0x84, 0xd9, 0x1c, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, - 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, - 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, - 0x74, 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, 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, 0x33, 0x30, 0x36, 0x32, 0x35, 0x30, 0x30, 0x30, - 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x36, 0x32, 0x31, 0x30, 0x30, 0x30, 0x39, - 0x33, 0x38, 0x5a, 0x30, 0x59, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1a, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x4f, 0x53, 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, 0x82, - 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xad, - 0xef, 0x52, 0xc8, 0xda, 0x8e, 0x3c, 0xcc, 0x06, 0xcf, 0xfc, 0xed, 0xdb, 0x92, 0xb3, 0xa8, 0xe0, - 0x3b, 0x14, 0x40, 0x34, 0xad, 0x91, 0xf3, 0xbe, 0x1a, 0x00, 0xbb, 0x06, 0xa2, 0xd7, 0x24, 0x6f, - 0xd5, 0xd3, 0xdf, 0xd9, 0xff, 0x0b, 0x4d, 0x6d, 0xc5, 0xdd, 0x7a, 0x37, 0xfa, 0x08, 0x49, 0x0e, - 0x36, 0x5e, 0xab, 0x83, 0x8d, 0xeb, 0x83, 0x00, 0xf9, 0xaa, 0xe4, 0x88, 0x09, 0x87, 0x05, 0x6b, - 0x01, 0x6e, 0x49, 0x54, 0xa1, 0x3b, 0x5c, 0xfc, 0x2b, 0x0f, 0x1f, 0xa9, 0x7c, 0xc1, 0xc5, 0xe1, - 0x32, 0xd7, 0x86, 0x49, 0x80, 0x0f, 0xf8, 0xe3, 0x3b, 0xa3, 0x12, 0x06, 0x5d, 0xf4, 0x43, 0xc0, - 0xb2, 0xc7, 0xcf, 0xb4, 0x14, 0x2c, 0x50, 0x70, 0x57, 0xb9, 0xb2, 0xe7, 0x72, 0x9a, 0x9f, 0x45, - 0x0b, 0x0d, 0xe5, 0xab, 0x3e, 0x23, 0x91, 0xe0, 0x88, 0x84, 0x3a, 0xec, 0xaa, 0x80, 0xab, 0x37, - 0xa3, 0x0c, 0x63, 0x99, 0x1c, 0xde, 0x1b, 0x29, 0x95, 0x4b, 0xff, 0xcd, 0x92, 0x10, 0xa3, 0x50, - 0x93, 0x89, 0x4f, 0xdc, 0x30, 0x0d, 0x29, 0x2a, 0x80, 0x04, 0x32, 0xb3, 0xb9, 0xa7, 0x79, 0x5f, - 0x18, 0xce, 0xc1, 0x90, 0xe6, 0xd6, 0x0c, 0xeb, 0x91, 0x27, 0x6f, 0x17, 0xd2, 0x93, 0xda, 0xa1, - 0xa8, 0x3f, 0x20, 0xe9, 0xeb, 0x54, 0x37, 0xd7, 0x54, 0xfd, 0x44, 0xa2, 0x8d, 0xa4, 0x30, 0x6e, - 0xbf, 0xd0, 0xbd, 0xc4, 0x7d, 0x93, 0xeb, 0xf6, 0xfa, 0x1e, 0xc1, 0xd5, 0xee, 0xfe, 0xb7, 0x56, - 0x51, 0xb3, 0x0b, 0x3f, 0xf4, 0xb1, 0x77, 0x75, 0xaf, 0x10, 0x14, 0x98, 0x74, 0x41, 0x40, 0xdb, - 0xe4, 0x6b, 0x3f, 0x49, 0xce, 0xb8, 0x80, 0x20, 0x72, 0x92, 0xcb, 0x63, 0x63, 0x44, 0x4e, 0xe8, - 0xe4, 0xde, 0xe9, 0xc3, 0x0a, 0x75, 0xd8, 0xbf, 0xc5, 0x8e, 0xcb, 0xcf, 0xec, 0x65, 0x49, 0x56, - 0xa1, 0x9f, 0xb6, 0x39, 0x53, 0x69, 0xb4, 0x04, 0xe8, 0xd0, 0x28, 0xc6, 0x69, 0xde, 0xdb, 0x30, - 0xa7, 0xb0, 0xbf, 0x6f, 0xfe, 0x7b, 0x45, 0x87, 0x07, 0xf0, 0x85, 0x34, 0x71, 0xca, 0xe5, 0x07, - 0x61, 0xce, 0x53, 0xf3, 0xd6, 0x69, 0x70, 0x5a, 0x4b, 0x7e, 0xda, 0x9b, 0x77, 0x17, 0x65, 0x6c, - 0x4d, 0xd5, 0x59, 0x00, 0x6f, 0x47, 0x65, 0x30, 0x98, 0xd9, 0x7b, 0xa7, 0x51, 0x8b, 0x47, 0x7d, - 0x8f, 0x5a, 0x91, 0x72, 0xe4, 0x86, 0x4f, 0xb0, 0xb4, 0x12, 0x42, 0x55, 0x95, 0x59, 0xa3, 0xc6, - 0xdf, 0xba, 0x20, 0x0e, 0x5d, 0x0f, 0x6a, 0x6a, 0xc2, 0x08, 0x93, 0x9f, 0x0e, 0x8b, 0x61, 0x20, - 0x9e, 0x2b, 0x64, 0x26, 0x15, 0x52, 0x9b, 0xef, 0x34, 0x7c, 0x12, 0xa4, 0xe4, 0xf7, 0xfc, 0x9a, - 0xa6, 0xe6, 0xe9, 0x6f, 0xfc, 0xbb, 0x16, 0xc4, 0x0f, 0x0b, 0xac, 0x84, 0x9d, 0xc8, 0xe9, 0x98, - 0xe1, 0xf4, 0x35, 0xfb, 0x97, 0x63, 0x14, 0x6c, 0x15, 0x51, 0x51, 0x5b, 0xc8, 0x64, 0x25, 0x46, - 0x44, 0x6d, 0xbd, 0x17, 0xdd, 0x17, 0x4d, 0x34, 0x77, 0xa8, 0x6d, 0x4b, 0x97, 0x4b, 0x77, 0xf5, - 0x77, 0x07, 0x1b, 0x93, 0x18, 0xf3, 0x44, 0x4e, 0x79, 0xe2, 0xfc, 0x96, 0x76, 0x5e, 0x69, 0x85, - 0xf6, 0xb6, 0x97, 0xbb, 0xb0, 0x41, 0x1f, 0x03, 0x8b, 0xcb, 0xc0, 0xa9, 0x10, 0x67, 0x8f, 0x6f, - 0x67, 0xab, 0xb0, 0xbd, 0x1f, 0xc7, 0x11, 0xfd, 0xb8, 0x29, 0x47, 0x41, 0xd4, 0x34, 0x0f, 0x5b, - 0x9d, 0x64, 0xfb, 0x8f, 0x5f, 0x37, 0xd1, 0x9a, 0x4a, 0x2d, 0x62, 0xd1, 0x74, 0x2e, 0x6b, 0x7f, - 0xdf, 0xb3, 0xea, 0x5f, 0xfa, 0x63, 0xd4, 0x4f, 0xb3, 0x89, 0x76, 0x67, 0x36, 0x71, 0xcd, 0xaf, - 0xd7, 0x9c, 0x95, 0xa8, 0xce, 0xee, 0x29, 0x25, 0xb1, 0x2a, 0xac, 0x99, 0x10, 0x9b, 0x03, 0x02, - 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x49, 0x30, 0x82, 0x02, 0x45, 0x30, 0x1d, 0x06, 0x03, - 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xcd, 0xbf, 0x6f, 0x14, 0xff, 0x8b, 0xb7, 0xf7, 0x29, - 0xcd, 0xa4, 0x8c, 0xc1, 0xb1, 0x30, 0x92, 0x37, 0x8b, 0xd4, 0xef, 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, 0x35, 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, - 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xe3, 0x06, 0x03, - 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, 0x04, 0x82, 0x01, 0xd7, 0x30, 0x82, 0x01, 0xd3, 0x30, 0x82, - 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, - 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, - 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, - 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, - 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, - 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, - 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, - 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, - 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, - 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, - 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, - 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, - 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, - 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, - 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, - 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, - 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, - 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, - 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, - 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, - 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, - 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, - 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, - 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, - 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, - 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x29, 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, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, - 0x0d, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, - 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, - 0x03, 0x82, 0x02, 0x01, 0x00, 0xc3, 0xd1, 0x52, 0x94, 0x51, 0xa7, 0x6d, 0xe9, 0xf8, 0x1a, 0xba, - 0x15, 0x2c, 0x38, 0x6b, 0xd6, 0xba, 0xcf, 0x12, 0x20, 0x1d, 0x46, 0xef, 0x99, 0x48, 0x95, 0x9d, - 0x1e, 0x49, 0x1b, 0xe7, 0x95, 0xde, 0x73, 0x28, 0xc1, 0x90, 0xfe, 0xeb, 0x39, 0xe1, 0xa8, 0xa8, - 0x5c, 0x4e, 0x71, 0x03, 0x1b, 0x22, 0x37, 0x07, 0xed, 0x24, 0xa4, 0xee, 0x5d, 0x0a, 0xf8, 0x04, - 0xf8, 0xba, 0x34, 0x50, 0xc0, 0x49, 0xd7, 0xa4, 0x4f, 0xdd, 0x06, 0x81, 0x33, 0x3a, 0x69, 0x4e, - 0x43, 0x85, 0x15, 0xde, 0x05, 0x37, 0xf5, 0xb3, 0xd5, 0x68, 0x4c, 0x30, 0x6a, 0x52, 0x35, 0x6a, - 0xb0, 0x2b, 0x8e, 0xe1, 0xde, 0xa6, 0xd2, 0xfc, 0xe2, 0x9f, 0xdc, 0x95, 0x65, 0x13, 0x45, 0x91, - 0xc1, 0x7b, 0xff, 0x90, 0x6a, 0x4c, 0xd3, 0x20, 0x5c, 0x1b, 0x99, 0xea, 0x82, 0xec, 0xfd, 0x0b, - 0x89, 0x25, 0x6c, 0x31, 0x3d, 0xa8, 0x52, 0xba, 0x8e, 0xdf, 0x20, 0xcb, 0x5f, 0x00, 0xf8, 0x6b, - 0xf2, 0x63, 0x5d, 0x2a, 0x55, 0xc6, 0xee, 0x34, 0xa4, 0x86, 0xab, 0x47, 0x89, 0xcd, 0xb6, 0xaa, - 0xe0, 0x5c, 0x9a, 0x57, 0x7d, 0x3e, 0xaa, 0x8b, 0x74, 0xfc, 0x94, 0xc7, 0x9d, 0x0e, 0xa2, 0x92, - 0xa9, 0xc5, 0xdd, 0x71, 0x53, 0x54, 0x38, 0xb0, 0x22, 0x88, 0xdc, 0x46, 0xcd, 0x45, 0xc7, 0x33, - 0xc7, 0x2f, 0xed, 0x5f, 0x4d, 0x05, 0x9d, 0xba, 0x2e, 0xf7, 0xa4, 0xb5, 0xfa, 0x79, 0x11, 0x41, - 0xd1, 0x1b, 0x50, 0xab, 0xef, 0xdf, 0xa8, 0x5c, 0x28, 0xc7, 0x8e, 0x86, 0xa2, 0x85, 0x8a, 0x90, - 0xf4, 0xda, 0x71, 0x1f, 0xff, 0x7f, 0x02, 0x4c, 0x24, 0x95, 0x0d, 0x31, 0xa3, 0x8b, 0x62, 0xae, - 0x45, 0xe2, 0x44, 0x6c, 0x01, 0x1d, 0xdc, 0x67, 0xbe, 0xfb, 0x16, 0x4f, 0x4c, 0xf0, 0x81, 0xa8, - 0xbd, 0xe1, 0x29, 0x6f, 0x1c, 0xff, 0xa4, 0x82, 0x96, 0xa3, 0x67, 0xad, 0xa6, 0x99, 0xd6, 0x29, - 0x02, 0x7f, 0xfc, 0xe3, 0x8d, 0xe3, 0x0d, 0x17, 0x91, 0x84, 0xcf, 0x4b, 0x05, 0xdd, 0x29, 0x96, - 0xb4, 0x58, 0x56, 0x9b, 0x65, 0x17, 0xdd, 0x16, 0x1f, 0xf8, 0x59, 0x8d, 0xfb, 0xa0, 0xb0, 0xc7, - 0x0b, 0x74, 0x64, 0xef, 0x8c, 0xcb, 0xba, 0x10, 0x48, 0x37, 0x28, 0xc9, 0x7f, 0x17, 0xac, 0x5f, - 0x04, 0xa0, 0x50, 0x6d, 0x18, 0x5f, 0x23, 0xe3, 0x9c, 0xb6, 0xe0, 0x6c, 0xc0, 0xe1, 0x5e, 0xba, - 0x8f, 0x70, 0xf1, 0xca, 0xc5, 0x97, 0x95, 0xf7, 0x4c, 0xdd, 0x6c, 0x8c, 0xbb, 0x4d, 0x68, 0x18, - 0x59, 0xb3, 0x1b, 0x6f, 0x81, 0xe7, 0xd8, 0x44, 0xdc, 0x6e, 0x84, 0xce, 0x5b, 0x0c, 0x66, 0xef, - 0xc4, 0x72, 0x00, 0xf2, 0x5a, 0xef, 0x82, 0x63, 0x18, 0xf7, 0xd3, 0xb8, 0x25, 0xc4, 0x91, 0x80, - 0x04, 0x54, 0x61, 0x5b, 0xf5, 0xe2, 0xda, 0xfb, 0x1d, 0xd4, 0x19, 0x99, 0x18, 0xbd, 0x9a, 0x1e, - 0x96, 0xe9, 0x1c, 0xd5, 0xd0, 0x06, 0xf5, 0x37, 0x91, 0x3b, 0x4d, 0xa5, 0x2a, 0xda, 0x3c, 0xcd, - 0xa6, 0xda, 0x53, 0xb8, 0x4a, 0x1e, 0xb9, 0x51, 0xed, 0xc3, 0x47, 0xc6, 0xfa, 0xdc, 0x2e, 0xb3, - 0xdd, 0x63, 0x65, 0xba, 0x17, 0xdb, 0x65, 0x8b, 0x63, 0x77, 0x31, 0x6d, 0xd9, 0xb7, 0x18, 0x33, - 0x91, 0xa1, 0x1f, 0xed, 0x0d, 0x49, 0x7f, 0x29, 0xd6, 0xd4, 0xf6, 0x12, 0x0f, 0xb2, 0x0c, 0xc9, - 0x0f, 0x61, 0xb1, 0x48, 0x58, 0x52, 0xac, 0x80, 0x92, 0xb4, 0x2d, 0x4c, 0xa8, 0x94, 0xf6, 0x99, - 0xc8, 0xb7, 0x1a, 0x7f, 0x3a, 0x52, 0x49, 0x9f, 0x44, 0xff, 0x0d, 0x38, 0x27, 0x3f, 0xad, 0xf6, - 0xa4, 0x8f, 0xd9, 0x4b, 0x30, 0x6f, 0xe0, 0xb8, 0x20, 0x94, 0x82, 0x4c, 0x96, 0xea, 0x27, 0x28, - 0x61, 0x1a, 0x41, 0x6d, 0xd4, 0x30, 0x82, 0x07, 0xca, 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, - 0x01, 0x02, 0x02, 0x08, 0x4e, 0xa1, 0x31, 0xe7, 0xca, 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, - 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, - 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, - 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, 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, 0x33, 0x30, 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, - 0x33, 0x39, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x36, 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, - 0x39, 0x5a, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 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, - 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, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, - 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, - 0x0c, 0x6f, 0x45, 0xb4, 0x04, 0x59, 0x24, 0xcb, 0x70, 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, - 0x87, 0x61, 0xb3, 0xd3, 0xfc, 0xbe, 0xb6, 0x05, 0x3c, 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, - 0x87, 0x07, 0xcf, 0x20, 0xbe, 0xaa, 0xeb, 0x24, 0xc5, 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, - 0xea, 0xb4, 0x5d, 0x3b, 0x29, 0x6c, 0xba, 0x4d, 0x15, 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, - 0x0d, 0x1d, 0xf7, 0x66, 0x77, 0xa2, 0x96, 0x56, 0xed, 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, - 0x32, 0x9c, 0xa9, 0xfd, 0xbf, 0xb8, 0x34, 0x6f, 0x57, 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, - 0xe9, 0x0f, 0x3c, 0xed, 0x4f, 0x31, 0x87, 0x05, 0xa4, 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, - 0xca, 0xd3, 0xf9, 0xd6, 0xaa, 0xaa, 0x88, 0x57, 0x66, 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, - 0x3d, 0x1d, 0xbc, 0x82, 0x6e, 0x81, 0xe9, 0x19, 0xf5, 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, - 0x88, 0xba, 0x51, 0xe7, 0x3a, 0xa0, 0x77, 0x2d, 0xe6, 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, - 0xf8, 0xa7, 0x79, 0x51, 0x2d, 0xe6, 0xc2, 0xee, 0xd2, 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, - 0x37, 0x12, 0xeb, 0x63, 0x99, 0x3d, 0xf3, 0x21, 0xbe, 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, - 0x0c, 0x4b, 0x43, 0x0c, 0x05, 0x6a, 0x6b, 0x8f, 0x05, 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, - 0xa7, 0x75, 0x63, 0x85, 0xe3, 0xa5, 0x5c, 0xc0, 0xd6, 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, - 0x6b, 0x4e, 0x99, 0x74, 0x7d, 0xd2, 0x69, 0x9f, 0xa8, 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, - 0x7e, 0x4a, 0x7a, 0x8a, 0xeb, 0x7c, 0xcd, 0x43, 0x9e, 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, - 0xe7, 0xfb, 0xa0, 0x43, 0xb3, 0xd7, 0x15, 0x28, 0x8a, 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, - 0x1b, 0x37, 0x33, 0x76, 0xc4, 0x58, 0xb9, 0x2d, 0x89, 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, - 0xa6, 0x07, 0x79, 0x11, 0x7d, 0x26, 0xd2, 0x85, 0x22, 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, - 0x18, 0xf3, 0xaa, 0x05, 0xce, 0x87, 0x99, 0xde, 0x76, 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, - 0x51, 0xa0, 0xc9, 0x70, 0xfc, 0xb9, 0x22, 0xfe, 0xd2, 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, - 0x53, 0xfd, 0xa1, 0xe6, 0xff, 0x8e, 0xd6, 0xde, 0x9e, 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, - 0xb2, 0x34, 0x8a, 0x1d, 0xf7, 0x9e, 0xa0, 0xbb, 0xf4, 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, - 0x92, 0x0d, 0xc9, 0x94, 0x7f, 0x24, 0xb9, 0x9f, 0xda, 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, - 0x3a, 0x70, 0x63, 0x3b, 0x22, 0x42, 0x14, 0xd0, 0xf9, 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, - 0x41, 0x20, 0x0d, 0x7e, 0x70, 0xd7, 0x88, 0x36, 0xa2, 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, - 0x9c, 0x5f, 0x4d, 0x3e, 0x4f, 0x83, 0x79, 0x06, 0x73, 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, - 0xce, 0x93, 0x5c, 0x68, 0xbf, 0x5a, 0xe6, 0x4c, 0x23, 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, - 0x1b, 0x64, 0x39, 0x64, 0xb7, 0xd2, 0x1d, 0xd0, 0x2d, 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, - 0x38, 0xb3, 0xf9, 0x5a, 0xee, 0x0e, 0x1d, 0xb6, 0xf9, 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, - 0x1a, 0x4b, 0x5a, 0xaf, 0x62, 0xb5, 0xd3, 0xef, 0x37, 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, - 0xa6, 0x46, 0x7b, 0x38, 0x63, 0x62, 0x3c, 0x18, 0x7d, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, - 0x82, 0x02, 0x3c, 0x30, 0x82, 0x02, 0x38, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, - 0x04, 0x14, 0x35, 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, - 0x48, 0xe8, 0x8f, 0x61, 0xb6, 0x1c, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, - 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, - 0x30, 0x16, 0x80, 0x14, 0x35, 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, - 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, - 0x20, 0x04, 0x82, 0x01, 0xca, 0x30, 0x82, 0x01, 0xc6, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, - 0x01, 0x66, 0x00, 0x52, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, - 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, - 0x00, 0x73, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, - 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, - 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, - 0x00, 0x74, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, - 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, - 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, - 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, - 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, - 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, - 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, - 0x00, 0x72, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, - 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, - 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, - 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, - 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, - 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, - 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, - 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, - 0x00, 0x70, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, - 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, - 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x02, 0x01, 0x16, 0x29, 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, 0x30, - 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, - 0x02, 0x01, 0x00, 0x6f, 0x8a, 0xb7, 0x35, 0x73, 0x5a, 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, - 0x17, 0x52, 0x1c, 0x70, 0xf0, 0xe0, 0x53, 0xb4, 0x16, 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, - 0x0e, 0xa6, 0x17, 0x86, 0x52, 0xc6, 0x70, 0x73, 0xf3, 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, - 0x0b, 0x85, 0xc9, 0xb9, 0xcf, 0x15, 0x91, 0x05, 0x2e, 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, - 0xf7, 0xe2, 0xd7, 0xf4, 0x60, 0xd2, 0xfc, 0x1d, 0xbf, 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, - 0x92, 0xef, 0xa4, 0x05, 0x34, 0x97, 0x57, 0x97, 0x56, 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, - 0x0e, 0x77, 0x85, 0xf1, 0x37, 0xc6, 0x19, 0x8b, 0x23, 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, - 0x78, 0xc5, 0xe6, 0x77, 0xfe, 0x72, 0x5f, 0xb2, 0x2c, 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, - 0xd9, 0x78, 0x20, 0xae, 0xbd, 0x75, 0x61, 0x6a, 0xaa, 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, - 0x91, 0x5c, 0x0a, 0x85, 0xc9, 0x59, 0x7d, 0x4e, 0x89, 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, - 0x1e, 0x62, 0x1e, 0xb9, 0x62, 0x2c, 0x34, 0x49, 0x15, 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, - 0x01, 0xc0, 0xda, 0x48, 0x44, 0xd4, 0x8b, 0xd3, 0x17, 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, - 0xaa, 0x14, 0x22, 0xa1, 0x38, 0x09, 0x0b, 0xb7, 0x0c, 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, - 0x07, 0xb4, 0x1b, 0xb3, 0x4a, 0xab, 0xae, 0xf6, 0xe7, 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, - 0xf9, 0x30, 0x28, 0x61, 0x92, 0x52, 0x58, 0x10, 0x15, 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, - 0x67, 0xc4, 0xb4, 0xcf, 0xe6, 0xf9, 0x46, 0x68, 0xe2, 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, - 0x9a, 0x45, 0x70, 0x3c, 0xf2, 0xdf, 0x29, 0x20, 0x9e, 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, - 0x4b, 0xae, 0x1a, 0x2f, 0x53, 0x03, 0x9a, 0xfd, 0x68, 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, - 0x3c, 0x1b, 0x47, 0x43, 0x19, 0x81, 0x0e, 0x0a, 0xbb, 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, - 0xb7, 0x9c, 0xe1, 0xf9, 0xeb, 0x37, 0xb0, 0x11, 0x20, 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, - 0xaf, 0x63, 0xed, 0x6a, 0x63, 0x1f, 0x1e, 0x61, 0x62, 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, - 0xd7, 0xba, 0x4f, 0xf2, 0x61, 0x26, 0x29, 0x99, 0xea, 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, - 0x5c, 0xe7, 0x86, 0x1d, 0xef, 0xf4, 0x6f, 0x3b, 0x6c, 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, - 0x9d, 0x0f, 0xdc, 0xcc, 0x0e, 0x7b, 0xf8, 0xc4, 0xee, 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, - 0xc8, 0x18, 0x4d, 0xa1, 0xe4, 0x40, 0x2c, 0xe9, 0x13, 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, - 0x93, 0x66, 0x56, 0x35, 0x5c, 0xc1, 0x38, 0x7d, 0xa1, 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, - 0xb6, 0x37, 0x19, 0x61, 0x81, 0x40, 0xba, 0xd7, 0x07, 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, - 0x8a, 0x2b, 0x99, 0x5a, 0x17, 0x3f, 0x9f, 0xcf, 0x86, 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, - 0x2d, 0x52, 0xce, 0x87, 0x10, 0x0f, 0x25, 0xc2, 0x1e, 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, - 0xd1, 0x65, 0xa8, 0xb4, 0xf6, 0xa5, 0x71, 0xad, 0x45, 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, - 0x96, 0x5a, 0x5d, 0x69, 0xfa, 0xdb, 0x13, 0x39, 0xb8, 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, - 0x6d, 0x39, 0xff, 0x26, 0xce, 0x2c, 0xa8, 0x5a, 0x7e, 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, - 0x48, 0xd3, 0xf8, 0x00, 0x00, 0x31, 0x82, 0x03, 0x28, 0x30, 0x82, 0x03, 0x24, 0x02, 0x01, 0x01, - 0x30, 0x81, 0x91, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, - 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 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, 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, 0x02, 0x08, 0x04, 0x2e, 0x97, 0xbb, - 0x62, 0x84, 0xd9, 0x1c, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x01, 0x05, 0x00, 0xa0, 0x69, 0x30, 0x18, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x03, 0x31, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, - 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, - 0x31, 0x33, 0x30, 0x36, 0x32, 0x35, 0x30, 0x30, 0x33, 0x39, 0x33, 0x33, 0x5a, 0x30, 0x2f, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x40, 0xe5, - 0x7f, 0xba, 0xdb, 0xb7, 0xe8, 0x35, 0xa0, 0x59, 0xd4, 0xa0, 0x57, 0x5c, 0x60, 0x53, 0x98, 0x48, - 0xda, 0x3b, 0x79, 0xf4, 0x73, 0x63, 0xd7, 0x90, 0xf0, 0x10, 0x2b, 0x71, 0x6e, 0x36, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, - 0x00, 0x6a, 0x51, 0xe7, 0xdc, 0x34, 0x87, 0x3c, 0x45, 0xd1, 0xeb, 0x6d, 0x20, 0x26, 0xcd, 0x53, - 0x01, 0x82, 0x71, 0x25, 0x73, 0xce, 0xe3, 0x9f, 0xfb, 0xca, 0x4c, 0x89, 0x01, 0x96, 0x6a, 0x1c, - 0x02, 0x57, 0xb1, 0xd1, 0x99, 0x43, 0x29, 0x4e, 0xfc, 0xf3, 0x30, 0x9e, 0xbc, 0x7e, 0xc4, 0x04, - 0xa3, 0x5d, 0x1a, 0x3c, 0x54, 0xc2, 0xba, 0x38, 0xdc, 0x8d, 0x12, 0xaf, 0xb4, 0x12, 0xe4, 0xeb, - 0x8a, 0x03, 0xb0, 0xc7, 0xaa, 0x72, 0xf4, 0x8b, 0x87, 0xd0, 0x0e, 0xd7, 0x9f, 0x45, 0xcb, 0xa5, - 0x0f, 0x4c, 0x60, 0x2b, 0xe5, 0xf7, 0xe8, 0xf1, 0x0a, 0xc0, 0x29, 0x0f, 0xe0, 0xa7, 0x0a, 0xc0, - 0x4b, 0xd9, 0x16, 0x04, 0xde, 0x4d, 0xc1, 0x5c, 0xbd, 0xad, 0x84, 0xb3, 0x8e, 0x72, 0x7d, 0xcc, - 0x73, 0x77, 0xe9, 0xeb, 0x3a, 0x36, 0xbc, 0xbd, 0x58, 0x0b, 0x97, 0x12, 0xd2, 0x9c, 0x3b, 0xd1, - 0x32, 0x2d, 0xbd, 0xe7, 0x40, 0xc8, 0x4c, 0x82, 0xbb, 0xe4, 0x49, 0xbc, 0x64, 0x50, 0xe3, 0x8b, - 0xba, 0xa2, 0xac, 0x31, 0xdb, 0xcd, 0x57, 0x79, 0xeb, 0x91, 0x87, 0xc7, 0x52, 0x70, 0xfe, 0xaa, - 0xd0, 0x7d, 0xd2, 0x78, 0x48, 0x77, 0xbc, 0xd9, 0xa7, 0x2b, 0x01, 0x20, 0x36, 0xd0, 0x99, 0x61, - 0x90, 0xfc, 0xb2, 0x8a, 0xfd, 0x02, 0xad, 0x60, 0xb6, 0x89, 0x82, 0xca, 0x8a, 0xc3, 0x6f, 0xd7, - 0x91, 0xb1, 0x4c, 0x25, 0x6a, 0x00, 0x59, 0xaa, 0x2c, 0xa0, 0xfc, 0x8b, 0x54, 0x64, 0xbd, 0x04, - 0x46, 0x8f, 0x7c, 0x1d, 0x53, 0xd4, 0x57, 0x9c, 0x06, 0x1f, 0xd8, 0x8e, 0x8b, 0x79, 0x0a, 0xe6, - 0xf5, 0xf3, 0xab, 0x10, 0x8c, 0xe1, 0x65, 0xd7, 0x0f, 0xf1, 0x9f, 0xe3, 0xf7, 0xd1, 0xca, 0xb2, - 0x6d, 0xcb, 0x6b, 0x50, 0x94, 0x1f, 0x1f, 0x4d, 0x55, 0xd1, 0xcb, 0x99, 0x86, 0xfe, 0xa4, 0xe5, - 0x05, 0x6c, 0x09, 0x54, 0x3a, 0xc7, 0x1c, 0x6e, 0xa5, 0x9c, 0x49, 0x69, 0xbb, 0xc3, 0x24, 0x8c, - 0x94, 0xf6, 0x67, 0xbd, 0x7b, 0xe9, 0x71, 0x31, 0x14, 0xcf, 0xf3, 0xf4, 0xdc, 0xd9, 0xdf, 0x99, - 0x31, 0x3d, 0x6f, 0xda, 0xba, 0x7c, 0x62, 0xbd, 0x2c, 0x01, 0x2c, 0x03, 0xa5, 0xfb, 0x22, 0xac, - 0x55, 0x60, 0x89, 0xe4, 0xf2, 0xb4, 0xb7, 0xed, 0x18, 0x9d, 0xa5, 0xe9, 0x55, 0xe6, 0xef, 0xbb, - 0x79, 0xe6, 0xf9, 0xd0, 0xf0, 0x62, 0x71, 0x30, 0x12, 0xdf, 0xde, 0x15, 0x42, 0x46, 0x2c, 0x5a, - 0x81, 0x6f, 0x3c, 0x38, 0x7f, 0x75, 0x00, 0x95, 0x68, 0xea, 0x43, 0x1c, 0x6a, 0xf9, 0x81, 0xde, - 0xb5, 0x0c, 0x0e, 0x50, 0xb5, 0x67, 0x9a, 0xea, 0x37, 0x6d, 0x9d, 0xd3, 0xd0, 0x69, 0x89, 0x5c, - 0x51, 0x27, 0x37, 0x10, 0x6f, 0x6e, 0x13, 0xdb, 0xb8, 0xb8, 0xe9, 0xd0, 0x84, 0x12, 0xf2, 0x3d, - 0x71, 0xc9, 0x7c, 0xe6, 0x9a, 0x1c, 0x50, 0xee, 0x43, 0x25, 0xff, 0x0b, 0x31, 0x88, 0x5b, 0xfa, - 0xc9, 0x84, 0x31, 0xb8, 0x6f, 0x67, 0x37, 0x7f, 0xa5, 0x0c, 0xaf, 0x15, 0x2a, 0x15, 0x04, 0xbd, - 0x1c, 0x76, 0xcb, 0x34, 0xb2, 0x38, 0x77, 0x2f, 0x1a, 0x09, 0x8b, 0x01, 0x44, 0xf5, 0x5f, 0x47, - 0x40, 0x64, 0x2a, 0x21, 0x4a, 0x88, 0xa2, 0xdd, 0xe6, 0xc5, 0xc4, 0x9d, 0xfd, 0x7c, 0x3d, 0xe3, - 0x1a, 0x79, 0x30, 0x90, 0xda, 0x17, 0x4d, 0x92, 0x86, 0xe6, 0xf7, 0x19, 0x93, 0x58, 0x1f, 0x21, - 0x16, 0x60, 0x01, 0x6a, 0xbb, 0x69, 0xc4, 0xfd, 0x29, 0xfc, 0xac, 0x04, 0xcb, 0x97, 0x7b, 0x47, - 0x51, 0xf6, 0x29, 0xca, 0x48, 0x52, 0x02, 0xb6, 0x27, 0x1c, 0xf2, 0x96, 0x06, 0x48, 0x23, 0x9d, - 0xf6, 0x93, 0xda, 0x5d, 0x83, 0x61, 0x2b, 0xbd, 0x52, 0x0c, 0x4d, 0x89, 0xf3, 0x2f, 0xa2, 0x67, - 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const UInt8 kSignedManifestData[] = { - 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, - 0x80, 0x02, 0x01, 0x01, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x82, 0x01, 0xeb, 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, - 0x30, 0x30, 0xd8, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, - 0x0e, 0x0f, 0x10, 0x5d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x5d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x5f, - 0x10, 0x0f, 0x63, 0x65, 0x72, 0x74, 0x73, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x64, 0x61, 0x74, - 0x61, 0x5d, 0x45, 0x56, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x5f, - 0x10, 0x14, 0x47, 0x72, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, - 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x10, 0x12, 0x41, 0x73, 0x73, 0x65, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x10, 0x0f, 0x63, 0x65, - 0x72, 0x74, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x10, 0x19, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x45, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x77, 0xfc, 0xe6, 0x2c, 0x4f, 0x10, - 0x20, 0x08, 0x89, 0x3f, 0xe7, 0x83, 0xdf, 0x07, 0x61, 0xaf, 0x65, 0x58, 0x66, 0xce, 0x74, 0xb5, - 0x46, 0x56, 0xc2, 0x03, 0x35, 0x4a, 0xd4, 0x88, 0xa7, 0x32, 0x6e, 0xdd, 0xcb, 0xb9, 0xb5, 0x21, - 0x6c, 0x4f, 0x10, 0x20, 0x2e, 0xa3, 0x40, 0x44, 0x60, 0xdb, 0x4f, 0x51, 0x3c, 0x06, 0x27, 0x4e, - 0x00, 0x7b, 0x25, 0x35, 0x13, 0x9a, 0x61, 0xc4, 0xa8, 0x0a, 0xaa, 0xcd, 0x70, 0xe7, 0x75, 0x7e, - 0x4d, 0x52, 0xbb, 0x24, 0x4f, 0x10, 0x20, 0x41, 0x11, 0x04, 0x71, 0xcb, 0x9b, 0xfb, 0xaf, 0xcf, - 0x6f, 0x1d, 0xee, 0x8e, 0x14, 0x3c, 0x1d, 0x39, 0x64, 0x68, 0xc8, 0x48, 0xb1, 0xee, 0x8a, 0xd1, - 0x05, 0x62, 0x40, 0x4f, 0x79, 0x22, 0x30, 0x4f, 0x10, 0x20, 0xa5, 0x0a, 0x89, 0x37, 0xf0, 0xa8, - 0x87, 0x2b, 0xcc, 0x33, 0xc1, 0x5a, 0xe6, 0xd3, 0x01, 0x43, 0x83, 0x50, 0x8d, 0x49, 0x84, 0x96, - 0x22, 0xaf, 0x3e, 0x26, 0x10, 0x78, 0x8a, 0x3a, 0x0c, 0x78, 0x4f, 0x10, 0x20, 0x6c, 0xcb, 0x07, - 0xc1, 0x68, 0x6f, 0xf9, 0xa3, 0x0c, 0x12, 0xd7, 0xb8, 0xe2, 0x51, 0x3d, 0xe2, 0xd5, 0x43, 0xeb, - 0xb5, 0x6d, 0x80, 0x6d, 0x8c, 0xca, 0x17, 0xd5, 0x31, 0x1a, 0x65, 0x48, 0x15, 0x4f, 0x10, 0x20, - 0xa6, 0x4c, 0x19, 0xd2, 0xb8, 0xe4, 0xbf, 0x59, 0x9a, 0x68, 0xe5, 0x34, 0x08, 0xc3, 0x61, 0x91, - 0xf9, 0x06, 0xf1, 0x16, 0x02, 0x1c, 0xfd, 0xaf, 0x46, 0xfb, 0xad, 0xc7, 0xb4, 0x57, 0x1d, 0x54, - 0x4f, 0x10, 0x20, 0x94, 0x47, 0xd4, 0x5d, 0xaf, 0x6a, 0x4f, 0xba, 0xc4, 0xe8, 0x6b, 0x10, 0x32, - 0x2a, 0x37, 0x90, 0x3c, 0x5a, 0x5b, 0x9f, 0x33, 0x48, 0x59, 0xd3, 0x1d, 0xf5, 0x57, 0x90, 0xde, - 0xb3, 0x5b, 0xf6, 0x00, 0x08, 0x00, 0x19, 0x00, 0x27, 0x00, 0x35, 0x00, 0x47, 0x00, 0x55, 0x00, - 0x6c, 0x00, 0x81, 0x00, 0x93, 0x00, 0xaf, 0x00, 0xb4, 0x00, 0xd7, 0x00, 0xfa, 0x01, 0x1d, 0x01, - 0x40, 0x01, 0x63, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x80, 0x30, 0x82, 0x07, - 0xab, 0x30, 0x82, 0x05, 0x93, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x04, 0x2e, 0x97, 0xbb, - 0x62, 0x84, 0xd9, 0x1c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x0b, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, - 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 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, 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, 0x33, - 0x30, 0x36, 0x32, 0x35, 0x30, 0x30, 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, - 0x36, 0x32, 0x31, 0x30, 0x30, 0x30, 0x39, 0x33, 0x38, 0x5a, 0x30, 0x59, 0x31, 0x23, 0x30, 0x21, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, - 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, - 0x67, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, 0x65, - 0x20, 0x4f, 0x53, 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, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, - 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xad, 0xef, 0x52, 0xc8, 0xda, 0x8e, 0x3c, 0xcc, 0x06, 0xcf, - 0xfc, 0xed, 0xdb, 0x92, 0xb3, 0xa8, 0xe0, 0x3b, 0x14, 0x40, 0x34, 0xad, 0x91, 0xf3, 0xbe, 0x1a, - 0x00, 0xbb, 0x06, 0xa2, 0xd7, 0x24, 0x6f, 0xd5, 0xd3, 0xdf, 0xd9, 0xff, 0x0b, 0x4d, 0x6d, 0xc5, - 0xdd, 0x7a, 0x37, 0xfa, 0x08, 0x49, 0x0e, 0x36, 0x5e, 0xab, 0x83, 0x8d, 0xeb, 0x83, 0x00, 0xf9, - 0xaa, 0xe4, 0x88, 0x09, 0x87, 0x05, 0x6b, 0x01, 0x6e, 0x49, 0x54, 0xa1, 0x3b, 0x5c, 0xfc, 0x2b, - 0x0f, 0x1f, 0xa9, 0x7c, 0xc1, 0xc5, 0xe1, 0x32, 0xd7, 0x86, 0x49, 0x80, 0x0f, 0xf8, 0xe3, 0x3b, - 0xa3, 0x12, 0x06, 0x5d, 0xf4, 0x43, 0xc0, 0xb2, 0xc7, 0xcf, 0xb4, 0x14, 0x2c, 0x50, 0x70, 0x57, - 0xb9, 0xb2, 0xe7, 0x72, 0x9a, 0x9f, 0x45, 0x0b, 0x0d, 0xe5, 0xab, 0x3e, 0x23, 0x91, 0xe0, 0x88, - 0x84, 0x3a, 0xec, 0xaa, 0x80, 0xab, 0x37, 0xa3, 0x0c, 0x63, 0x99, 0x1c, 0xde, 0x1b, 0x29, 0x95, - 0x4b, 0xff, 0xcd, 0x92, 0x10, 0xa3, 0x50, 0x93, 0x89, 0x4f, 0xdc, 0x30, 0x0d, 0x29, 0x2a, 0x80, - 0x04, 0x32, 0xb3, 0xb9, 0xa7, 0x79, 0x5f, 0x18, 0xce, 0xc1, 0x90, 0xe6, 0xd6, 0x0c, 0xeb, 0x91, - 0x27, 0x6f, 0x17, 0xd2, 0x93, 0xda, 0xa1, 0xa8, 0x3f, 0x20, 0xe9, 0xeb, 0x54, 0x37, 0xd7, 0x54, - 0xfd, 0x44, 0xa2, 0x8d, 0xa4, 0x30, 0x6e, 0xbf, 0xd0, 0xbd, 0xc4, 0x7d, 0x93, 0xeb, 0xf6, 0xfa, - 0x1e, 0xc1, 0xd5, 0xee, 0xfe, 0xb7, 0x56, 0x51, 0xb3, 0x0b, 0x3f, 0xf4, 0xb1, 0x77, 0x75, 0xaf, - 0x10, 0x14, 0x98, 0x74, 0x41, 0x40, 0xdb, 0xe4, 0x6b, 0x3f, 0x49, 0xce, 0xb8, 0x80, 0x20, 0x72, - 0x92, 0xcb, 0x63, 0x63, 0x44, 0x4e, 0xe8, 0xe4, 0xde, 0xe9, 0xc3, 0x0a, 0x75, 0xd8, 0xbf, 0xc5, - 0x8e, 0xcb, 0xcf, 0xec, 0x65, 0x49, 0x56, 0xa1, 0x9f, 0xb6, 0x39, 0x53, 0x69, 0xb4, 0x04, 0xe8, - 0xd0, 0x28, 0xc6, 0x69, 0xde, 0xdb, 0x30, 0xa7, 0xb0, 0xbf, 0x6f, 0xfe, 0x7b, 0x45, 0x87, 0x07, - 0xf0, 0x85, 0x34, 0x71, 0xca, 0xe5, 0x07, 0x61, 0xce, 0x53, 0xf3, 0xd6, 0x69, 0x70, 0x5a, 0x4b, - 0x7e, 0xda, 0x9b, 0x77, 0x17, 0x65, 0x6c, 0x4d, 0xd5, 0x59, 0x00, 0x6f, 0x47, 0x65, 0x30, 0x98, - 0xd9, 0x7b, 0xa7, 0x51, 0x8b, 0x47, 0x7d, 0x8f, 0x5a, 0x91, 0x72, 0xe4, 0x86, 0x4f, 0xb0, 0xb4, - 0x12, 0x42, 0x55, 0x95, 0x59, 0xa3, 0xc6, 0xdf, 0xba, 0x20, 0x0e, 0x5d, 0x0f, 0x6a, 0x6a, 0xc2, - 0x08, 0x93, 0x9f, 0x0e, 0x8b, 0x61, 0x20, 0x9e, 0x2b, 0x64, 0x26, 0x15, 0x52, 0x9b, 0xef, 0x34, - 0x7c, 0x12, 0xa4, 0xe4, 0xf7, 0xfc, 0x9a, 0xa6, 0xe6, 0xe9, 0x6f, 0xfc, 0xbb, 0x16, 0xc4, 0x0f, - 0x0b, 0xac, 0x84, 0x9d, 0xc8, 0xe9, 0x98, 0xe1, 0xf4, 0x35, 0xfb, 0x97, 0x63, 0x14, 0x6c, 0x15, - 0x51, 0x51, 0x5b, 0xc8, 0x64, 0x25, 0x46, 0x44, 0x6d, 0xbd, 0x17, 0xdd, 0x17, 0x4d, 0x34, 0x77, - 0xa8, 0x6d, 0x4b, 0x97, 0x4b, 0x77, 0xf5, 0x77, 0x07, 0x1b, 0x93, 0x18, 0xf3, 0x44, 0x4e, 0x79, - 0xe2, 0xfc, 0x96, 0x76, 0x5e, 0x69, 0x85, 0xf6, 0xb6, 0x97, 0xbb, 0xb0, 0x41, 0x1f, 0x03, 0x8b, - 0xcb, 0xc0, 0xa9, 0x10, 0x67, 0x8f, 0x6f, 0x67, 0xab, 0xb0, 0xbd, 0x1f, 0xc7, 0x11, 0xfd, 0xb8, - 0x29, 0x47, 0x41, 0xd4, 0x34, 0x0f, 0x5b, 0x9d, 0x64, 0xfb, 0x8f, 0x5f, 0x37, 0xd1, 0x9a, 0x4a, - 0x2d, 0x62, 0xd1, 0x74, 0x2e, 0x6b, 0x7f, 0xdf, 0xb3, 0xea, 0x5f, 0xfa, 0x63, 0xd4, 0x4f, 0xb3, - 0x89, 0x76, 0x67, 0x36, 0x71, 0xcd, 0xaf, 0xd7, 0x9c, 0x95, 0xa8, 0xce, 0xee, 0x29, 0x25, 0xb1, - 0x2a, 0xac, 0x99, 0x10, 0x9b, 0x03, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x49, 0x30, - 0x82, 0x02, 0x45, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xcd, 0xbf, - 0x6f, 0x14, 0xff, 0x8b, 0xb7, 0xf7, 0x29, 0xcd, 0xa4, 0x8c, 0xc1, 0xb1, 0x30, 0x92, 0x37, 0x8b, - 0xd4, 0xef, 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, 0x35, 0x07, 0x82, - 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, - 0x1c, 0x30, 0x82, 0x01, 0xe3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, 0x04, 0x82, 0x01, - 0xd7, 0x30, 0x82, 0x01, 0xd3, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x63, 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, - 0x00, 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, - 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, - 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, - 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, - 0x00, 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, - 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, - 0x00, 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, - 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, - 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, - 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, - 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, - 0x00, 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, - 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, - 0x00, 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, - 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, - 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, - 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, - 0x00, 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, - 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, - 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, - 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, - 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, - 0x00, 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, - 0x16, 0x29, 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, 0x30, 0x0b, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x0d, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, - 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0xc3, 0xd1, 0x52, 0x94, - 0x51, 0xa7, 0x6d, 0xe9, 0xf8, 0x1a, 0xba, 0x15, 0x2c, 0x38, 0x6b, 0xd6, 0xba, 0xcf, 0x12, 0x20, - 0x1d, 0x46, 0xef, 0x99, 0x48, 0x95, 0x9d, 0x1e, 0x49, 0x1b, 0xe7, 0x95, 0xde, 0x73, 0x28, 0xc1, - 0x90, 0xfe, 0xeb, 0x39, 0xe1, 0xa8, 0xa8, 0x5c, 0x4e, 0x71, 0x03, 0x1b, 0x22, 0x37, 0x07, 0xed, - 0x24, 0xa4, 0xee, 0x5d, 0x0a, 0xf8, 0x04, 0xf8, 0xba, 0x34, 0x50, 0xc0, 0x49, 0xd7, 0xa4, 0x4f, - 0xdd, 0x06, 0x81, 0x33, 0x3a, 0x69, 0x4e, 0x43, 0x85, 0x15, 0xde, 0x05, 0x37, 0xf5, 0xb3, 0xd5, - 0x68, 0x4c, 0x30, 0x6a, 0x52, 0x35, 0x6a, 0xb0, 0x2b, 0x8e, 0xe1, 0xde, 0xa6, 0xd2, 0xfc, 0xe2, - 0x9f, 0xdc, 0x95, 0x65, 0x13, 0x45, 0x91, 0xc1, 0x7b, 0xff, 0x90, 0x6a, 0x4c, 0xd3, 0x20, 0x5c, - 0x1b, 0x99, 0xea, 0x82, 0xec, 0xfd, 0x0b, 0x89, 0x25, 0x6c, 0x31, 0x3d, 0xa8, 0x52, 0xba, 0x8e, - 0xdf, 0x20, 0xcb, 0x5f, 0x00, 0xf8, 0x6b, 0xf2, 0x63, 0x5d, 0x2a, 0x55, 0xc6, 0xee, 0x34, 0xa4, - 0x86, 0xab, 0x47, 0x89, 0xcd, 0xb6, 0xaa, 0xe0, 0x5c, 0x9a, 0x57, 0x7d, 0x3e, 0xaa, 0x8b, 0x74, - 0xfc, 0x94, 0xc7, 0x9d, 0x0e, 0xa2, 0x92, 0xa9, 0xc5, 0xdd, 0x71, 0x53, 0x54, 0x38, 0xb0, 0x22, - 0x88, 0xdc, 0x46, 0xcd, 0x45, 0xc7, 0x33, 0xc7, 0x2f, 0xed, 0x5f, 0x4d, 0x05, 0x9d, 0xba, 0x2e, - 0xf7, 0xa4, 0xb5, 0xfa, 0x79, 0x11, 0x41, 0xd1, 0x1b, 0x50, 0xab, 0xef, 0xdf, 0xa8, 0x5c, 0x28, - 0xc7, 0x8e, 0x86, 0xa2, 0x85, 0x8a, 0x90, 0xf4, 0xda, 0x71, 0x1f, 0xff, 0x7f, 0x02, 0x4c, 0x24, - 0x95, 0x0d, 0x31, 0xa3, 0x8b, 0x62, 0xae, 0x45, 0xe2, 0x44, 0x6c, 0x01, 0x1d, 0xdc, 0x67, 0xbe, - 0xfb, 0x16, 0x4f, 0x4c, 0xf0, 0x81, 0xa8, 0xbd, 0xe1, 0x29, 0x6f, 0x1c, 0xff, 0xa4, 0x82, 0x96, - 0xa3, 0x67, 0xad, 0xa6, 0x99, 0xd6, 0x29, 0x02, 0x7f, 0xfc, 0xe3, 0x8d, 0xe3, 0x0d, 0x17, 0x91, - 0x84, 0xcf, 0x4b, 0x05, 0xdd, 0x29, 0x96, 0xb4, 0x58, 0x56, 0x9b, 0x65, 0x17, 0xdd, 0x16, 0x1f, - 0xf8, 0x59, 0x8d, 0xfb, 0xa0, 0xb0, 0xc7, 0x0b, 0x74, 0x64, 0xef, 0x8c, 0xcb, 0xba, 0x10, 0x48, - 0x37, 0x28, 0xc9, 0x7f, 0x17, 0xac, 0x5f, 0x04, 0xa0, 0x50, 0x6d, 0x18, 0x5f, 0x23, 0xe3, 0x9c, - 0xb6, 0xe0, 0x6c, 0xc0, 0xe1, 0x5e, 0xba, 0x8f, 0x70, 0xf1, 0xca, 0xc5, 0x97, 0x95, 0xf7, 0x4c, - 0xdd, 0x6c, 0x8c, 0xbb, 0x4d, 0x68, 0x18, 0x59, 0xb3, 0x1b, 0x6f, 0x81, 0xe7, 0xd8, 0x44, 0xdc, - 0x6e, 0x84, 0xce, 0x5b, 0x0c, 0x66, 0xef, 0xc4, 0x72, 0x00, 0xf2, 0x5a, 0xef, 0x82, 0x63, 0x18, - 0xf7, 0xd3, 0xb8, 0x25, 0xc4, 0x91, 0x80, 0x04, 0x54, 0x61, 0x5b, 0xf5, 0xe2, 0xda, 0xfb, 0x1d, - 0xd4, 0x19, 0x99, 0x18, 0xbd, 0x9a, 0x1e, 0x96, 0xe9, 0x1c, 0xd5, 0xd0, 0x06, 0xf5, 0x37, 0x91, - 0x3b, 0x4d, 0xa5, 0x2a, 0xda, 0x3c, 0xcd, 0xa6, 0xda, 0x53, 0xb8, 0x4a, 0x1e, 0xb9, 0x51, 0xed, - 0xc3, 0x47, 0xc6, 0xfa, 0xdc, 0x2e, 0xb3, 0xdd, 0x63, 0x65, 0xba, 0x17, 0xdb, 0x65, 0x8b, 0x63, - 0x77, 0x31, 0x6d, 0xd9, 0xb7, 0x18, 0x33, 0x91, 0xa1, 0x1f, 0xed, 0x0d, 0x49, 0x7f, 0x29, 0xd6, - 0xd4, 0xf6, 0x12, 0x0f, 0xb2, 0x0c, 0xc9, 0x0f, 0x61, 0xb1, 0x48, 0x58, 0x52, 0xac, 0x80, 0x92, - 0xb4, 0x2d, 0x4c, 0xa8, 0x94, 0xf6, 0x99, 0xc8, 0xb7, 0x1a, 0x7f, 0x3a, 0x52, 0x49, 0x9f, 0x44, - 0xff, 0x0d, 0x38, 0x27, 0x3f, 0xad, 0xf6, 0xa4, 0x8f, 0xd9, 0x4b, 0x30, 0x6f, 0xe0, 0xb8, 0x20, - 0x94, 0x82, 0x4c, 0x96, 0xea, 0x27, 0x28, 0x61, 0x1a, 0x41, 0x6d, 0xd4, 0x30, 0x82, 0x07, 0xca, - 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e, 0xa1, 0x31, 0xe7, 0xca, - 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, - 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 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, - 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, 0x33, 0x30, - 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x36, - 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, - 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 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, 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, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, - 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, 0x0c, 0x6f, 0x45, 0xb4, 0x04, 0x59, 0x24, 0xcb, 0x70, - 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, 0x87, 0x61, 0xb3, 0xd3, 0xfc, 0xbe, 0xb6, 0x05, 0x3c, - 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, 0x87, 0x07, 0xcf, 0x20, 0xbe, 0xaa, 0xeb, 0x24, 0xc5, - 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, 0xea, 0xb4, 0x5d, 0x3b, 0x29, 0x6c, 0xba, 0x4d, 0x15, - 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, 0x0d, 0x1d, 0xf7, 0x66, 0x77, 0xa2, 0x96, 0x56, 0xed, - 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, 0x32, 0x9c, 0xa9, 0xfd, 0xbf, 0xb8, 0x34, 0x6f, 0x57, - 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, 0xe9, 0x0f, 0x3c, 0xed, 0x4f, 0x31, 0x87, 0x05, 0xa4, - 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, 0xca, 0xd3, 0xf9, 0xd6, 0xaa, 0xaa, 0x88, 0x57, 0x66, - 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, 0x3d, 0x1d, 0xbc, 0x82, 0x6e, 0x81, 0xe9, 0x19, 0xf5, - 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, 0x88, 0xba, 0x51, 0xe7, 0x3a, 0xa0, 0x77, 0x2d, 0xe6, - 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, 0xf8, 0xa7, 0x79, 0x51, 0x2d, 0xe6, 0xc2, 0xee, 0xd2, - 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, 0x37, 0x12, 0xeb, 0x63, 0x99, 0x3d, 0xf3, 0x21, 0xbe, - 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, 0x0c, 0x4b, 0x43, 0x0c, 0x05, 0x6a, 0x6b, 0x8f, 0x05, - 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, 0xa7, 0x75, 0x63, 0x85, 0xe3, 0xa5, 0x5c, 0xc0, 0xd6, - 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, 0x6b, 0x4e, 0x99, 0x74, 0x7d, 0xd2, 0x69, 0x9f, 0xa8, - 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, 0x7e, 0x4a, 0x7a, 0x8a, 0xeb, 0x7c, 0xcd, 0x43, 0x9e, - 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, 0xe7, 0xfb, 0xa0, 0x43, 0xb3, 0xd7, 0x15, 0x28, 0x8a, - 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, 0x1b, 0x37, 0x33, 0x76, 0xc4, 0x58, 0xb9, 0x2d, 0x89, - 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, 0xa6, 0x07, 0x79, 0x11, 0x7d, 0x26, 0xd2, 0x85, 0x22, - 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, 0x18, 0xf3, 0xaa, 0x05, 0xce, 0x87, 0x99, 0xde, 0x76, - 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, 0x51, 0xa0, 0xc9, 0x70, 0xfc, 0xb9, 0x22, 0xfe, 0xd2, - 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, 0x53, 0xfd, 0xa1, 0xe6, 0xff, 0x8e, 0xd6, 0xde, 0x9e, - 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, 0xb2, 0x34, 0x8a, 0x1d, 0xf7, 0x9e, 0xa0, 0xbb, 0xf4, - 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, 0x92, 0x0d, 0xc9, 0x94, 0x7f, 0x24, 0xb9, 0x9f, 0xda, - 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, 0x3a, 0x70, 0x63, 0x3b, 0x22, 0x42, 0x14, 0xd0, 0xf9, - 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, 0x41, 0x20, 0x0d, 0x7e, 0x70, 0xd7, 0x88, 0x36, 0xa2, - 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, 0x9c, 0x5f, 0x4d, 0x3e, 0x4f, 0x83, 0x79, 0x06, 0x73, - 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, 0xce, 0x93, 0x5c, 0x68, 0xbf, 0x5a, 0xe6, 0x4c, 0x23, - 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, 0x1b, 0x64, 0x39, 0x64, 0xb7, 0xd2, 0x1d, 0xd0, 0x2d, - 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, 0x38, 0xb3, 0xf9, 0x5a, 0xee, 0x0e, 0x1d, 0xb6, 0xf9, - 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, 0x1a, 0x4b, 0x5a, 0xaf, 0x62, 0xb5, 0xd3, 0xef, 0x37, - 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, 0xa6, 0x46, 0x7b, 0x38, 0x63, 0x62, 0x3c, 0x18, 0x7d, - 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3c, 0x30, 0x82, 0x02, 0x38, 0x30, 0x1d, - 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x35, 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, - 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, 0x1c, 0x30, 0x0f, 0x06, - 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1f, - 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35, 0x07, 0x82, 0xfe, 0x0e, - 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, 0x1c, 0x30, - 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0xca, 0x30, 0x82, 0x01, 0xc6, - 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x01, 0x30, - 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, - 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00, 0x65, 0x00, 0x6c, 0x00, - 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, - 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, - 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, - 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, - 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, - 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, - 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, - 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x70, 0x00, - 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, - 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00, - 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x73, 0x00, 0x20, 0x00, - 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, - 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, - 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x63, 0x00, - 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, - 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, - 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, - 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63, 0x00, - 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, - 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2e, 0x30, - 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x29, 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, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, - 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x6f, 0x8a, 0xb7, 0x35, 0x73, 0x5a, - 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, 0x17, 0x52, 0x1c, 0x70, 0xf0, 0xe0, 0x53, 0xb4, 0x16, - 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, 0x0e, 0xa6, 0x17, 0x86, 0x52, 0xc6, 0x70, 0x73, 0xf3, - 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, 0x0b, 0x85, 0xc9, 0xb9, 0xcf, 0x15, 0x91, 0x05, 0x2e, - 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, 0xf7, 0xe2, 0xd7, 0xf4, 0x60, 0xd2, 0xfc, 0x1d, 0xbf, - 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, 0x92, 0xef, 0xa4, 0x05, 0x34, 0x97, 0x57, 0x97, 0x56, - 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, 0x0e, 0x77, 0x85, 0xf1, 0x37, 0xc6, 0x19, 0x8b, 0x23, - 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, 0x78, 0xc5, 0xe6, 0x77, 0xfe, 0x72, 0x5f, 0xb2, 0x2c, - 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, 0xd9, 0x78, 0x20, 0xae, 0xbd, 0x75, 0x61, 0x6a, 0xaa, - 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, 0x91, 0x5c, 0x0a, 0x85, 0xc9, 0x59, 0x7d, 0x4e, 0x89, - 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, 0x1e, 0x62, 0x1e, 0xb9, 0x62, 0x2c, 0x34, 0x49, 0x15, - 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, 0x01, 0xc0, 0xda, 0x48, 0x44, 0xd4, 0x8b, 0xd3, 0x17, - 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, 0xaa, 0x14, 0x22, 0xa1, 0x38, 0x09, 0x0b, 0xb7, 0x0c, - 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, 0x07, 0xb4, 0x1b, 0xb3, 0x4a, 0xab, 0xae, 0xf6, 0xe7, - 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, 0xf9, 0x30, 0x28, 0x61, 0x92, 0x52, 0x58, 0x10, 0x15, - 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, 0x67, 0xc4, 0xb4, 0xcf, 0xe6, 0xf9, 0x46, 0x68, 0xe2, - 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, 0x9a, 0x45, 0x70, 0x3c, 0xf2, 0xdf, 0x29, 0x20, 0x9e, - 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, 0x4b, 0xae, 0x1a, 0x2f, 0x53, 0x03, 0x9a, 0xfd, 0x68, - 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, 0x3c, 0x1b, 0x47, 0x43, 0x19, 0x81, 0x0e, 0x0a, 0xbb, - 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, 0xb7, 0x9c, 0xe1, 0xf9, 0xeb, 0x37, 0xb0, 0x11, 0x20, - 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, 0xaf, 0x63, 0xed, 0x6a, 0x63, 0x1f, 0x1e, 0x61, 0x62, - 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, 0xd7, 0xba, 0x4f, 0xf2, 0x61, 0x26, 0x29, 0x99, 0xea, - 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, 0x5c, 0xe7, 0x86, 0x1d, 0xef, 0xf4, 0x6f, 0x3b, 0x6c, - 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, 0x9d, 0x0f, 0xdc, 0xcc, 0x0e, 0x7b, 0xf8, 0xc4, 0xee, - 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, 0xc8, 0x18, 0x4d, 0xa1, 0xe4, 0x40, 0x2c, 0xe9, 0x13, - 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, 0x93, 0x66, 0x56, 0x35, 0x5c, 0xc1, 0x38, 0x7d, 0xa1, - 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, 0xb6, 0x37, 0x19, 0x61, 0x81, 0x40, 0xba, 0xd7, 0x07, - 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, 0x8a, 0x2b, 0x99, 0x5a, 0x17, 0x3f, 0x9f, 0xcf, 0x86, - 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, 0x2d, 0x52, 0xce, 0x87, 0x10, 0x0f, 0x25, 0xc2, 0x1e, - 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, 0xd1, 0x65, 0xa8, 0xb4, 0xf6, 0xa5, 0x71, 0xad, 0x45, - 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, 0x96, 0x5a, 0x5d, 0x69, 0xfa, 0xdb, 0x13, 0x39, 0xb8, - 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, 0x6d, 0x39, 0xff, 0x26, 0xce, 0x2c, 0xa8, 0x5a, 0x7e, - 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, 0x48, 0xd3, 0xf8, 0x00, 0x00, 0x31, 0x82, 0x03, 0x28, - 0x30, 0x82, 0x03, 0x24, 0x02, 0x01, 0x01, 0x30, 0x81, 0x91, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, - 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, - 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 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, 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, 0x02, 0x08, 0x04, 0x2e, 0x97, 0xbb, 0x62, 0x84, 0xd9, 0x1c, 0x30, 0x0d, 0x06, 0x09, 0x60, - 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa0, 0x69, 0x30, 0x18, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x03, 0x31, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x36, 0x32, 0x38, 0x31, 0x37, 0x35, - 0x35, 0x32, 0x34, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, - 0x04, 0x31, 0x22, 0x04, 0x20, 0x7f, 0xe5, 0xca, 0xfa, 0x9e, 0x7f, 0xd9, 0x3b, 0xec, 0x98, 0x25, - 0x4f, 0x65, 0x73, 0x30, 0x1f, 0x7a, 0xe3, 0x51, 0xd3, 0xa4, 0xa9, 0x18, 0x7e, 0xeb, 0x6f, 0xdb, - 0x13, 0xcb, 0x2f, 0x82, 0x4b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0x5e, 0xc2, 0x3f, 0x3d, 0x74, 0x0e, 0x23, 0x44, - 0xec, 0x4f, 0x51, 0x96, 0x08, 0x28, 0x05, 0xe1, 0x2e, 0xd6, 0xba, 0x3a, 0x51, 0xf4, 0x46, 0xff, - 0x2c, 0x96, 0x4a, 0x05, 0xa0, 0xa1, 0x89, 0xc8, 0x8d, 0x28, 0xb8, 0x1d, 0xc2, 0xc7, 0xa3, 0x6e, - 0x43, 0x9b, 0xa0, 0xe8, 0xcb, 0x3a, 0x5e, 0xa7, 0xa7, 0xe7, 0x34, 0x93, 0xc9, 0x31, 0xf7, 0xde, - 0x92, 0x55, 0x95, 0x22, 0x96, 0xdf, 0xbb, 0x6e, 0xb3, 0xb1, 0x8c, 0x20, 0x9f, 0x6f, 0x20, 0x85, - 0xae, 0x3a, 0x48, 0x69, 0xfe, 0x5d, 0xd9, 0xf0, 0xe9, 0xd1, 0x86, 0x74, 0xc8, 0x13, 0x58, 0x27, - 0xc6, 0xb5, 0x00, 0x76, 0xa3, 0x75, 0x01, 0x53, 0xfe, 0x8f, 0x7d, 0xe4, 0x69, 0x51, 0x3b, 0x19, - 0x4b, 0xef, 0x34, 0x6e, 0x33, 0xf1, 0x03, 0x4d, 0xfc, 0x08, 0xd9, 0xe3, 0x47, 0x19, 0x83, 0x83, - 0xb9, 0xa1, 0x83, 0x14, 0x5a, 0x70, 0x4f, 0xf7, 0x72, 0x2c, 0x00, 0x04, 0xce, 0x3f, 0x5d, 0xf2, - 0xd3, 0xd8, 0x03, 0x7d, 0xe6, 0xb7, 0xf3, 0xe5, 0x88, 0x44, 0x91, 0x3e, 0x2f, 0x15, 0x51, 0x36, - 0xbd, 0x16, 0xcb, 0x96, 0xc0, 0xda, 0x33, 0xa5, 0x82, 0x07, 0xc0, 0x6f, 0x20, 0x81, 0x0a, 0x5a, - 0x14, 0xc9, 0x35, 0xe3, 0xf7, 0x08, 0x7a, 0x10, 0x80, 0x66, 0x08, 0xa5, 0x88, 0x22, 0xf6, 0xab, - 0x37, 0xbc, 0xc0, 0x75, 0x2c, 0xca, 0xed, 0x5b, 0x83, 0x0c, 0x4b, 0xed, 0x11, 0x05, 0xb1, 0xf9, - 0x91, 0x2b, 0x2a, 0x3e, 0x0f, 0xa7, 0x1e, 0xfe, 0x68, 0xb9, 0x88, 0x02, 0x0b, 0x51, 0xf2, 0x38, - 0x3c, 0xc1, 0xb7, 0x56, 0x57, 0x20, 0x7b, 0xcf, 0xfa, 0x19, 0x85, 0x1f, 0x64, 0x2f, 0x55, 0xb8, - 0xde, 0x80, 0xee, 0x04, 0x99, 0xa9, 0x53, 0x42, 0x15, 0x27, 0x27, 0x22, 0x2e, 0xae, 0xee, 0x98, - 0x17, 0x3e, 0xd6, 0xcf, 0xc7, 0x1c, 0x8c, 0x1a, 0xb9, 0x6a, 0x0c, 0x34, 0xe7, 0xb2, 0x4f, 0xa3, - 0x25, 0xbc, 0xe6, 0x12, 0xae, 0x51, 0xe8, 0xa3, 0x25, 0x6f, 0xc7, 0x10, 0x3e, 0xcf, 0x74, 0x7c, - 0x97, 0x4a, 0x4d, 0xaf, 0xa2, 0x60, 0x9c, 0x99, 0xc7, 0x2a, 0x17, 0x86, 0x13, 0x7b, 0xc6, 0xde, - 0xf1, 0x72, 0xdd, 0x7d, 0x4a, 0x61, 0xce, 0x08, 0xb1, 0x04, 0x6e, 0xcf, 0xc0, 0x50, 0xfd, 0xe9, - 0x80, 0x04, 0xed, 0xb9, 0xbf, 0xc6, 0xcd, 0xa1, 0xad, 0xe7, 0x34, 0x8f, 0x31, 0xb2, 0x6e, 0x25, - 0xba, 0x54, 0x22, 0x23, 0x19, 0x06, 0xe6, 0xea, 0xe7, 0x06, 0x9f, 0x64, 0x44, 0x39, 0x71, 0xc1, - 0xaa, 0xa6, 0xa4, 0xef, 0xaa, 0xdb, 0x6b, 0x9e, 0xce, 0x29, 0x97, 0x55, 0x2f, 0x06, 0x5c, 0x6c, - 0x10, 0xe6, 0xa5, 0x8c, 0x30, 0xf6, 0x81, 0x65, 0xee, 0x74, 0xb3, 0x40, 0xaa, 0x3b, 0x70, 0xcb, - 0x80, 0x50, 0x22, 0x01, 0x0d, 0x12, 0x11, 0x72, 0x6d, 0x10, 0x54, 0x6e, 0xa4, 0x9e, 0x5e, 0xcd, - 0xcc, 0xa0, 0x30, 0xf8, 0x61, 0xab, 0x36, 0x4a, 0x3a, 0xf0, 0x5a, 0xe3, 0xf5, 0x38, 0x70, 0x05, - 0xdd, 0x04, 0x2e, 0x2b, 0x3a, 0xf8, 0x9a, 0x39, 0x48, 0x5f, 0x3f, 0xc6, 0x60, 0xaf, 0x9e, 0xca, - 0x47, 0xb9, 0xfa, 0xb0, 0x1e, 0x45, 0x56, 0x47, 0xe0, 0xf1, 0x00, 0x47, 0x60, 0xb0, 0xca, 0x06, - 0xef, 0xe8, 0xe9, 0x3b, 0xcd, 0x61, 0x8f, 0xc3, 0x14, 0xbc, 0x61, 0x9b, 0x08, 0x4e, 0xf5, 0x4a, - 0xf9, 0x9a, 0x35, 0x5f, 0x84, 0x97, 0x43, 0x24, 0x62, 0x60, 0xd2, 0xa7, 0xd7, 0xe6, 0x10, 0xe7, - 0xf1, 0xe4, 0xd0, 0x96, 0x1f, 0x7c, 0x93, 0xbc, 0x3a, 0x28, 0x59, 0x10, 0x3e, 0x32, 0x71, 0xa4, - 0x9f, 0xab, 0xf6, 0x30, 0x07, 0xca, 0x7e, 0xcd, 0x35, 0xdb, 0xc1, 0xa2, 0x99, 0x8e, 0x7f, 0x85, - 0xba, 0x92, 0xf6, 0x76, 0x99, 0xa3, 0xbc, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const UInt8 kApplePKISettingsRootCACert[] = { - 0x30, 0x82, 0x07, 0xca, 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e, - 0xa1, 0x31, 0xe7, 0xca, 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 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, 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, 0x33, 0x30, 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d, - 0x34, 0x33, 0x30, 0x36, 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x30, 0x81, 0x84, - 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, - 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, - 0x6f, 0x74, 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, 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, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, - 0x02, 0x82, 0x02, 0x01, 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, 0x0c, 0x6f, 0x45, 0xb4, 0x04, - 0x59, 0x24, 0xcb, 0x70, 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, 0x87, 0x61, 0xb3, 0xd3, 0xfc, - 0xbe, 0xb6, 0x05, 0x3c, 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, 0x87, 0x07, 0xcf, 0x20, 0xbe, - 0xaa, 0xeb, 0x24, 0xc5, 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, 0xea, 0xb4, 0x5d, 0x3b, 0x29, - 0x6c, 0xba, 0x4d, 0x15, 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, 0x0d, 0x1d, 0xf7, 0x66, 0x77, - 0xa2, 0x96, 0x56, 0xed, 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, 0x32, 0x9c, 0xa9, 0xfd, 0xbf, - 0xb8, 0x34, 0x6f, 0x57, 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, 0xe9, 0x0f, 0x3c, 0xed, 0x4f, - 0x31, 0x87, 0x05, 0xa4, 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, 0xca, 0xd3, 0xf9, 0xd6, 0xaa, - 0xaa, 0x88, 0x57, 0x66, 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, 0x3d, 0x1d, 0xbc, 0x82, 0x6e, - 0x81, 0xe9, 0x19, 0xf5, 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, 0x88, 0xba, 0x51, 0xe7, 0x3a, - 0xa0, 0x77, 0x2d, 0xe6, 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, 0xf8, 0xa7, 0x79, 0x51, 0x2d, - 0xe6, 0xc2, 0xee, 0xd2, 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, 0x37, 0x12, 0xeb, 0x63, 0x99, - 0x3d, 0xf3, 0x21, 0xbe, 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, 0x0c, 0x4b, 0x43, 0x0c, 0x05, - 0x6a, 0x6b, 0x8f, 0x05, 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, 0xa7, 0x75, 0x63, 0x85, 0xe3, - 0xa5, 0x5c, 0xc0, 0xd6, 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, 0x6b, 0x4e, 0x99, 0x74, 0x7d, - 0xd2, 0x69, 0x9f, 0xa8, 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, 0x7e, 0x4a, 0x7a, 0x8a, 0xeb, - 0x7c, 0xcd, 0x43, 0x9e, 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, 0xe7, 0xfb, 0xa0, 0x43, 0xb3, - 0xd7, 0x15, 0x28, 0x8a, 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, 0x1b, 0x37, 0x33, 0x76, 0xc4, - 0x58, 0xb9, 0x2d, 0x89, 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, 0xa6, 0x07, 0x79, 0x11, 0x7d, - 0x26, 0xd2, 0x85, 0x22, 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, 0x18, 0xf3, 0xaa, 0x05, 0xce, - 0x87, 0x99, 0xde, 0x76, 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, 0x51, 0xa0, 0xc9, 0x70, 0xfc, - 0xb9, 0x22, 0xfe, 0xd2, 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, 0x53, 0xfd, 0xa1, 0xe6, 0xff, - 0x8e, 0xd6, 0xde, 0x9e, 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, 0xb2, 0x34, 0x8a, 0x1d, 0xf7, - 0x9e, 0xa0, 0xbb, 0xf4, 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, 0x92, 0x0d, 0xc9, 0x94, 0x7f, - 0x24, 0xb9, 0x9f, 0xda, 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, 0x3a, 0x70, 0x63, 0x3b, 0x22, - 0x42, 0x14, 0xd0, 0xf9, 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, 0x41, 0x20, 0x0d, 0x7e, 0x70, - 0xd7, 0x88, 0x36, 0xa2, 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, 0x9c, 0x5f, 0x4d, 0x3e, 0x4f, - 0x83, 0x79, 0x06, 0x73, 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, 0xce, 0x93, 0x5c, 0x68, 0xbf, - 0x5a, 0xe6, 0x4c, 0x23, 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, 0x1b, 0x64, 0x39, 0x64, 0xb7, - 0xd2, 0x1d, 0xd0, 0x2d, 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, 0x38, 0xb3, 0xf9, 0x5a, 0xee, - 0x0e, 0x1d, 0xb6, 0xf9, 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, 0x1a, 0x4b, 0x5a, 0xaf, 0x62, - 0xb5, 0xd3, 0xef, 0x37, 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, 0xa6, 0x46, 0x7b, 0x38, 0x63, - 0x62, 0x3c, 0x18, 0x7d, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3c, 0x30, 0x82, - 0x02, 0x38, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x35, 0x07, 0x82, - 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, - 0x1c, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, - 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35, - 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, - 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0xca, - 0x30, 0x82, 0x01, 0xc6, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, - 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00, - 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, - 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, - 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, - 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00, - 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, - 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00, - 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, - 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, - 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00, - 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, - 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, - 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, - 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, - 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00, - 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, - 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00, - 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, - 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, - 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, - 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, - 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, - 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, - 0x29, 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, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, - 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x6f, 0x8a, - 0xb7, 0x35, 0x73, 0x5a, 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, 0x17, 0x52, 0x1c, 0x70, 0xf0, - 0xe0, 0x53, 0xb4, 0x16, 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, 0x0e, 0xa6, 0x17, 0x86, 0x52, - 0xc6, 0x70, 0x73, 0xf3, 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, 0x0b, 0x85, 0xc9, 0xb9, 0xcf, - 0x15, 0x91, 0x05, 0x2e, 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, 0xf7, 0xe2, 0xd7, 0xf4, 0x60, - 0xd2, 0xfc, 0x1d, 0xbf, 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, 0x92, 0xef, 0xa4, 0x05, 0x34, - 0x97, 0x57, 0x97, 0x56, 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, 0x0e, 0x77, 0x85, 0xf1, 0x37, - 0xc6, 0x19, 0x8b, 0x23, 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, 0x78, 0xc5, 0xe6, 0x77, 0xfe, - 0x72, 0x5f, 0xb2, 0x2c, 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, 0xd9, 0x78, 0x20, 0xae, 0xbd, - 0x75, 0x61, 0x6a, 0xaa, 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, 0x91, 0x5c, 0x0a, 0x85, 0xc9, - 0x59, 0x7d, 0x4e, 0x89, 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, 0x1e, 0x62, 0x1e, 0xb9, 0x62, - 0x2c, 0x34, 0x49, 0x15, 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, 0x01, 0xc0, 0xda, 0x48, 0x44, - 0xd4, 0x8b, 0xd3, 0x17, 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, 0xaa, 0x14, 0x22, 0xa1, 0x38, - 0x09, 0x0b, 0xb7, 0x0c, 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, 0x07, 0xb4, 0x1b, 0xb3, 0x4a, - 0xab, 0xae, 0xf6, 0xe7, 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, 0xf9, 0x30, 0x28, 0x61, 0x92, - 0x52, 0x58, 0x10, 0x15, 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, 0x67, 0xc4, 0xb4, 0xcf, 0xe6, - 0xf9, 0x46, 0x68, 0xe2, 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, 0x9a, 0x45, 0x70, 0x3c, 0xf2, - 0xdf, 0x29, 0x20, 0x9e, 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, 0x4b, 0xae, 0x1a, 0x2f, 0x53, - 0x03, 0x9a, 0xfd, 0x68, 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, 0x3c, 0x1b, 0x47, 0x43, 0x19, - 0x81, 0x0e, 0x0a, 0xbb, 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, 0xb7, 0x9c, 0xe1, 0xf9, 0xeb, - 0x37, 0xb0, 0x11, 0x20, 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, 0xaf, 0x63, 0xed, 0x6a, 0x63, - 0x1f, 0x1e, 0x61, 0x62, 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, 0xd7, 0xba, 0x4f, 0xf2, 0x61, - 0x26, 0x29, 0x99, 0xea, 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, 0x5c, 0xe7, 0x86, 0x1d, 0xef, - 0xf4, 0x6f, 0x3b, 0x6c, 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, 0x9d, 0x0f, 0xdc, 0xcc, 0x0e, - 0x7b, 0xf8, 0xc4, 0xee, 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, 0xc8, 0x18, 0x4d, 0xa1, 0xe4, - 0x40, 0x2c, 0xe9, 0x13, 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, 0x93, 0x66, 0x56, 0x35, 0x5c, - 0xc1, 0x38, 0x7d, 0xa1, 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, 0xb6, 0x37, 0x19, 0x61, 0x81, - 0x40, 0xba, 0xd7, 0x07, 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, 0x8a, 0x2b, 0x99, 0x5a, 0x17, - 0x3f, 0x9f, 0xcf, 0x86, 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, 0x2d, 0x52, 0xce, 0x87, 0x10, - 0x0f, 0x25, 0xc2, 0x1e, 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, 0xd1, 0x65, 0xa8, 0xb4, 0xf6, - 0xa5, 0x71, 0xad, 0x45, 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, 0x96, 0x5a, 0x5d, 0x69, 0xfa, - 0xdb, 0x13, 0x39, 0xb8, 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, 0x6d, 0x39, 0xff, 0x26, 0xce, - 0x2c, 0xa8, 0x5a, 0x7e, 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, 0x48, 0xd3, 0xf8 -}; - -static const UInt8 kBasePList[] = { - 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, 0xd1, 0x01, 0x02, 0x53, 0x66, 0x6f, 0x6f, 0x53, - 0x62, 0x61, 0x72, 0x08, 0x0b, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x13 -}; - -static const UInt8 kBaseManifestData[] = { - 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, - 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, - 0x46, 0x2d, 0x38, 0x22, 0x3f, 0x3e, 0x0a, 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, - 0x20, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x22, 0x2d, - 0x2f, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2f, 0x2f, 0x44, 0x54, 0x44, 0x20, 0x50, 0x4c, 0x49, - 0x53, 0x54, 0x20, 0x31, 0x2e, 0x30, 0x2f, 0x2f, 0x45, 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x44, 0x54, 0x44, 0x73, 0x2f, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x4c, - 0x69, 0x73, 0x74, 0x2d, 0x31, 0x2e, 0x30, 0x2e, 0x64, 0x74, 0x64, 0x22, 0x3e, 0x0a, 0x3c, 0x70, - 0x6c, 0x69, 0x73, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, - 0x30, 0x22, 0x3e, 0x0a, 0x3c, 0x64, 0x69, 0x63, 0x74, 0x3e, 0x0a, 0x09, 0x3c, 0x6b, 0x65, 0x79, - 0x3e, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x45, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, - 0x0a, 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x6c, 0x45, 0x66, 0x55, 0x58, 0x61, - 0x39, 0x71, 0x54, 0x37, 0x72, 0x45, 0x36, 0x47, 0x73, 0x51, 0x4d, 0x69, 0x6f, 0x33, 0x6b, 0x44, - 0x78, 0x61, 0x57, 0x35, 0x38, 0x7a, 0x53, 0x46, 0x6e, 0x54, 0x48, 0x66, 0x56, 0x58, 0x6b, 0x4e, - 0x36, 0x7a, 0x57, 0x2f, 0x59, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, - 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, - 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x62, 0x4d, 0x73, 0x48, 0x77, 0x57, 0x68, 0x76, - 0x2b, 0x61, 0x4d, 0x4d, 0x45, 0x74, 0x65, 0x34, 0x34, 0x6c, 0x45, 0x39, 0x34, 0x74, 0x56, 0x44, - 0x36, 0x37, 0x56, 0x74, 0x67, 0x47, 0x32, 0x4d, 0x79, 0x68, 0x66, 0x56, 0x4d, 0x52, 0x70, 0x6c, - 0x53, 0x42, 0x55, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x3c, - 0x6b, 0x65, 0x79, 0x3e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x2e, 0x70, 0x6c, 0x69, 0x73, - 0x74, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, - 0x09, 0x43, 0x49, 0x6b, 0x2f, 0x35, 0x34, 0x50, 0x66, 0x42, 0x32, 0x47, 0x76, 0x5a, 0x56, 0x68, - 0x6d, 0x7a, 0x6e, 0x53, 0x31, 0x52, 0x6c, 0x62, 0x43, 0x41, 0x7a, 0x56, 0x4b, 0x31, 0x49, 0x69, - 0x6e, 0x4d, 0x6d, 0x37, 0x64, 0x79, 0x37, 0x6d, 0x31, 0x49, 0x57, 0x77, 0x3d, 0x0a, 0x09, 0x3c, - 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x45, 0x56, 0x52, - 0x6f, 0x6f, 0x74, 0x73, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, - 0x0a, 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x51, 0x52, 0x45, 0x45, 0x63, 0x63, - 0x75, 0x62, 0x2b, 0x36, 0x2f, 0x50, 0x62, 0x78, 0x33, 0x75, 0x6a, 0x68, 0x51, 0x38, 0x48, 0x54, - 0x6c, 0x6b, 0x61, 0x4d, 0x68, 0x49, 0x73, 0x65, 0x36, 0x4b, 0x30, 0x51, 0x56, 0x69, 0x51, 0x45, - 0x39, 0x35, 0x49, 0x6a, 0x41, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, - 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x47, 0x72, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x64, - 0x4b, 0x65, 0x79, 0x73, 0x2e, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, - 0x0a, 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x70, 0x51, 0x71, 0x4a, 0x4e, 0x2f, - 0x43, 0x6f, 0x68, 0x79, 0x76, 0x4d, 0x4d, 0x38, 0x46, 0x61, 0x35, 0x74, 0x4d, 0x42, 0x51, 0x34, - 0x4e, 0x51, 0x6a, 0x55, 0x6d, 0x45, 0x6c, 0x69, 0x4b, 0x76, 0x50, 0x69, 0x59, 0x51, 0x65, 0x49, - 0x6f, 0x36, 0x44, 0x48, 0x67, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, - 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, 0x3c, 0x69, 0x6e, 0x74, 0x65, - 0x67, 0x65, 0x72, 0x3e, 0x32, 0x30, 0x31, 0x33, 0x30, 0x36, 0x32, 0x37, 0x30, 0x30, 0x3c, 0x2f, - 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x3e, 0x0a, 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x63, - 0x65, 0x72, 0x74, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x3c, 0x2f, - 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x70, 0x6b, - 0x77, 0x5a, 0x30, 0x72, 0x6a, 0x6b, 0x76, 0x31, 0x6d, 0x61, 0x61, 0x4f, 0x55, 0x30, 0x43, 0x4d, - 0x4e, 0x68, 0x6b, 0x66, 0x6b, 0x47, 0x38, 0x52, 0x59, 0x43, 0x48, 0x50, 0x32, 0x76, 0x52, 0x76, - 0x75, 0x74, 0x78, 0x37, 0x52, 0x58, 0x48, 0x56, 0x51, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, - 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x63, 0x65, 0x72, 0x74, 0x73, 0x54, - 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, - 0x09, 0x3c, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x09, 0x4c, 0x71, 0x4e, 0x41, 0x52, 0x47, 0x44, - 0x62, 0x54, 0x31, 0x45, 0x38, 0x42, 0x69, 0x64, 0x4f, 0x41, 0x48, 0x73, 0x6c, 0x4e, 0x52, 0x4f, - 0x61, 0x59, 0x63, 0x53, 0x6f, 0x43, 0x71, 0x72, 0x4e, 0x63, 0x4f, 0x64, 0x31, 0x66, 0x6b, 0x31, - 0x53, 0x75, 0x79, 0x51, 0x3d, 0x0a, 0x09, 0x3c, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x3e, 0x0a, 0x3c, - 0x2f, 0x64, 0x69, 0x63, 0x74, 0x3e, 0x0a, 0x3c, 0x2f, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3e, 0x0a -}; -static void test_OTA_PKI() -{ - CFDataRef signed_plist_data = NULL; - isnt(signed_plist_data = CFDataCreate(kCFAllocatorDefault, kSignedPList, sizeof(kSignedPList)), - NULL, "create CMS signed message from kSignedPList"); - - SecPolicyRef policy = NULL; - SecTrustRef trustRef = NULL; - CFDataRef payload = NULL; - isnt(policy = SecPolicyCreateOTAPKISigner(), NULL, "create the OTAPKISigner policy"); - ok_status(SecCMSVerifyCopyDataAndAttributes(signed_plist_data, NULL, policy, &trustRef, &payload, NULL)); - isnt(payload, NULL, "payload from the CMS message (plist)"); - isnt(trustRef, NULL, "trustRef from the CMS message (plist)"); - - CFDataRef apple_pki_settings_root_certificate_authority_cert_data = NULL; - isnt(apple_pki_settings_root_certificate_authority_cert_data = CFDataCreate(kCFAllocatorDefault, kApplePKISettingsRootCACert, sizeof(kApplePKISettingsRootCACert)), - NULL, "Get the Apple PKI Settings Root Certification Authority Cert Data"); - - SecCertificateRef apple_pki_settings_root_certificate_authority_cert = NULL; - isnt(apple_pki_settings_root_certificate_authority_cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, - kApplePKISettingsRootCACert, sizeof(kApplePKISettingsRootCACert)), - NULL, "Get the Apple PKI Settings Root Certification Authority Cert"); - - CFArrayRef anchors = CFArrayCreate(kCFAllocatorDefault, (const void **)&apple_pki_settings_root_certificate_authority_cert, 1, &kCFTypeArrayCallBacks); - CFReleaseNull(apple_pki_settings_root_certificate_authority_cert); - apple_pki_settings_root_certificate_authority_cert = NULL; - - SecTrustSetAnchorCertificates(trustRef, anchors); - - SecTrustResultType trust_result = kSecTrustResultRecoverableTrustFailure; - - ok_status(SecTrustEvaluate(trustRef, &trust_result), "Evaluate trust of the CMS message (plist)"); - - is_status(trust_result, kSecTrustResultUnspecified, "trust is kSecTrustResultRecoverableTrustFailure (plist)"); - - CFPropertyListFormat plist_format; - CFErrorRef error = NULL; - CFPropertyListRef propertyRef = NULL; - isnt(propertyRef = CFPropertyListCreateWithData(kCFAllocatorDefault, payload, 0, &plist_format, &error), - NULL, "create Plist object from the payload"); - is(error, NULL, "error returned from CFPropertyListCreateWithData (payload plist)"); - - CFDataRef base_plist_data = NULL; - isnt(base_plist_data = CFDataCreate(kCFAllocatorDefault, kBasePList, sizeof(kBasePList)), - NULL, "create base plist data object"); - - CFPropertyListRef base_propertyRef = NULL; - isnt(base_propertyRef = CFPropertyListCreateWithData(kCFAllocatorDefault, base_plist_data, 0, &plist_format, &error), - NULL, "create base Plist object from the payload"); - is(error, NULL, "error returned from CFPropertyListCreateWithData (base plist)"); - - ok(CFEqual(base_propertyRef, propertyRef)); - - CFReleaseSafe(signed_plist_data); - - CFReleaseSafe(trustRef); - CFReleaseSafe(payload); - CFReleaseSafe(propertyRef); - CFReleaseSafe(base_plist_data); - CFReleaseSafe(base_propertyRef); - - // Now do this same test with a 'real' manifest file - CFDataRef signed_manifest_data = NULL; - isnt(signed_manifest_data = CFDataCreate(kCFAllocatorDefault, kSignedManifestData, sizeof(kSignedManifestData)), - NULL, "create CMS signed message from kSignedManifestData"); - - trustRef = NULL; - payload = NULL; - - ok_status(SecCMSVerifyCopyDataAndAttributes(signed_manifest_data, NULL, policy, &trustRef, &payload, NULL)); - CFReleaseSafe(signed_manifest_data); - isnt(payload, NULL, "payload from the CMS message (manifest)"); - isnt(trustRef, NULL, "trustRef from the CMS message (manifest)"); - SecTrustSetAnchorCertificates(trustRef, anchors); - trust_result = kSecTrustResultRecoverableTrustFailure; - - ok_status(SecTrustEvaluate(trustRef, &trust_result), "Evaluate trust of the CMS message (plist)"); - - is_status(trust_result, kSecTrustResultUnspecified, "trust is kSecTrustResultRecoverableTrustFailure (plist)"); - - CFPropertyListRef manifestRef = NULL; - - isnt(manifestRef = CFPropertyListCreateWithData(kCFAllocatorDefault, payload, 0, &plist_format, &error), - NULL, "create manifest plist object from the payload"); - is(error, NULL, "error returned from CFPropertyListCreateWithData (manifest plist)"); - - CFDataRef base_manifest_data = NULL; - isnt(base_manifest_data = CFDataCreate(kCFAllocatorDefault, kBaseManifestData, sizeof(kBaseManifestData)), - NULL, "create base manifest data object"); - - CFPropertyListRef base_manifestRef = NULL; - isnt(base_manifestRef = CFPropertyListCreateWithData(kCFAllocatorDefault, base_manifest_data, 0, &plist_format, &error), - NULL, "create base manifest object from the payload"); - is(error, NULL, "error returned from CFPropertyListCreateWithData (manifest plist)"); - - ok(CFEqual(base_manifestRef, manifestRef)); - - CFReleaseSafe(policy); - CFReleaseSafe(trustRef); - CFReleaseSafe(payload); - CFReleaseSafe(manifestRef); - CFReleaseSafe(base_manifest_data); - CFReleaseSafe(base_manifestRef); - CFReleaseSafe(anchors); - CFReleaseSafe(apple_pki_settings_root_certificate_authority_cert_data); - -} - -static void tests(void) -{ - test_OTA_PKI(); -} - -int si_74_OTA_PKI_Signer(int argc, char *const *argv) -{ - -//#if defined(NO_SERVER) && NO_SERVER == 1 - plan_tests(27); - - tests(); -//#endif - - return 0; -} - diff --git a/OSX/sec/Security/Regressions/secitem/si-82-token-ag.c b/OSX/sec/Security/Regressions/secitem/si-82-token-ag.c index 1863bf1f..0ec84b4c 100644 --- a/OSX/sec/Security/Regressions/secitem/si-82-token-ag.c +++ b/OSX/sec/Security/Regressions/secitem/si-82-token-ag.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "Security_regressions.h" @@ -20,7 +21,11 @@ static void tests(void) { CFDictionaryAddValue(dict, kSecAttrAccessGroup, kSecAttrAccessGroupToken); is_status(SecItemAdd(dict, NULL), errSecMissingEntitlement); - is_status(SecItemCopyMatching(dict, NULL), errSecItemNotFound); + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + is_status(SecItemCopyMatching(dict, NULL), errSecItemNotFound); + } else { + is_status(SecItemCopyMatching(dict, NULL), errSecMissingEntitlement); + } CFRelease(dict); } diff --git a/OSX/sec/Security/Regressions/secitem/si-84-sectrust-allowlist.m b/OSX/sec/Security/Regressions/secitem/si-84-sectrust-allowlist.m deleted file mode 100644 index ab4ed0e9..00000000 --- a/OSX/sec/Security/Regressions/secitem/si-84-sectrust-allowlist.m +++ /dev/null @@ -1,490 +0,0 @@ -/* - * si-84-sectrust-allowlist.c - * Security - * - * Copyright (c) 2015-2017 Apple Inc. All Rights Reserved. - */ - -#include -#import -#include -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -#include "si-84-sectrust-allowlist/cnnic_certs.h" -#include "si-84-sectrust-allowlist/wosign_certs.h" -#include "si-84-sectrust-allowlist/date_testing_certs.h" - -/* Define this symbol for testing updated allowlist workaround. */ -#define RADAR_32792206 1 - - -static SecCertificateRef createCertFromStaticData(const UInt8 *certData, CFIndex certLength) -{ - SecCertificateRef cert = NULL; - CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, certData, certLength, kCFAllocatorNull); - if (data) { - cert = SecCertificateCreateWithData(NULL, data); - CFRelease(data); - } - return cert; -} - -static void TestLeafOnAllowList() -{ - SecCertificateRef certs[4]; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFDateRef date = NULL; - CFArrayRef certArray = NULL; - CFArrayRef anchorsArray = NULL; - - isnt(certs[0] = createCertFromStaticData(leafOnAllowList_Cert, sizeof(leafOnAllowList_Cert)), - NULL, "allowlist: create leaf cert"); - isnt(certs[1] = createCertFromStaticData(ca1_Cert, sizeof(ca1_Cert)), - NULL, "allowlist: create intermediate ca 1"); - isnt(certs[2] = createCertFromStaticData(ca2_Cert, sizeof(ca2_Cert)), - NULL, "allowlist: create intermediate ca 2"); - isnt(certs[3] = createCertFromStaticData(root_Cert, sizeof(root_Cert)), - NULL, "allowlist: create root"); - - isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 4, &kCFTypeArrayCallBacks), - NULL, "allowlist: create cert array"); - - /* create a trust reference with ssl policy */ - isnt(policy = SecPolicyCreateSSL(true, CFSTR("telegram.im")), NULL, "allowlist: create policy"); - ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "allowlist: create trust"); - - /* set evaluate date: September 12, 2016 at 1:30:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495405000.0), NULL, "allowlist: create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "allowlist: set verify date"); - - /* use a known root CA at this point in time to anchor the chain */ - isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[3], 1, &kCFTypeArrayCallBacks), - NULL, "allowlist: create anchors array"); - ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "allowlist: set anchors"); - - SecTrustResultType trustResult = kSecTrustResultInvalid; - ok_status(SecTrustEvaluate(trust, &trustResult), "allowlist: evaluate"); - -#if 0 - /* expected result is kSecTrustResultUnspecified since cert is on allow list and its issuer chains to a trusted root */ - ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", - (int)trustResult); -#else - #if RADAR_32792206 - /* this certificate was on the allow list prior to v5, and list hasn't yet updated. */ - if (trustResult == kSecTrustResultUnspecified) { - trustResult = kSecTrustResultRecoverableTrustFailure; - } - #endif - /* this certificate is no longer on the allow list: */ - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - - /* clean up */ - for(CFIndex idx=0; idx < 4; idx++) { - if (certs[idx]) { CFRelease(certs[idx]); } - } - if (policy) { CFRelease(policy); } - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - if (certArray) { CFRelease(certArray); } - if (anchorsArray) { CFRelease(anchorsArray); } -} - -static void TestLeafNotOnAllowList() -{ - SecCertificateRef certs[4]; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFDateRef date = NULL; - CFArrayRef certArray = NULL; - CFArrayRef anchorsArray = NULL; - - isnt(certs[0] = createCertFromStaticData(leafNotOnAllowList_Cert, sizeof(leafNotOnAllowList_Cert)), - NULL, "!allowlist: create leaf cert"); - isnt(certs[1] = createCertFromStaticData(ca1_Cert, sizeof(ca1_Cert)), - NULL, "!allowlist: create intermediate ca 1"); - isnt(certs[2] = createCertFromStaticData(ca2_Cert, sizeof(ca2_Cert)), - NULL, "!allowlist: create intermediate ca 2"); - isnt(certs[3] = createCertFromStaticData(root_Cert, sizeof(root_Cert)), - NULL, "!allowlist: create root"); - - isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 4, &kCFTypeArrayCallBacks), - NULL, "!allowlist: create cert array"); - - /* create a trust reference with basic policy */ - isnt(policy = SecPolicyCreateBasicX509(), NULL, "!allowlist: create policy"); - ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "!allowlist: create trust"); - - /* set evaluate date: September 7, 2016 at 9:00:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495000000.0), NULL, "!allowlist: create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "!allowlist: set verify date"); - - /* use a known root CA at this point in time to anchor the chain */ - isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[3], 1, &kCFTypeArrayCallBacks), - NULL, "allowlist: create anchors array"); - ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "!allowlist: set anchors"); - - SecTrustResultType trustResult = kSecTrustResultInvalid; - ok_status(SecTrustEvaluate(trust, &trustResult), "!allowlist: evaluate"); - - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); - - /* clean up */ - for(CFIndex idx=0; idx < 4; idx++) { - if (certs[idx]) { CFRelease(certs[idx]); } - } - if (policy) { CFRelease(policy); } - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - if (certArray) { CFRelease(certArray); } - if (anchorsArray) { CFRelease(anchorsArray); } -} - -static void TestAllowListForRootCA(void) -{ - SecCertificateRef test0[2] = {NULL,NULL}; - SecCertificateRef test1[2] = {NULL,NULL}; - SecCertificateRef test1e[2] = {NULL,NULL}; - SecCertificateRef test2[2] = {NULL,NULL}; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CFDateRef date = NULL; - SecTrustResultType trustResult; - - isnt(test0[0] = createCertFromStaticData(cert0, sizeof(cert0)), - NULL, "create first leaf"); - isnt(test1[0] = createCertFromStaticData(cert1, sizeof(cert1)), - NULL, "create second leaf"); - isnt(test1e[0] = createCertFromStaticData(cert1_expired, sizeof(cert1_expired)), - NULL, "create second leaf (expired)"); - isnt(test2[0] = createCertFromStaticData(cert2, sizeof(cert2)), - NULL, "create third leaf"); - - isnt(test0[1] = createCertFromStaticData(intermediate0, sizeof(intermediate0)), - NULL, "create intermediate"); - isnt(test1[1] = createCertFromStaticData(intermediate1, sizeof(intermediate1)), - NULL, "create intermediate"); - isnt(test1e[1] = createCertFromStaticData(intermediate1, sizeof(intermediate1)), - NULL, "create intermediate"); - isnt(test2[1] = createCertFromStaticData(intermediate2, sizeof(intermediate2)), - NULL, "create intermediate"); - - CFArrayRef certs0 = CFArrayCreate(kCFAllocatorDefault, (const void **)test0, 2, &kCFTypeArrayCallBacks); - CFArrayRef certs1 = CFArrayCreate(kCFAllocatorDefault, (const void **)test1, 2, &kCFTypeArrayCallBacks); - CFArrayRef certs1e = CFArrayCreate(kCFAllocatorDefault, (const void **)test1e, 2, &kCFTypeArrayCallBacks); - CFArrayRef certs2 = CFArrayCreate(kCFAllocatorDefault, (const void **)test2, 2, &kCFTypeArrayCallBacks); - - /* - * Allowlisted certificates issued by untrusted root CA. - */ - isnt(policy = SecPolicyCreateBasicX509(), NULL, "create policy"); - ok_status(SecTrustCreateWithCertificates(certs0, policy, &trust), "create trust"); - /* set evaluate date within validity range: September 12, 2016 at 1:30:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495405000.0), NULL, "create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "set verify date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); -#if 0 - /* successful trust result expected since this is on the allow list */ - ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", - (int)trustResult); -#else - #if RADAR_32792206 - /* this certificate was on the allow list prior to v5, and list hasn't yet updated. */ - if (trustResult == kSecTrustResultUnspecified) { - trustResult = kSecTrustResultRecoverableTrustFailure; - } - #endif - /* this certificate is no longer on the allow list: */ - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - - ok_status(SecTrustCreateWithCertificates(certs1, policy, &trust), "create trust"); - /* set evaluate date within validity range: September 12, 2016 at 1:30:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495405000.0), NULL, "create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "set verify date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); -#if 0 - /* Note: this certificate has expired and was removed from the allowlist, - so we currently expect a revoked trust failure despite the verify date. */ - ok(trustResult == kSecTrustResultFatalTrustFailure, "trustResult 6 expected (got %d)", - (int)trustResult); -#else - /* there is no longer an allowlist: */ - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - - ok_status(SecTrustCreateWithCertificates(certs2, policy, &trust), "create trust"); - /* set evaluate date within validity range: September 12, 2016 at 1:30:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495405000.0), NULL, "create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "set verify date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); -#if 0 - /* successful trust result expected since this is on the allow list */ - ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", - (int)trustResult); -#else - #if RADAR_32792206 - /* this certificate was on the allow list prior to v5, and list hasn't yet updated. */ - if (trustResult == kSecTrustResultUnspecified) { - trustResult = kSecTrustResultRecoverableTrustFailure; - } - #endif - /* this certificate is no longer on the allow list: */ - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - - /* - * Same certificate, on allow list but past expiration. Expect to fail. - */ - if (date) { CFRelease(date); } - isnt(date = CFDateCreate(NULL, 667680000.0), NULL, "create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "set date to far future so certs are expired"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); -#if 0 - ok(trustResult == kSecTrustResultRecoverableTrustFailure, "trustResult 5 expected (got %d)", - (int)trustResult); -#else - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - - /* - * Expired certificate not on allow list. Expect to fail. - */ - ok_status(SecTrustCreateWithCertificates(certs1e, policy, &trust), "create trust"); - /* set evaluate date within validity range: September 12, 2016 at 1:30:00 PM PDT */ - isnt(date = CFDateCreate(NULL, 495405000.0), NULL, "create date"); - ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "set verify date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); -#if 0 - /* Note: because this certificate is not on the allow list, and the allow list is complete, - we now expect it to be treated as revoked regardless of expiration status. */ - ok(trustResult == kSecTrustResultFatalTrustFailure, "trustResult 6 expected (got %d)", - (int)trustResult); -#else - /* there is no longer an allowlist: */ - /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) - or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ - ok(trustResult == kSecTrustResultRecoverableTrustFailure || - trustResult == kSecTrustResultFatalTrustFailure, - "trustResult 5 or 6 expected (got %d)", (int)trustResult); -#endif - if (trust) { CFRelease(trust); } - if (date) { CFRelease(date); } - - - /* Clean up. */ - if (policy) { CFRelease(policy); } - if (certs0) { CFRelease(certs0); } - if (certs1) { CFRelease(certs1); } - if (certs1e) { CFRelease(certs1e); } - if (certs2) { CFRelease(certs2); } - - if (test0[0]) { CFRelease(test0[0]); } - if (test0[1]) { CFRelease(test0[1]); } - if (test1[0]) { CFRelease(test1[0]); } - if (test1[1]) { CFRelease(test1[1]); } - if (test1e[0]) { CFRelease(test1e[0]); } - if (test1e[1]) { CFRelease(test1e[1]); } - if (test2[0]) { CFRelease(test2[0]); } - if (test2[1]) { CFRelease(test2[1]); } -} - -static void TestDateBasedAllowListForRootCA(void) { - SecCertificateRef root = NULL, beforeInt = NULL, afterInt = NULL, - beforeLeaf = NULL, afterLeaf = NULL; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - NSArray *anchors = nil, *certs = nil; - NSDate *verifyDate = nil; - SecTrustResultType trustResult = kSecTrustResultInvalid; - - require(root = SecCertificateCreateWithBytes(NULL, _datetest_root, sizeof(_datetest_root)), out); - require(beforeInt = SecCertificateCreateWithBytes(NULL, _datetest_before_int, sizeof(_datetest_before_int)), out); - require(afterInt = SecCertificateCreateWithBytes(NULL, _datetest_after_int, sizeof(_datetest_after_int)), out); - require(beforeLeaf = SecCertificateCreateWithBytes(NULL, _datetest_before_leaf, sizeof(_datetest_before_leaf)), out); - require(afterLeaf = SecCertificateCreateWithBytes(NULL, _datetest_after_leaf, sizeof(_datetest_after_leaf)), out); - - anchors = @[(__bridge id)root]; - require(policy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com")), out); - verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:504000000.0]; /* 21 Dec 2016 */ - - /* Leaf issued before cutoff should pass */ - certs = @[(__bridge id)beforeLeaf, (__bridge id)beforeInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultUnspecified, "leaf issued before cutoff failed evaluation"); - CFReleaseNull(trust); - trustResult = kSecTrustResultInvalid; - - /* Leaf issued after cutoff should fail */ - certs = @[(__bridge id)afterLeaf, (__bridge id)beforeInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultFatalTrustFailure, "leaf issued after cutoff succeeded evaluation"); - CFReleaseNull(trust); - trustResult = kSecTrustResultInvalid; - - /* Intermediate issued after cutoff should fail (even for leaf issued before) */ - certs = @[(__bridge id)beforeLeaf, (__bridge id)afterInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultFatalTrustFailure, "intermediate issued after cutoff succeeded evaluation"); - CFReleaseNull(trust); - trustResult = kSecTrustResultInvalid; - - /* Intermediate issued after cutoff should fail */ - certs = @[(__bridge id)afterLeaf, (__bridge id)afterInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultFatalTrustFailure, "intermediate issued before cutoff succeeded evaluation"); - CFReleaseNull(trust); - trustResult = kSecTrustResultInvalid; - - /* Leaf issued before cutoff should choose acceptable path */ - certs = @[(__bridge id)beforeLeaf, (__bridge id) afterInt, (__bridge id)beforeInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultUnspecified, "leaf issued before cutoff failed evaluation (multi-path)"); - CFReleaseNull(trust); - trustResult = kSecTrustResultInvalid; - - /* No good path for leaf issued after cutoff */ - certs = @[(__bridge id)afterLeaf, (__bridge id)beforeInt, (__bridge id)afterInt]; - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - is(trustResult, kSecTrustResultFatalTrustFailure, "leaf issued after cutoff succeeded evaluation (multi-path)"); - -out: - CFReleaseNull(root); - CFReleaseNull(beforeInt); - CFReleaseNull(afterInt); - CFReleaseNull(beforeLeaf); - CFReleaseNull(afterLeaf); - CFReleaseNull(policy); - CFReleaseNull(trust); -} - -static void TestLeafOnAllowListOtherFailures(void) -{ - SecCertificateRef certs[4]; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - NSArray *anchors = nil, *certArray = nil; - NSDate *verifyDate = nil; - SecTrustResultType trustResult = kSecTrustResultInvalid; - - memset(certs, 0, 4 * sizeof(SecCertificateRef)); - - require(certs[0] = SecCertificateCreateWithBytes(NULL, leafOnAllowList_Cert, sizeof(leafOnAllowList_Cert)), out); - require(certs[1] = SecCertificateCreateWithBytes(NULL, ca1_Cert, sizeof(ca1_Cert)), out); - require(certs[2] = SecCertificateCreateWithBytes(NULL, ca2_Cert, sizeof(ca2_Cert)), out); - require(certs[3] = SecCertificateCreateWithBytes(NULL, root_Cert, sizeof(root_Cert)), out); - - anchors = @[(__bridge id)certs[3]]; - certArray = @[(__bridge id)certs[0], (__bridge id)certs[1], (__bridge id)certs[2], (__bridge id)certs[3]]; - verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:495405000.0]; - - /* Mismatched hostname, should fail */ - require(policy = SecPolicyCreateSSL(true, (__bridge CFStringRef)@"wrong.hostname.com"), out); - require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certArray, policy, &trust), out); - require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); - require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, - "hostname failure with cert on allow list succeeded evaluation"); - CFReleaseNull(policy); - trustResult = kSecTrustResultInvalid; - - /* Wrong EKU, should fail */ - require(policy = SecPolicyCreateCodeSigning(), out); - require_noerr(SecTrustSetPolicies(trust, policy), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, - "EKU failure with cert on allow list succeeded evaluation"); - CFReleaseNull(policy); - trustResult = kSecTrustResultInvalid; - - /* Apple pinning policy, should fail */ - require(policy = SecPolicyCreateAppleSSLPinned((__bridge CFStringRef)@"aPolicy", - (__bridge CFStringRef)@"telegram.im", NULL, - (__bridge CFStringRef)@"1.2.840.113635.100.6.27.12"), out); - require_noerr(SecTrustSetPolicies(trust, policy), out); - require_noerr(SecTrustEvaluate(trust, &trustResult), out); - ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, - "Apple pinning policy with cert on allow list succeeded evaluation"); - - out: - CFReleaseNull(certs[0]); - CFReleaseNull(certs[1]); - CFReleaseNull(certs[2]); - CFReleaseNull(certs[3]); - CFReleaseNull(policy); - CFReleaseNull(trust); -} - -static void tests(void) -{ - TestAllowListForRootCA(); - TestLeafOnAllowList(); - TestLeafNotOnAllowList(); - TestDateBasedAllowListForRootCA(); - TestLeafOnAllowListOtherFailures(); -} - -int si_84_sectrust_allowlist(int argc, char *const *argv) -{ - plan_tests(68); - tests(); - - return 0; -} diff --git a/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.c b/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.c index 6aed79c3..285e7ff3 100644 --- a/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.c +++ b/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.c @@ -368,7 +368,7 @@ static void sign_tests(SecIdentityRef identity, bool isRSA) { is(sign_please(identity, SEC_OID_SHA1, false, (isRSA) ? rsa_sha1 : NULL, (isRSA) ? sizeof(rsa_sha1) : 0), errSecSuccess, "Signed with SHA-1"); - is(sign_please(identity, SEC_OID_SHA256, false, (isRSA) ? rsa_sha256 : NULL, + is(sign_please(identity, SEC_OID_SHA256, false, (isRSA) ? new_sig_alg_rsa_sha256 : NULL, (isRSA) ? sizeof(rsa_sha256) : 0), errSecSuccess, "Signed with SHA-256"); is(sign_please(identity, SEC_OID_SHA384, false, NULL, 0), errSecSuccess, "Signed with SHA-384"); diff --git a/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.h b/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.h index 371b8f69..c7ad36b9 100644 --- a/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.h +++ b/OSX/sec/Security/Regressions/secitem/si-95-cms-basic.h @@ -465,7 +465,7 @@ unsigned char rsa_sha1[] = { 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, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, - 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, + 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x29, 0xbb, 0xc2, 0xc1, 0x17, 0xb9, 0x7d, 0x8b, 0x43, 0xc6, 0x25, 0xad, 0xf1, 0xae, 0xb6, 0x26, 0x78, 0x9c, 0x92, 0x47, 0x77, 0xf8, 0xac, 0x53, 0xca, 0x17, 0x58, 0x4a, 0x8d, 0x66, 0x44, 0x99, 0x14, 0x3f, 0x63, 0x98, 0x3a, 0x7c, 0xe6, 0x65, 0xf0, 0x2a, 0x5e, 0x49, 0xbe, 0xdd, 0x40, 0x6e, 0x21, 0x43, 0xe1, 0xb9, 0x13, 0xa8, 0x31, 0xbf, 0x12, 0xb2, 0x78, 0x97, @@ -565,6 +565,89 @@ unsigned char rsa_sha256[] = { 0x45, 0xc2, 0x99, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +unsigned char new_sig_alg_rsa_sha256[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 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, 0xdc, 0x30, 0x82, 0x01, 0xd8, 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, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x0b, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xc9, 0x25, 0xbe, 0xb8, 0xf2, 0x2c, 0x7f, 0xc8, 0x3a, 0xc3, 0xc2, 0x4b, + 0xac, 0x54, 0xcf, 0xa6, 0x75, 0xaa, 0xeb, 0x40, 0x68, 0xee, 0xe2, 0xb1, 0xa8, 0x70, 0x9e, 0xe9, 0x8b, 0xf1, 0x0a, 0x85, + 0x88, 0x40, 0xef, 0xb8, 0xa5, 0x04, 0x87, 0x63, 0x03, 0xf5, 0x41, 0x81, 0x29, 0x42, 0x7f, 0x31, 0x8f, 0x5b, 0xde, 0xe8, + 0x15, 0xc1, 0xa3, 0x45, 0xf1, 0xbc, 0xff, 0x81, 0x58, 0xbd, 0xac, 0x4c, 0xa5, 0xb3, 0x30, 0x9a, 0xb8, 0x9e, 0x69, 0x10, + 0xad, 0x44, 0x7b, 0x93, 0x28, 0xba, 0xca, 0x6f, 0x2e, 0xf8, 0x1b, 0x03, 0xc2, 0x0a, 0x4a, 0x06, 0x32, 0x4d, 0x30, 0x50, + 0xb7, 0x9c, 0x57, 0x4d, 0x4b, 0x6c, 0x34, 0x53, 0xd8, 0xf5, 0xca, 0x91, 0xa5, 0xdf, 0xa6, 0x67, 0x0a, 0x2e, 0x02, 0x47, + 0x1c, 0x1c, 0xd6, 0x2b, 0xe2, 0x85, 0xc1, 0xda, 0x79, 0xa2, 0xe2, 0x1e, 0xf8, 0x5e, 0xf9, 0x76, 0x55, 0xaf, 0x61, 0xaf, + 0xde, 0x0a, 0x7b, 0xeb, 0xa1, 0xa8, 0xc6, 0xef, 0x76, 0x2f, 0x50, 0xd1, 0x0a, 0xce, 0xdb, 0x14, 0xc3, 0x13, 0x72, 0xe5, + 0x26, 0x67, 0x90, 0x19, 0x15, 0x7b, 0x79, 0x05, 0xeb, 0x20, 0xb3, 0x5a, 0x4e, 0x78, 0xae, 0x2d, 0x9c, 0xd1, 0x31, 0xfd, + 0x2e, 0xcb, 0x84, 0xb9, 0x67, 0xea, 0xaf, 0xb3, 0xc2, 0x5f, 0xf5, 0xcd, 0x7b, 0x66, 0x3f, 0xdf, 0xf7, 0xe7, 0x76, 0x46, + 0x57, 0xd9, 0xee, 0x4b, 0xb2, 0xc8, 0x7b, 0xf9, 0x88, 0xab, 0x8e, 0xca, 0xfc, 0x39, 0xd1, 0x8e, 0x1c, 0xba, 0x3e, 0x63, + 0xb7, 0xe8, 0x0e, 0x2f, 0xde, 0x6b, 0x76, 0x81, 0xbf, 0x78, 0x26, 0x0c, 0xa0, 0x2c, 0x35, 0x21, 0xde, 0xb4, 0x45, 0x0a, + 0x84, 0xea, 0x68, 0xa5, 0x37, 0xe8, 0x4a, 0xbc, 0xa6, 0xcf, 0x24, 0x85, 0x46, 0x33, 0x9e, 0xd9, 0xba, 0x58, 0x75, 0xd7, + 0x45, 0xc2, 0x99, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + /* * MARK: RSA-signed messages (with attributes) */ @@ -726,7 +809,7 @@ unsigned char rsa_sha1_attr[] = { 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x38, 0x31, 0x33, 0x32, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0xef, 0x53, 0x0b, 0xfa, 0xcf, 0x34, 0x18, 0xb3, 0x30, 0xff, 0xf8, 0x9e, 0x09, 0xb3, 0xb6, 0x21, 0xd6, 0x83, 0xb9, 0xe9, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x52, 0xbd, 0xa1, 0x0a, 0x41, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x52, 0xbd, 0xa1, 0x0a, 0x41, 0xce, 0xc1, 0xe8, 0xe8, 0x2f, 0x2e, 0x1f, 0x73, 0xd1, 0x2f, 0x2e, 0x53, 0x53, 0x21, 0xec, 0x88, 0x30, 0x6a, 0x9d, 0x58, 0x64, 0x95, 0xef, 0xf2, 0x20, 0x55, 0xb0, 0x15, 0x64, 0x02, 0x1d, 0xf9, 0x44, 0xdd, 0xcb, 0x7a, 0x9c, 0x50, 0x10, 0xea, 0xfa, 0x6f, 0x07, 0x64, 0xaf, 0x30, 0x6e, 0xe2, 0xc1, 0x34, 0x55, 0xd0, 0x6a, 0x6e, 0xe1, 0x09, 0x91, 0xb7, 0xe3, 0x7b, @@ -814,7 +897,7 @@ unsigned char rsa_sha256_attr[] = { 0x31, 0x33, 0x32, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x33, 0x1f, 0x3a, 0xc4, 0x95, 0x97, 0x64, 0x1c, 0x99, 0x9b, 0x37, 0xc8, 0xf2, 0xba, 0xd0, 0xb4, 0x38, 0xa5, 0x9c, 0x3a, 0xa3, 0x78, 0xf9, 0xfb, 0x66, 0x28, 0x4e, 0x6a, 0x90, 0xcc, 0x0e, 0x4c, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xae, 0x6d, 0xa9, 0xa7, 0xee, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xae, 0x6d, 0xa9, 0xa7, 0xee, 0x0c, 0x94, 0x1b, 0xf3, 0x93, 0x40, 0x43, 0x11, 0x41, 0x20, 0x11, 0x60, 0xd9, 0x4e, 0xb6, 0x2d, 0x3e, 0x98, 0xfe, 0x06, 0xd2, 0xc4, 0xe4, 0x0a, 0x66, 0xdc, 0xbb, 0xbd, 0x4d, 0x8e, 0xcb, 0xe1, 0x87, 0x39, 0x3f, 0xb3, 0x4b, 0xf8, 0xe7, 0x18, 0x6f, 0x39, 0xad, 0x01, 0xd4, 0xe8, 0x85, 0x8c, 0x84, 0x96, 0x2c, 0x3a, 0xd4, 0xcf, 0x3c, 0xe5, 0x05, 0xdd, 0xc7, 0xc0, diff --git a/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c b/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c index 44b57a7d..3abf319c 100644 --- a/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c +++ b/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c @@ -411,8 +411,8 @@ static bool merge_der_in_to_data(const void *der1, size_t der1_len, const void * CFPropertyListRef dict1 = NULL; CFPropertyListRef dict2 = NULL; - der_decode_plist(NULL, kCFPropertyListImmutable, &dict1, NULL, der1, der1 + der1_len); - der_decode_plist(NULL, kCFPropertyListImmutable, &dict2, NULL, der2, der2 + der2_len); + der_decode_plist(NULL, &dict1, NULL, der1, der1 + der1_len); + der_decode_plist(NULL, &dict2, NULL, der2, der2 + der2_len); if (dict1 && dict2) { CFMutableDictionaryRef result_dict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dict1); CFDictionaryForEach(dict2, ^(const void *key, const void *value) { @@ -463,7 +463,7 @@ static int aks_crypt_acl(CFTypeRef operation, keybag_handle_t keybag, require_action_string(der, out, aks_return = kAKSReturnError, "aks_ref_key_decrypt failed"); CFPropertyListRef decoded_data = NULL; - der_decode_plist(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_data, NULL, der, der + der_len); + der_decode_plist(kCFAllocatorDefault, &decoded_data, NULL, der, der + der_len); require_action_string(decoded_data, out, aks_return = kAKSReturnError, "der_decode_plist failed"); if (CFGetTypeID(decoded_data) == CFDataGetTypeID()) { CFDataSetLength(dest, 0); diff --git a/OSX/sec/Security/Regressions/vmdh/vmdh-41-example.c b/OSX/sec/Security/Regressions/vmdh/vmdh-41-example.c index 089c59ee..fed52229 100644 --- a/OSX/sec/Security/Regressions/vmdh/vmdh-41-example.c +++ b/OSX/sec/Security/Regressions/vmdh/vmdh-41-example.c @@ -19,16 +19,14 @@ //these are copies of SecDH_gp() and SecDH_priv() static inline ccdh_gp_t vmdh_gp(struct vmdh *dh) { - return (ccdh_gp_t)dh; + return (ccdh_gp_t)dh; } static inline ccdh_full_ctx_t vmdh_priv(struct vmdh *dh) { ccdh_gp_t gp = vmdh_gp(dh); cc_size s = ccn_sizeof_n(ccdh_gp_n(gp)); - ccdh_full_ctx_t priv = (ccdh_full_ctx_t)((char *) dh + ccdh_gp_size(s)); - - return priv; + return (ccdh_full_ctx_t)cc_pad_align((uintptr_t)dh + ccdh_gp_size(s)); } static uint32_t param_g = 5; diff --git a/OSX/sec/Security/Regressions/vmdh/vmdh-42-example2.c b/OSX/sec/Security/Regressions/vmdh/vmdh-42-example2.c index 3c79e75e..ded731c7 100644 --- a/OSX/sec/Security/Regressions/vmdh/vmdh-42-example2.c +++ b/OSX/sec/Security/Regressions/vmdh/vmdh-42-example2.c @@ -19,16 +19,14 @@ //these are copies of SecDH_gp() and SecDH_priv() static inline ccdh_gp_t vmdh_gp(struct vmdh *dh) { - return (ccdh_gp_t)dh; + return (ccdh_gp_t)dh; } static inline ccdh_full_ctx_t vmdh_priv(struct vmdh *dh) { ccdh_gp_t gp = vmdh_gp(dh); cc_size s = ccn_sizeof_n(ccdh_gp_n(gp)); - ccdh_full_ctx_t priv = (ccdh_full_ctx_t)((char *) dh + ccdh_gp_size(s)); - - return priv; + return (ccdh_full_ctx_t)cc_pad_align((uintptr_t)dh + ccdh_gp_size(s)); } static uint32_t param_g = 5; diff --git a/OSX/sec/Security/SecAccessControl.m b/OSX/sec/Security/SecAccessControl.m index 652e72e8..e9ef95c6 100644 --- a/OSX/sec/Security/SecAccessControl.m +++ b/OSX/sec/Security/SecAccessControl.m @@ -478,7 +478,7 @@ SecAccessControlRef SecAccessControlCreateFromData(CFAllocatorRef allocator, CFD 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); + require_quiet(der = der_decode_plist(0, &plist, error, der, der_end), errOut); if (der != der_end) { SecError(errSecDecode, error, CFSTR("trailing garbage at end of SecAccessControl data")); goto errOut; diff --git a/OSX/sec/Security/SecBase64.c b/OSX/sec/Security/SecBase64.c index b92d8dba..1c67bb98 100644 --- a/OSX/sec/Security/SecBase64.c +++ b/OSX/sec/Security/SecBase64.c @@ -43,7 +43,7 @@ #include "SecBase64.h" -#include +#include #include #include diff --git a/OSX/sec/Security/SecCTKKey.m b/OSX/sec/Security/SecCTKKey.m index 9d43e27a..fd0a9a6f 100644 --- a/OSX/sec/Security/SecCTKKey.m +++ b/OSX/sec/Security/SecCTKKey.m @@ -353,6 +353,13 @@ out: return TRUE; } +static Boolean SecCTKKeyIsEqual(SecKeyRef key1, SecKeyRef key2) { + SecCTKKeyData *kd1 = key1->key; + SecCTKKeyData *kd2 = key2->key; + + return CFEqual(kd1->token_id, kd2->token_id) && CFEqual(kd1->object_id, kd2->object_id); +} + static SecKeyDescriptor kSecCTKKeyDescriptor = { .version = kSecKeyDescriptorVersion, .name = "CTKKey", @@ -365,6 +372,7 @@ static SecKeyDescriptor kSecCTKKeyDescriptor = { .getAlgorithmID = SecCTKGetAlgorithmID, .copyPublic = SecCTKKeyCopyPublicOctets, .copyOperationResult = SecCTKKeyCopyOperationResult, + .isEqual = SecCTKKeyIsEqual, .createDuplicate = SecCTKKeyCreateDuplicate, .setParameter = SecCTKKeySetParameter, }; @@ -401,14 +409,6 @@ SecKeyRef SecKeyCreateCTKKey(CFAllocatorRef allocator, CFDictionaryRef refAttrib CFDictionarySetValue(SecCFDictionaryCOWGetMutable(&kd->attributes), kSecAttrIsPrivate, kCFBooleanTrue); } - // Convert some attributes which are stored as numbers in iOS keychain but a lot of code counts that the values - // are actually strings as specified by kSecAttrXxx constants. - static const CFStringRef *numericAttributes[] = { - &kSecAttrKeyType, - &kSecAttrKeyClass, - NULL, - }; - CFMutableDictionaryRef attrs = NULL; if (kd->token == NULL) { require_quiet(kd->token = SecCTKKeyCopyToken(key, error), out); @@ -432,6 +432,14 @@ SecKeyRef SecKeyCreateCTKKey(CFAllocatorRef allocator, CFDictionaryRef refAttrib require_quiet(kd->token != NULL && kd->object_id != NULL, out); } + // Convert some attributes which are stored as numbers in iOS keychain but a lot of code counts that the values + // are actually strings as specified by kSecAttrXxx constants. + static const CFStringRef *numericAttributes[] = { + &kSecAttrKeyType, + &kSecAttrKeyClass, + NULL, + }; + for (const CFStringRef **attrName = &numericAttributes[0]; *attrName != NULL; attrName++) { CFTypeRef value = CFDictionaryGetValue(kd->attributes.dictionary, **attrName); if (value != NULL && CFGetTypeID(value) == CFNumberGetTypeID()) { @@ -445,6 +453,11 @@ SecKeyRef SecKeyCreateCTKKey(CFAllocatorRef allocator, CFDictionaryRef refAttrib } } } + + // Sanitize some important attributes. + CFDictionarySetValue(SecCFDictionaryCOWGetMutable(&kd->attributes), kSecClass, kSecClassKey); + CFDictionarySetValue(SecCFDictionaryCOWGetMutable(&kd->attributes), kSecAttrKeyClass, kSecAttrKeyClassPrivate); + result = (SecKeyRef)CFRetain(key); out: @@ -523,7 +536,17 @@ SecKeyRef SecKeyCopyAttestationKey(SecKeyAttestationKeyType keyType, CFErrorRef static const uint8_t uikProposedObjectIDBytes[] = { 0x04, 22, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 't', 'o', 'k', 'e', 'n', '.', 'u', 'i', 'k', 'p' }; static const uint8_t casdObjectIDBytes[] = { 0x04, 27, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 'c', 'e', 'l', 'e', 'm', 't', 'o', 'k', 'e', 'n', '.', 'c', 'a', 's', 'd' }; - + + // [[TKTLVBERRecord alloc] initWithPropertyList:[@"com.apple.setoken.oikc" dataUsingEncoding:NSUTF8StringEncoding]].data + static const uint8_t oikCommittedObjectIDBytes[] = { 0x04, 22, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 't', 'o', 'k', 'e', 'n', '.', 'o', 'i', 'k', 'c' }; + // [[TKTLVBERRecord alloc] initWithPropertyList:[@"com.apple.setoken.oikp" dataUsingEncoding:NSUTF8StringEncoding]].data + static const uint8_t oikProposedObjectIDBytes[] = { 0x04, 22, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 't', 'o', 'k', 'e', 'n', '.', 'o', 'i', 'k', 'p' }; + + // [[TKTLVBERRecord alloc] initWithPropertyList:[@"com.apple.setoken.dakc" dataUsingEncoding:NSUTF8StringEncoding]].data + static const uint8_t dakCommittedObjectIDBytes[] = { 0x04, 22, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 't', 'o', 'k', 'e', 'n', '.', 'd', 'a', 'k', 'c' }; + // [[TKTLVBERRecord alloc] initWithPropertyList:[@"com.apple.setoken.dakp" dataUsingEncoding:NSUTF8StringEncoding]].data + static const uint8_t dakProposedObjectIDBytes[] = { 0x04, 22, 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', '.', 's', 'e', 't', 'o', 'k', 'e', 'n', '.', 'd', 'a', 'k', 'p' }; + CFStringRef token = kSecAttrTokenIDAppleKeyStore; switch (keyType) { @@ -543,6 +566,18 @@ SecKeyRef SecKeyCopyAttestationKey(SecKeyAttestationKeyType keyType, CFErrorRef object_id = CFDataCreate(kCFAllocatorDefault, casdObjectIDBytes, sizeof(casdObjectIDBytes)); token = kSecAttrTokenIDSecureElement; break; + case kSecKeyAttestationKeyTypeOIKCommitted: + object_id = CFDataCreate(kCFAllocatorDefault, oikCommittedObjectIDBytes, sizeof(uikCommittedObjectIDBytes)); + break; + case kSecKeyAttestationKeyTypeOIKProposed: + object_id = CFDataCreate(kCFAllocatorDefault, oikProposedObjectIDBytes, sizeof(uikProposedObjectIDBytes)); + break; + case kSecKeyAttestationKeyTypeDAKCommitted: + object_id = CFDataCreate(kCFAllocatorDefault, dakCommittedObjectIDBytes, sizeof(uikCommittedObjectIDBytes)); + break; + case kSecKeyAttestationKeyTypeDAKProposed: + object_id = CFDataCreate(kCFAllocatorDefault, dakProposedObjectIDBytes, sizeof(uikProposedObjectIDBytes)); + break; default: SecError(errSecParam, error, CFSTR("unexpected attestation key type %d"), (int)keyType); goto out; @@ -639,10 +674,6 @@ Boolean SecKeyControlLifetime(SecKeyRef key, SecKeyControlLifetimeType type, CFE }, 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); diff --git a/OSX/sec/Security/SecCertificate.c b/OSX/sec/Security/SecCertificate.c index 204ec41a..dd5f50d4 100644 --- a/OSX/sec/Security/SecCertificate.c +++ b/OSX/sec/Security/SecCertificate.c @@ -71,6 +71,8 @@ #include "AppleiPhoneDeviceCACertificates.h" #include #include +#include "AppleExternalRootCertificates.h" +#include #pragma clang diagnostic ignored "-Wformat=2" @@ -85,6 +87,14 @@ #define IPv4ADDRLEN 4 // 4 octets #define IPv6ADDRLEN 16 // 16 octets +#define MAX_EXTENSIONS 10000 +#define MAX_ATTRIBUTE_TYPE_AND_VALUES 1024 +#define MAX_CRL_DPS 1024 +#define MAX_CERTIFICATE_POLICIES 8192 +#define MAX_POLICY_MAPPINGS 8192 +#define MAX_EKUS 8192 +#define MAX_AIAS 1024 + typedef struct SecCertificateExtension { DERItem extnID; bool critical; @@ -300,8 +310,6 @@ static CFHashCode SecCertificateHash(CFTypeRef cf) { return (hashCode + der_length + sig_length); } -#if 1 - /************************************************************************/ /************************* General Name Parsing *************************/ /************************************************************************/ @@ -390,159 +398,15 @@ OSStatus SecCertificateParseGeneralNames(const DERItem *generalNames, void *cont DERDecodedInfo generalNamesContent; DERReturn drtn = DERDecodeItem(generalNames, &generalNamesContent); require_noerr_quiet(drtn, badDER); + // GeneralNames ::= SEQUENCE SIZE (1..MAX) require_quiet(generalNamesContent.tag == ASN1_CONSTR_SEQUENCE, badDER); + require_quiet(generalNamesContent.content.length > 0, badDER); // not defining a max due to use of large number of SANs return parseGeneralNamesContent(&generalNamesContent.content, context, callback); badDER: return errSecInvalidCertificate; } -#else - -/* - GeneralName ::= CHOICE { - otherName [0] OtherName, - rfc822Name [1] IA5String, - dNSName [2] IA5String, - x400Address [3] ORAddress, - directoryName [4] Name, - ediPartyName [5] EDIPartyName, - uniformResourceIdentifier [6] IA5String, - iPAddress [7] OCTET STRING, - registeredID [8] OBJECT IDENTIFIER} - - EDIPartyName ::= SEQUENCE { - nameAssigner [0] DirectoryString OPTIONAL, - partyName [1] DirectoryString } - */ -static OSStatus parseGeneralNameContentProperty(DERTag tag, - const DERItem *generalNameContent, SecCEGeneralName *generalName) { - switch (tag) { - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0: - generalName->nameType = GNT_OtherName; - generalName->berEncoded = true; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | 1: - /* IA5String. */ - generalName->nameType = GNT_RFC822Name; - generalName->berEncoded = false; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | 2: - /* IA5String. */ - generalName->nameType = GNT_DNSName; - generalName->berEncoded = false; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3: - generalName->nameType = GNT_X400Address; - generalName->berEncoded = true; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 4: - generalName->nameType = GNT_DirectoryName; - generalName->berEncoded = true; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 5: - generalName->nameType = GNT_EdiPartyName; - generalName->berEncoded = true; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 6: - { - /* Technically I don't think this is valid, but there are certs out - in the wild that use a constructed IA5String. In particular the - VeriSign Time Stamping Authority CA.cer does this. */ - DERDecodedInfo decoded; - require_noerr(DERDecodeItem(generalNameContent, &decoded), badDER); - require(decoded.tag == ASN1_IA5_STRING, badDER); - generalName->nameType = GNT_URI; - generalName->berEncoded = false; - generalName->name = decoded.content; - break; - } - case ASN1_CONTEXT_SPECIFIC | 6: - generalName->nameType = GNT_URI; - generalName->berEncoded = false; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | 7: - /* @@@ This is the IP Address as an OCTECT STRING. For IPv4 it's - 8 octects, addr/mask for ipv6 it's 32. */ - generalName->nameType = GNT_IPAddress; - generalName->berEncoded = false; - generalName->name = *generalNameContent; - break; - case ASN1_CONTEXT_SPECIFIC | 8: - /* name is the content of an OID. */ - generalName->nameType = GNT_RegisteredID; - generalName->berEncoded = false; - generalName->name = *generalNameContent; - break; - default: - goto badDER; - break; - } - return errSecSuccess; -badDER: - return errSecInvalidCertificate; -} - -/* - GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - */ -static OSStatus parseGeneralNamesContent(const DERItem *generalNamesContent, - CFIndex *count, SecCEGeneralName **name) { - SecCEGeneralName *generalNames = NULL; - DERSequence gnSeq; - DERReturn drtn = DERDecodeSeqContentInit(generalNamesContent, &gnSeq); - require_noerr_quiet(drtn, badDER); - DERDecodedInfo generalNameContent; - CFIndex generalNamesCount = 0; - while ((drtn = DERDecodeSeqNext(&gnSeq, &generalNameContent)) == - DR_Success) { - ++generalNamesCount; - } - require_quiet(drtn == DR_EndOfSequence, badDER); - - require(generalNames = calloc(generalNamesCount, sizeof(SecCEGeneralName)), - badDER); - DERDecodeSeqContentInit(generalNamesContent, &gnSeq); - CFIndex ix = 0; - while ((drtn = DERDecodeSeqNext(&gnSeq, &generalNameContent)) == - DR_Success) { - if (!parseGeneralNameContentProperty(generalNameContent.tag, - &generalNameContent.content, &generalNames[ix])) { - goto badDER; - } - ++ix; - } - *count = generalNamesCount; - *name = generalNames; - return errSecSuccess; - -badDER: - if (generalNames) - free(generalNames); - return errSecInvalidCertificate; -} - -static OSStatus parseGeneralNames(const DERItem *generalNames, - CFIndex *count, SecCEGeneralName **name) { - DERDecodedInfo generalNamesContent; - DERReturn drtn = DERDecodeItem(generalNames, &generalNamesContent); - require_noerr_quiet(drtn, badDER); - require_quiet(generalNamesContent.tag == ASN1_CONSTR_SEQUENCE, - badDER); - parseGeneralNamesContent(&generalNamesContent.content, count, name); - return errSecSuccess; -badDER: - return errSecInvalidCertificate; -} -#endif - /************************************************************************/ /************************** X.509 Name Parsing **************************/ /************************************************************************/ @@ -579,25 +443,30 @@ badDER: } static OSStatus parseX501NameContent(const DERItem *x501NameContent, void *context, - parseX501NameCallback callback, bool localized) { - DERSequence derSeq; - DERReturn drtn = DERDecodeSeqContentInit(x501NameContent, &derSeq); - require_noerr_quiet(drtn, badDER); - DERDecodedInfo currDecoded; - while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { - require_quiet(currDecoded.tag == ASN1_CONSTR_SET, badDER); - OSStatus status = parseRDNContent(&currDecoded.content, context, - callback, localized); - if (status) { - return status; - } - } - require_quiet(drtn == DR_EndOfSequence, badDER); + parseX501NameCallback callback, bool localized) { + DERSequence derSeq; + DERReturn drtn = DERDecodeSeqContentInit(x501NameContent, &derSeq); + require_noerr_quiet(drtn, badDER); + DERDecodedInfo currDecoded; + int atv_count = 0; + while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { + /* RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue */ + require_quiet(currDecoded.tag == ASN1_CONSTR_SET, badDER); + require_quiet(currDecoded.content.length > 0, badDER); + OSStatus status = parseRDNContent(&currDecoded.content, context, + callback, localized); + if (status) { + return status; + } + atv_count++; + require_quiet(atv_count < MAX_ATTRIBUTE_TYPE_AND_VALUES, badDER); + } + require_quiet(drtn == DR_EndOfSequence, badDER); - return errSecSuccess; + return errSecSuccess; badDER: - return errSecInvalidCertificate; + return errSecInvalidCertificate; } static OSStatus parseX501Name(const DERItem *x501Name, void *context, @@ -676,11 +545,23 @@ static bool SecCEPPrivateKeyUsagePeriod(SecCertificateRef certificate, return true; } +static OSStatus verifySubjectAltGeneralName(void *context, SecCEGeneralNameType type, + const DERItem *value) { + // Nothing to do for now + return errSecSuccess; +} + static bool SecCEPSubjectAltName(SecCertificateRef certificate, const SecCertificateExtension *extn) { secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + // Make sure that the SAN is parse-able + require_noerr_quiet(SecCertificateParseGeneralNames(&extn->extnValue, NULL, verifySubjectAltGeneralName), badDER); certificate->_subjectAltName = extn; return true; +badDER: + certificate->_subjectAltName = NULL; + secwarning("Invalid SubjectAltName Extension"); + return false; } static bool SecCEPIssuerAltName(SecCertificateRef certificate, @@ -849,7 +730,9 @@ static bool SecCEPCrlDistributionPoints(SecCertificateRef certificate, DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &crlDPSeq); require_noerr_quiet(drtn, badDER); require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + require_quiet(crlDPSeq.nextItem != crlDPSeq.end, badDER); DERDecodedInfo dpContent; + int crldp_count = 0; while ((drtn = DERDecodeSeqNext(&crlDPSeq, &dpContent)) == DR_Success) { require_quiet(dpContent.tag == ASN1_CONSTR_SEQUENCE, badDER); DERDistributionPoint dp; @@ -879,6 +762,8 @@ static bool SecCEPCrlDistributionPoints(SecCertificateRef certificate, appendCRLDPFromGeneralNames); require_noerr_quiet(drtn, badDER); } + crldp_count++; + require_quiet(crldp_count < MAX_CRL_DPS, badDER); } require_quiet(drtn == DR_EndOfSequence, badDER); return true; @@ -901,8 +786,6 @@ badDER: policyQualifierId PolicyQualifierId, qualifier ANY DEFINED BY policyQualifierId } */ -/* maximum number of policies of 8192 seems more than adequate */ -#define MAX_CERTIFICATE_POLICIES 8192 static bool SecCEPCertificatePolicies(SecCertificateRef certificate, const SecCertificateExtension *extn) { secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); @@ -920,14 +803,14 @@ static bool SecCEPCertificatePolicies(SecCertificateRef certificate, policy_count++; } require_quiet(drtn == DR_EndOfSequence, badDER); - require_quiet(policies = (SecCEPolicyInformation *)malloc(sizeof(SecCEPolicyInformation) - * (policy_count > 0 ? policy_count : 1)), + require_quiet(policy_count > 0, badDER); + require_quiet(policies = (SecCEPolicyInformation *)malloc(sizeof(SecCEPolicyInformation) * policy_count), badDER); drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &piSeq); require_noerr_quiet(drtn, badDER); DERSize policy_ix = 0; - while ((policy_ix < (policy_count > 0 ? policy_count : 1)) && - (drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { + while ((policy_ix < policy_count) && + (DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { DERPolicyInformation pi; drtn = DERParseSequenceContent(&piContent.content, DERNumPolicyInformationItemSpecs, @@ -957,7 +840,6 @@ badDER: issuerDomainPolicy CertPolicyId, subjectDomainPolicy CertPolicyId } */ -#define MAX_POLICY_MAPPINGS 8192 static bool SecCEPPolicyMappings(SecCertificateRef certificate, const SecCertificateExtension *extn) { secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); @@ -975,14 +857,14 @@ static bool SecCEPPolicyMappings(SecCertificateRef certificate, mapping_count++; } require_quiet(drtn == DR_EndOfSequence, badDER); - require_quiet(mappings = (SecCEPolicyMapping *)malloc(sizeof(SecCEPolicyMapping) - * (mapping_count > 0 ? mapping_count : 1)), + require_quiet(mapping_count > 0, badDER); // PolicyMappings ::= SEQUENCE SIZE (1..MAX) + require_quiet(mappings = (SecCEPolicyMapping *)malloc(sizeof(SecCEPolicyMapping) * mapping_count), badDER); drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &pmSeq); require_noerr_quiet(drtn, badDER); DERSize mapping_ix = 0; - while ((mapping_ix < (mapping_count > 0 ? mapping_count : 1)) && - (drtn = DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { + while ((mapping_ix < mapping_count) && + (DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { require_quiet(pmContent.tag == ASN1_CONSTR_SEQUENCE, badDER); DERPolicyMapping pm; drtn = DERParseSequenceContent(&pmContent.content, @@ -1003,7 +885,7 @@ badDER: free(mappings); } certificate->_policyMappings.present = false; - secwarning("Invalid CertificatePolicies Extension"); + secwarning("Invalid PolicyMappings Extension"); return false; } @@ -1085,9 +967,13 @@ static bool SecCEPExtendedKeyUsage(SecCertificateRef certificate, DERTag ekuTag; DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &ekuTag, &ekuSeq); require_quiet((drtn == DR_Success) && (ekuTag == ASN1_CONSTR_SEQUENCE), badDER); + require_quiet(ekuSeq.nextItem != ekuSeq.end, badDER); // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId DERDecodedInfo ekuContent; + int eku_count = 0; while ((drtn = DERDecodeSeqNext(&ekuSeq, &ekuContent)) == DR_Success) { require_quiet(ekuContent.tag == ASN1_OBJECT_ID, badDER); + eku_count++; + require_quiet(eku_count < MAX_EKUS, badDER); } require_quiet(drtn == DR_EndOfSequence, badDER); return true; @@ -1144,7 +1030,9 @@ static bool SecCEPAuthorityInfoAccess(SecCertificateRef certificate, DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &adSeq); require_noerr_quiet(drtn, badDER); require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); + require_quiet(adSeq.nextItem != adSeq.end, badDER); DERDecodedInfo adContent; + int aia_count = 0; while ((drtn = DERDecodeSeqNext(&adSeq, &adContent)) == DR_Success) { require_quiet(adContent.tag == ASN1_CONSTR_SEQUENCE, badDER); DERAccessDescription ad; @@ -1153,6 +1041,8 @@ static bool SecCEPAuthorityInfoAccess(SecCertificateRef certificate, DERAccessDescriptionItemSpecs, &ad, sizeof(ad)); require_noerr_quiet(drtn, badDER); + aia_count++; + require_quiet(aia_count < MAX_AIAS, badDER); CFMutableArrayRef *urls; if (DEROidCompare(&ad.accessMethod, &oidAdOCSP)) urls = &certificate->_ocspResponders; @@ -1818,9 +1708,10 @@ static bool SecCertificateParse(SecCertificateRef certificate) extensionCount++; } require_quiet(drtn == DR_EndOfSequence, badCert); + require_quiet(extensionCount > 0, badCert); // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension /* Put some upper limit on the number of extensions allowed. */ - require_quiet(extensionCount < 10000, badCert); + require_quiet(extensionCount < MAX_EXTENSIONS, badCert); certificate->_extensionCount = extensionCount; certificate->_extensions = malloc(sizeof(SecCertificateExtension) * (extensionCount > 0 ? extensionCount : 1)); require_quiet(certificate->_extensions, badCert); @@ -3008,7 +2899,7 @@ static void appendSerialNumberProperty(CFMutableArrayRef parent, CFStringRef lab static void appendBitStringContentNames(CFMutableArrayRef properties, CFStringRef label, const DERItem *bitStringContent, - const CFStringRef *names, CFIndex namesCount, + const __nonnull CFStringRef *names, CFIndex namesCount, bool localized) { DERSize len = bitStringContent->length - 1; require_quiet(len == 1 || len == 2, badDER); @@ -3039,7 +2930,7 @@ static void appendBitStringContentNames(CFMutableArrayRef properties, string = s; } else { string = localizedName; - CFRetain(string); + CFRetainSafe(string); } } mask >>= 1; @@ -3056,7 +2947,7 @@ badDER: static void appendBitStringNames(CFMutableArrayRef properties, CFStringRef label, const DERItem *bitString, - const CFStringRef *names, CFIndex namesCount, + const __nonnull CFStringRef *names, CFIndex namesCount, bool localized) { DERDecodedInfo bitStringContent; DERReturn drtn = DERDecodeItem(bitString, &bitStringContent); @@ -4429,10 +4320,20 @@ CFDataRef SecCertificateCopySerialNumberData( return certificate->_serialNumber; } +#if TARGET_OS_OSX && TARGET_CPU_ARM64 +/* force this implementation to be _SecCertificateCopySerialNumber on arm64 macOS. + note: the legacy function in SecCertificate.cpp is now _SecCertificateCopySerialNumber$LEGACYMAC + when both TARGET_OS_OSX and TARGET_CPU_ARM64 are true. + */ +extern CFDataRef SecCertificateCopySerialNumber_ios(SecCertificateRef certificate) __asm("_SecCertificateCopySerialNumber"); +CFDataRef SecCertificateCopySerialNumber_ios(SecCertificateRef certificate) { + return SecCertificateCopySerialNumberData(certificate, NULL); +} +#endif + #if !TARGET_OS_OSX -/* On iOS, the SecCertificateCopySerialNumber API takes one argument. */ -CFDataRef SecCertificateCopySerialNumber( - SecCertificateRef certificate) { +CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate) +{ return SecCertificateCopySerialNumberData(certificate, NULL); } #endif @@ -4653,69 +4554,59 @@ CFDataRef SecFrameworkCopyIPAddressData(CFStringRef string) { return data; } -static OSStatus appendIPAddressesFromGeneralNames(void *context, - SecCEGeneralNameType gnType, const DERItem *generalName) { - CFMutableArrayRef ipAddresses = (CFMutableArrayRef)context; - if (gnType == GNT_IPAddress) { - CFStringRef string = copyIPAddressContentDescription( - kCFAllocatorDefault, generalName); - if (string) { - CFArrayAppendValue(ipAddresses, string); - CFRelease(string); - } else { - return errSecInvalidCertificate; - } - } - return errSecSuccess; +static OSStatus appendIPAddressesFromGeneralNames(void *context, SecCEGeneralNameType gnType, const DERItem *generalName) { + CFMutableArrayRef ipAddresses = (CFMutableArrayRef)context; + if (gnType == GNT_IPAddress) { + if (generalName->length == IPv4ADDRLEN || generalName->length == IPv6ADDRLEN) { + CFDataRef address = CFDataCreate(NULL, generalName->data, generalName->length); + CFArrayAppendValue(ipAddresses, address); + CFReleaseNull(address); + } else { + return errSecInvalidCertificate; + } + } + return errSecSuccess; } CFArrayRef SecCertificateCopyIPAddresses(SecCertificateRef certificate) { - /* These can only exist in the subject alt name. */ - if (!certificate->_subjectAltName) - return NULL; - - CFMutableArrayRef ipAddresses = CFArrayCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeArrayCallBacks); - OSStatus status = SecCertificateParseGeneralNames(&certificate->_subjectAltName->extnValue, - ipAddresses, appendIPAddressesFromGeneralNames); - if (status || CFArrayGetCount(ipAddresses) == 0) { - CFRelease(ipAddresses); - ipAddresses = NULL; - } - return ipAddresses; -} + CFArrayRef ipAddresses = SecCertificateCopyIPAddressDatas(certificate); + if (!ipAddresses) { + return NULL; + } -static OSStatus appendIPAddressesFromX501Name(void *context, const DERItem *type, - const DERItem *value, CFIndex rdnIX, - bool localized) { - CFMutableArrayRef addrs = (CFMutableArrayRef)context; - if (DEROidCompare(type, &oidCommonName)) { - CFStringRef string = copyDERThingDescription(kCFAllocatorDefault, - value, true, localized); + // Convert data IP addresses to strings + __block CFMutableArrayRef result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayForEach(ipAddresses, ^(const void *value) { + CFDataRef address = (CFDataRef)value; + DERItem der_address = { (unsigned char *)CFDataGetBytePtr(address), CFDataGetLength(address) }; + CFStringRef string = copyIPAddressContentDescription(NULL, &der_address); if (string) { - CFDataRef data = NULL; - if (convertIPAddress(string, &data)) { - CFArrayAppendValue(addrs, data); - CFReleaseNull(data); - } + CFArrayAppendValue(result, string); CFRelease(string); - } else { - return errSecInvalidCertificate; } + }); + CFReleaseNull(ipAddresses); + if (CFArrayGetCount(result) == 0) { + CFReleaseNull(result); } - return errSecSuccess; + + return result; } -CFArrayRef SecCertificateCopyIPAddressesFromSubject(SecCertificateRef certificate) { - CFMutableArrayRef addrs = CFArrayCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeArrayCallBacks); - OSStatus status = parseX501NameContent(&certificate->_subject, addrs, - appendIPAddressesFromX501Name, true); - if (status || CFArrayGetCount(addrs) == 0) { - CFReleaseNull(addrs); +CFArrayRef SecCertificateCopyIPAddressDatas(SecCertificateRef certificate) { + /* These can only exist in the subject alt name. */ + if (!certificate->_subjectAltName) return NULL; + + CFMutableArrayRef ipAddresses = CFArrayCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeArrayCallBacks); + OSStatus status = SecCertificateParseGeneralNames(&certificate->_subjectAltName->extnValue, + ipAddresses, appendIPAddressesFromGeneralNames); + if (status || CFArrayGetCount(ipAddresses) == 0) { + CFRelease(ipAddresses); + ipAddresses = NULL; } - return addrs; + return ipAddresses; } static OSStatus appendDNSNamesFromGeneralNames(void *context, SecCEGeneralNameType gnType, @@ -4840,21 +4731,12 @@ static OSStatus appendDNSNamesFromX501Name(void *context, const DERItem *type, return errSecSuccess; } -CFArrayRef SecCertificateCopyDNSNamesFromSubject(SecCertificateRef certificate) { - CFMutableArrayRef dnsNames = CFArrayCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeArrayCallBacks); - OSStatus status = parseX501NameContent(&certificate->_subject, dnsNames, - appendDNSNamesFromX501Name, true); - if (status || CFArrayGetCount(dnsNames) == 0) { - CFReleaseNull(dnsNames); - return NULL; - } - - /* appendDNSNamesFromX501Name allows IP addresses, we don't want those for this function */ +static CF_RETURNS_RETAINED CFArrayRef filterIPAddresses(CFArrayRef CF_CONSUMED dnsNames) +{ __block CFMutableArrayRef result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFArrayForEach(dnsNames, ^(const void *value) { CFStringRef name = (CFStringRef)value; - if (!convertIPAddress(name, NULL)) { + if (!SecFrameworkIsIPAddress(name)) { CFArrayAppendValue(result, name); } }); @@ -4869,50 +4751,56 @@ CFArrayRef SecCertificateCopyDNSNamesFromSubject(SecCertificateRef certificate) CFArrayRef SecCertificateCopyDNSNamesFromSAN(SecCertificateRef certificate) { CFMutableArrayRef dnsNames = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - OSStatus status = errSecSuccess; if (certificate->_subjectAltName) { - status = SecCertificateParseGeneralNames(&certificate->_subjectAltName->extnValue, - dnsNames, appendDNSNamesFromGeneralNames); + if (SecCertificateParseGeneralNames(&certificate->_subjectAltName->extnValue, + dnsNames, appendDNSNamesFromGeneralNames) != errSecSuccess) { + CFReleaseNull(dnsNames); + return NULL; + } } - if (status || CFArrayGetCount(dnsNames) == 0) { - CFReleaseNull(dnsNames); - } - return dnsNames; + /* appendDNSNamesFromGeneralNames allows IP addresses, we don't want those for this function */ + return filterIPAddresses(dnsNames); } /* Not everything returned by this function is going to be a proper DNS name, we also return the certificates common name entries from the subject, - assuming they look like dns names as specified in RFC 1035. */ + assuming they look like dns names as specified in RFC 1035. + + To preserve bug for bug compatibility, we can't use SecCertificateCopyDNSNamesFromSAN + because that function filters out IP Addresses. This function is Private, but + SecCertificateCopyValues uses it and that's Public. */ CFArrayRef SecCertificateCopyDNSNames(SecCertificateRef certificate) { - /* These can exist in the subject alt name or in the subject. */ - CFArrayRef sanNames = SecCertificateCopyDNSNamesFromSAN(certificate); - if (sanNames && CFArrayGetCount(sanNames) > 0) { - return sanNames; - } - CFReleaseNull(sanNames); - - /* RFC 2818 section 3.1. Server Identity - [...] - If a subjectAltName extension of type dNSName is present, that MUST - be used as the identity. Otherwise, the (most specific) Common Name - field in the Subject field of the certificate MUST be used. Although - the use of the Common Name is existing practice, it is deprecated and - Certification Authorities are encouraged to use the dNSName instead. - [...] - - This implies that if we found 1 or more DNSNames in the - subjectAltName, we should not use the Common Name of the subject as - a DNSName. - */ - - /* To preserve bug for bug compatibility, we can't use SecCertificateCopyDNSNamesFromSubject - * because that function filters out IP Addresses. This function is Private, but - * SecCertificateCopyValues uses it and that's Public. */ + /* RFC 2818 section 3.1. Server Identity + [...] + If a subjectAltName extension of type dNSName is present, that MUST + be used as the identity. Otherwise, the (most specific) Common Name + field in the Subject field of the certificate MUST be used. Although + the use of the Common Name is existing practice, it is deprecated and + Certification Authorities are encouraged to use the dNSName instead. + [...] + + This implies that if we found 1 or more DNSNames in the + subjectAltName, we should not use the Common Name of the subject as + a DNSName. + */ + + /* return SAN DNS names if they exist */ + if (certificate->_subjectAltName) { + CFMutableArrayRef sanNames = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + OSStatus status = SecCertificateParseGeneralNames(&certificate->_subjectAltName->extnValue, + sanNames, appendDNSNamesFromGeneralNames); + if (status == errSecSuccess && sanNames && CFArrayGetCount(sanNames) > 0) { + return sanNames; + } + CFReleaseNull(sanNames); + } + + /* fall back to return DNS names in the Common Name */ CFMutableArrayRef dnsNames = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); OSStatus status = parseX501NameContent(&certificate->_subject, dnsNames, - appendDNSNamesFromX501Name, true); + appendDNSNamesFromX501Name, true); if (status || CFArrayGetCount(dnsNames) == 0) { CFReleaseNull(dnsNames); } @@ -5133,6 +5021,37 @@ CFArrayRef SecCertificateCopyCountry(SecCertificateRef certificate) { return countries; } +typedef struct { + DERItem *attributeOID; + CFStringRef *result; +} ATV_Context; + +static OSStatus copyAttributeValueFromX501Name(void *context, const DERItem *type, const DERItem *value, CFIndex rdnIX, bool localized) { + ATV_Context *ctx = (ATV_Context *)context; + if (DEROidCompare(type, ctx->attributeOID)) { + CFStringRef string = copyDERThingDescription(kCFAllocatorDefault, value, true, localized); + if (string) { + CFAssignRetained(*ctx->result, string); + } else { + return errSecInvalidCertificate; + } + } + return errSecSuccess; +} + +CFStringRef SecCertificateCopySubjectAttributeValue(SecCertificateRef cert, DERItem *attributeOID) { + CFStringRef result = NULL; + ATV_Context context = { + .attributeOID = attributeOID, + .result = &result, + }; + OSStatus status = parseX501NameContent(&cert->_subject, &context, copyAttributeValueFromX501Name, false); + if (status) { + CFReleaseNull(result); + } + return result; +} + const SecCEBasicConstraints * SecCertificateGetBasicConstraints(SecCertificateRef certificate) { if (certificate->_basicConstraints.present) @@ -5389,11 +5308,15 @@ const DERItem *SecCertificateGetPublicKeyData(SecCertificateRef certificate) { } #if TARGET_OS_OSX -/* There is already a SecCertificateCopyPublicKey with different args on OS X, - so we will refer to this one internally as SecCertificateCopyPublicKey_ios. +#if TARGET_CPU_ARM64 +/* force this implementation to be _SecCertificateCopyPublicKey on arm64 macOS. + note: the legacy function in SecCertificate.cpp is now _SecCertificateCopyPublicKey$LEGACYMAC + when both TARGET_OS_OSX and TARGET_CPU_ARM64 are true. */ +extern __nullable SecKeyRef SecCertificateCopyPublicKey_ios(SecCertificateRef certificate) __asm("_SecCertificateCopyPublicKey"); +#endif /* TARGET_CPU_ARM64 */ __nullable SecKeyRef SecCertificateCopyPublicKey_ios(SecCertificateRef certificate) -#else +#else /* !TARGET_OS_OSX */ __nullable SecKeyRef SecCertificateCopyPublicKey(SecCertificateRef certificate) #endif { @@ -6132,8 +6055,10 @@ static void check_for_marker(const void *key, const void *value, void *context) CFDataRef key_data = SecCertificateCreateOidDataFromString(NULL, key_string); - if (!isData(key_data)) + if (!isData(key_data)) { + CFReleaseNull(key_data); return; + } if (cert_contains_marker_extension_value(search_ctx->certificate, key_data, value_ref)) search_ctx->found = true; @@ -6715,71 +6640,76 @@ SEC_CONST_DECL (kSecSignatureDigestAlgorithmSHA256, "SignatureDigestSHA256"); SEC_CONST_DECL (kSecSignatureDigestAlgorithmSHA384, "SignatureDigestSHA284"); SEC_CONST_DECL (kSecSignatureDigestAlgorithmSHA512, "SignatureDigestSHA512"); +SecSignatureHashAlgorithm SecSignatureHashAlgorithmForAlgorithmOid(const DERItem *algOid) +{ + SecSignatureHashAlgorithm result = kSecSignatureHashAlgorithmUnknown; + while (algOid) { + if (!algOid->data || !algOid->length) { + break; + } + /* classify the signature algorithm OID into one of our known types */ + if (DEROidCompare(algOid, &oidSha512Ecdsa) || + DEROidCompare(algOid, &oidSha512Rsa) || + DEROidCompare(algOid, &oidSha512)) { + result = kSecSignatureHashAlgorithmSHA512; + break; + } + if (DEROidCompare(algOid, &oidSha384Ecdsa) || + DEROidCompare(algOid, &oidSha384Rsa) || + DEROidCompare(algOid, &oidSha384)) { + result = kSecSignatureHashAlgorithmSHA384; + break; + } + if (DEROidCompare(algOid, &oidSha256Ecdsa) || + DEROidCompare(algOid, &oidSha256Rsa) || + DEROidCompare(algOid, &oidSha256)) { + result = kSecSignatureHashAlgorithmSHA256; + break; + } + if (DEROidCompare(algOid, &oidSha224Ecdsa) || + DEROidCompare(algOid, &oidSha224Rsa) || + DEROidCompare(algOid, &oidSha224)) { + result = kSecSignatureHashAlgorithmSHA224; + break; + } + if (DEROidCompare(algOid, &oidSha1Ecdsa) || + DEROidCompare(algOid, &oidSha1Rsa) || + DEROidCompare(algOid, &oidSha1Dsa) || + DEROidCompare(algOid, &oidSha1DsaOIW) || + DEROidCompare(algOid, &oidSha1DsaCommonOIW) || + DEROidCompare(algOid, &oidSha1RsaOIW) || + DEROidCompare(algOid, &oidSha1Fee) || + DEROidCompare(algOid, &oidSha1)) { + result = kSecSignatureHashAlgorithmSHA1; + break; + } + if (DEROidCompare(algOid, &oidMd5Rsa) || + DEROidCompare(algOid, &oidMd5Fee) || + DEROidCompare(algOid, &oidMd5)) { + result = kSecSignatureHashAlgorithmMD5; + break; + } + if (DEROidCompare(algOid, &oidMd4Rsa) || + DEROidCompare(algOid, &oidMd4)) { + result = kSecSignatureHashAlgorithmMD4; + break; + } + if (DEROidCompare(algOid, &oidMd2Rsa) || + DEROidCompare(algOid, &oidMd2)) { + result = kSecSignatureHashAlgorithmMD2; + break; + } + break; + } + + return result; +} + SecSignatureHashAlgorithm SecCertificateGetSignatureHashAlgorithm(SecCertificateRef certificate) { - SecSignatureHashAlgorithm result = kSecSignatureHashAlgorithmUnknown; DERAlgorithmId *algId = (certificate) ? &certificate->_tbsSigAlg : NULL; const DERItem *algOid = (algId) ? &algId->oid : NULL; - while (algOid) { - if (!algOid->data || !algOid->length) { - break; - } - /* classify the signature algorithm OID into one of our known types */ - if (DEROidCompare(algOid, &oidSha512Ecdsa) || - DEROidCompare(algOid, &oidSha512Rsa) || - DEROidCompare(algOid, &oidSha512)) { - result = kSecSignatureHashAlgorithmSHA512; - break; - } - if (DEROidCompare(algOid, &oidSha384Ecdsa) || - DEROidCompare(algOid, &oidSha384Rsa) || - DEROidCompare(algOid, &oidSha384)) { - result = kSecSignatureHashAlgorithmSHA384; - break; - } - if (DEROidCompare(algOid, &oidSha256Ecdsa) || - DEROidCompare(algOid, &oidSha256Rsa) || - DEROidCompare(algOid, &oidSha256)) { - result = kSecSignatureHashAlgorithmSHA256; - break; - } - if (DEROidCompare(algOid, &oidSha224Ecdsa) || - DEROidCompare(algOid, &oidSha224Rsa) || - DEROidCompare(algOid, &oidSha224)) { - result = kSecSignatureHashAlgorithmSHA224; - break; - } - if (DEROidCompare(algOid, &oidSha1Ecdsa) || - DEROidCompare(algOid, &oidSha1Rsa) || - DEROidCompare(algOid, &oidSha1Dsa) || - DEROidCompare(algOid, &oidSha1DsaOIW) || - DEROidCompare(algOid, &oidSha1DsaCommonOIW) || - DEROidCompare(algOid, &oidSha1RsaOIW) || - DEROidCompare(algOid, &oidSha1Fee) || - DEROidCompare(algOid, &oidSha1)) { - result = kSecSignatureHashAlgorithmSHA1; - break; - } - if (DEROidCompare(algOid, &oidMd5Rsa) || - DEROidCompare(algOid, &oidMd5Fee) || - DEROidCompare(algOid, &oidMd5)) { - result = kSecSignatureHashAlgorithmMD5; - break; - } - if (DEROidCompare(algOid, &oidMd4Rsa) || - DEROidCompare(algOid, &oidMd4)) { - result = kSecSignatureHashAlgorithmMD4; - break; - } - if (DEROidCompare(algOid, &oidMd2Rsa) || - DEROidCompare(algOid, &oidMd2)) { - result = kSecSignatureHashAlgorithmMD2; - break; - } - break; - } - - return result; + return SecSignatureHashAlgorithmForAlgorithmOid(algOid); } CFArrayRef SecCertificateCopyiPhoneDeviceCAChain(void) { @@ -6833,3 +6763,25 @@ CFIndex SecCertificateGetUnparseableKnownExtension(SecCertificateRef certificate } return certificate->_unparseableKnownExtensionIndex; } + +CFArrayRef SecCertificateCopyAppleExternalRoots(void) { + CFMutableArrayRef result = NULL; + SecCertificateRef appleExternalECRoot = NULL, testAppleExternalECRoot = NULL; + + require_quiet(appleExternalECRoot = SecCertificateCreateWithBytes(NULL, _AppleExternalECRootCA, sizeof(_AppleExternalECRootCA)), + errOut); + require_quiet(testAppleExternalECRoot = SecCertificateCreateWithBytes(NULL, _TestAppleExternalECRootCA, + sizeof(_TestAppleExternalECRootCA)), + errOut); + + require_quiet(result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), errOut); + CFArrayAppendValue(result, appleExternalECRoot); + if (SecIsInternalRelease()) { + CFArrayAppendValue(result, testAppleExternalECRoot); + } + +errOut: + CFReleaseNull(appleExternalECRoot); + CFReleaseNull(testAppleExternalECRoot); + return result; +} diff --git a/OSX/sec/Security/SecCertificateInternal.h b/OSX/sec/Security/SecCertificateInternal.h index 46ea84a5..048050e6 100644 --- a/OSX/sec/Security/SecCertificateInternal.h +++ b/OSX/sec/Security/SecCertificateInternal.h @@ -90,6 +90,8 @@ typedef struct { __BEGIN_DECLS +SecSignatureHashAlgorithm SecSignatureHashAlgorithmForAlgorithmOid(const DERItem *algOid); + CFDataRef SecCertificateGetAuthorityKeyID(SecCertificateRef certificate); CFDataRef SecCertificateGetSubjectKeyID(SecCertificateRef certificate); @@ -245,11 +247,9 @@ bool SecCertificateIsOidString(CFStringRef oid); DERItem *SecCertificateGetExtensionValue(SecCertificateRef certificate, CFTypeRef oid); -CFArrayRef SecCertificateCopyDNSNamesFromSubject(SecCertificateRef certificate); -CFArrayRef SecCertificateCopyIPAddressesFromSubject(SecCertificateRef certificate); CFArrayRef SecCertificateCopyRFC822NamesFromSubject(SecCertificateRef certificate); - CFArrayRef SecCertificateCopyDNSNamesFromSAN(SecCertificateRef certificate); +CFArrayRef SecCertificateCopyIPAddressDatas(SecCertificateRef certificate); CFIndex SecCertificateGetUnparseableKnownExtension(SecCertificateRef certificate); diff --git a/OSX/sec/Security/SecCertificateRequest.c b/OSX/sec/Security/SecCertificateRequest.c index dad68a9e..0d19b393 100644 --- a/OSX/sec/Security/SecCertificateRequest.c +++ b/OSX/sec/Security/SecCertificateRequest.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2008-2009,2012-2017 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2008-2009,2012-2020 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, @@ -17,7 +17,7 @@ * 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@ * */ @@ -111,7 +111,7 @@ static uint8_t * mod128_oid_encoding_ptr(uint8_t *ptr, uint32_t src, bool final) { if (src > 128) ptr = mod128_oid_encoding_ptr(ptr, src / 128, false); - + unsigned char octet = src % 128; if (!final) octet |= 128; @@ -170,16 +170,16 @@ Consider using IA5String for email address static inline bool printable_string(CFStringRef string) { bool result = true; - - CFCharacterSetRef printable_charset = + + CFCharacterSetRef printable_charset = CFCharacterSetCreateWithCharactersInString(kCFAllocatorDefault, CFSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789 '()+,-./:=?")); - CFCharacterSetRef not_printable_charset = + CFCharacterSetRef not_printable_charset = CFCharacterSetCreateInvertedSet(kCFAllocatorDefault, printable_charset); CFRange found; - if (CFStringFindCharacterFromSet(string, not_printable_charset, + if (CFStringFindCharacterFromSet(string, not_printable_charset, CFRangeMake(0, CFStringGetLength(string)), 0, &found)) result = false; @@ -189,7 +189,7 @@ static inline bool printable_string(CFStringRef string) return result; } -static bool make_nss_atv(PRArenaPool *poolp, +static bool make_nss_atv(PRArenaPool *poolp, CFTypeRef oid, const void * value, const unsigned char type_in, NSS_ATV *nss_atv) { size_t length = 0; @@ -210,7 +210,7 @@ static bool make_nss_atv(PRArenaPool *poolp, else { if (!type || type == SecASN1PrintableString) { if (!printable_string(value)) - type = SEC_ASN1_IA5_STRING; + type = SEC_ASN1_UTF8_STRING; else type = SEC_ASN1_PRINTABLE_STRING; } @@ -245,8 +245,8 @@ static bool make_nss_atv(PRArenaPool *poolp, /* will remain valid for the duration of the operation, still maybe copy into pool */ oid_length = CFDataGetLength(oid); oid_data = (uint8_t *)CFDataGetBytePtr(oid); - } - NSS_ATV stage_nss_atv = { { oid_length, oid_data }, + } + NSS_ATV stage_nss_atv = { { oid_length, oid_data }, { { length, (uint8_t*)buffer }, type } }; *nss_atv = stage_nss_atv; return true; @@ -270,7 +270,7 @@ static NSS_RDN **make_subject(PRArenaPool *poolp, CFArrayRef subject) for (atv_ix = 0; atv_ix < atv_count; atv_ix++) { rdns[rdn_ix].atvs[atv_ix] = &atvs[atv_ix]; CFArrayRef atv = CFArrayGetValueAtIndex(rdn, atv_ix); - if ((CFArrayGetCount(atv) != 2) + if ((CFArrayGetCount(atv) != 2) || !make_nss_atv(poolp, CFArrayGetValueAtIndex(atv, 0), CFArrayGetValueAtIndex(atv, 1), 0, &atvs[atv_ix])) return NULL; @@ -302,7 +302,7 @@ static void make_general_names(const void *key, const void *value, void *context } require(entry_count > 0, out); - + require(key,out); require(CFGetTypeID(key) == CFStringGetTypeID(), out); @@ -312,7 +312,7 @@ static void make_general_names(const void *key, const void *value, void *context capacity *= 2; else capacity = 10; - + void * new_array = PORT_ArenaZNewArray(gn->poolp, SecAsn1Item, capacity); if (gn->names) memcpy(new_array, gn->names, gn->capacity); @@ -389,7 +389,7 @@ static void make_general_names(const void *key, const void *value, void *context } else goto out; - + if (gn_values) { for (entry_ix = 0; entry_ix < entry_count; entry_ix++) { CFTypeRef entry_value = CFArrayGetValueAtIndex(gn_values, entry_ix); @@ -419,7 +419,7 @@ out: static SecAsn1Item make_subjectAltName_extension(PRArenaPool *poolp, CFDictionaryRef subjectAltNames) { SecAsn1Item subjectAltExt = {}; - + struct make_general_names_context context = { poolp, NULL, 0 }; CFDictionaryApplyFunction(subjectAltNames, make_general_names, &context); @@ -498,7 +498,7 @@ extensions_from_parameters(PRArenaPool *poolp, CFDictionaryRef parameters) if (basic_contraints_num) { NSS_BasicConstraints basic_contraints = { asn1_true, {} }; uint8_t path_len; - + int basic_contraints_path_len = 0; require(CFNumberGetValue(basic_contraints_num, kCFNumberIntType, &basic_contraints_path_len), out); if (basic_contraints_path_len >= 0 && basic_contraints_path_len < 256) { @@ -506,12 +506,12 @@ extensions_from_parameters(PRArenaPool *poolp, CFDictionaryRef parameters) basic_contraints.pathLenConstraint.Length = sizeof(path_len); basic_contraints.pathLenConstraint.Data = &path_len; } - + csr_extension[num_extensions].extnId.Data = oidBasicConstraints.data; csr_extension[num_extensions].extnId.Length = oidBasicConstraints.length; csr_extension[num_extensions].critical = asn1_true; - - SEC_ASN1EncodeItem(poolp, &csr_extension[num_extensions].value, &basic_contraints, + + SEC_ASN1EncodeItem(poolp, &csr_extension[num_extensions].value, &basic_contraints, kSecAsn1BasicConstraintsTemplate); require(num_extensions++ < max_extensions, out); } @@ -532,7 +532,7 @@ extensions_from_parameters(PRArenaPool *poolp, CFDictionaryRef parameters) int key_usage_value; require(CFNumberGetValue(key_usage_requested, kCFNumberIntType, &key_usage_value), out); if (key_usage_value > 0) { - uint32_t key_usage_value_be = 0, key_usage_mask = 1<<31; + uint32_t key_usage_value_be = 0, key_usage_mask = (uint32_t)0x80000000; // 1L<<31 uint32_t key_usage_value_max_bitlen = 9, key_usage_value_bitlen = 0; while(key_usage_value_max_bitlen) { if (key_usage_value & 1) { @@ -544,7 +544,7 @@ extensions_from_parameters(PRArenaPool *poolp, CFDictionaryRef parameters) key_usage_mask >>= 1; } - SecAsn1Item key_usage_input = { key_usage_value_bitlen, + SecAsn1Item key_usage_input = { key_usage_value_bitlen, ((uint8_t*)&key_usage_value_be) + 3 - (key_usage_value_bitlen >> 3) }; SEC_ASN1EncodeItem(poolp, &key_usage_asn1_value, &key_usage_input, kSecAsn1BitStringTemplate); @@ -603,14 +603,14 @@ NSS_Attribute **nss_attributes_from_parameters_dict(PRArenaPool *poolp, CFDictio whenever possible. If internationalization issues make this impossible, the UTF8String alternative SHOULD be used. PKCS #9- attribute processing systems MUST be able to recognize and process - all string types in DirectoryString values. - + all string types in DirectoryString values. + Upperbound of 255 defined for all PKCS#9 attributes. - + pkcs-9 OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9} pkcs-9-at-challengePassword OBJECT IDENTIFIER ::= {pkcs-9 7} - + */ if (!parameters) return NULL; @@ -631,11 +631,11 @@ NSS_Attribute **nss_attributes_from_parameters_dict(PRArenaPool *poolp, CFDictio if (!printable_string(challenge)) utf8 = true; - SecAsn1Item *challenge_password_value = PORT_ArenaZNewArray(poolp, SecAsn1Item, 1); + SecAsn1Item *challenge_password_value = PORT_ArenaZNewArray(poolp, SecAsn1Item, 1); SecAsn1Item challenge_password_raw = { strlen(buffer), (uint8_t*)buffer }; - SEC_ASN1EncodeItem(poolp, challenge_password_value, &challenge_password_raw, + SEC_ASN1EncodeItem(poolp, challenge_password_value, &challenge_password_raw, utf8 ? kSecAsn1UTF8StringTemplate : kSecAsn1PrintableStringTemplate); - SecAsn1Item **challenge_password_values = PORT_ArenaZNewArray(poolp, SecAsn1Item *, 2); + SecAsn1Item **challenge_password_values = PORT_ArenaZNewArray(poolp, SecAsn1Item *, 2); challenge_password_values[0] = challenge_password_value; challenge_password_attr.attrType.Length = sizeof(pkcs9ChallengePassword); challenge_password_attr.attrType.Data = (uint8_t*)&pkcs9ChallengePassword; @@ -656,7 +656,7 @@ NSS_Attribute **nss_attributes_from_parameters_dict(PRArenaPool *poolp, CFDictio extensions_requested_attr.attrValue = extensions_requested_values; num_attrs++; } - + NSS_Attribute **attributes_ptr = PORT_ArenaZNewArray(poolp, NSS_Attribute *, num_attrs + 1); NSS_Attribute *attributes = PORT_ArenaZNewArray(poolp, NSS_Attribute, num_attrs); if (challenge_password_attr.attrType.Length) { @@ -783,7 +783,7 @@ static CF_RETURNS_RETAINED CFDataRef make_signature (void *data_pointer, size_t return signature; } -CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, +CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey) { if (subject == NULL || *subject == NULL) { @@ -796,12 +796,13 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, SecKeyRef realPublicKey = NULL; /* We calculate this from the private key rather than * trusting the caller to give us the right one. */ PRArenaPool *poolp = PORT_NewArena(1024); - - if (!poolp) + + if (!poolp) { return NULL; + } - NSSCertRequest certReq; - memset(&certReq, 0, sizeof(certReq)); + NSSCertRequest certReq; + memset(&certReq, 0, sizeof(certReq)); /* version */ unsigned char version = 0; @@ -831,7 +832,7 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, rdnps[rdn_num] = &rdns[rdn_num]; rdn_num++; for (one_atv = *one_rdn; one_atv->oid; one_atv++) { - if (!make_nss_atv(poolp, one_atv->oid, one_atv->value, + if (!make_nss_atv(poolp, one_atv->oid, one_atv->value, one_atv->type, &atvs[atv_num])) goto out; atvps[atv_num] = &atvs[atv_num]; @@ -841,7 +842,7 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, } rdnps[rdn_num] = NULL; certReq.reqInfo.subject.rdns = rdnps; - + /* public key info */ realPublicKey = SecKeyCopyPublicKey(privateKey); if (!realPublicKey) { @@ -852,7 +853,7 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, require_quiet(realPublicKey, out); publicKeyData = make_public_key(realPublicKey, &certReq.reqInfo.subjectPublicKeyInfo, &allocated_parameters); require_quiet(publicKeyData, out); - + certReq.reqInfo.attributes = nss_attributes_from_parameters_dict(poolp, parameters); SecCmsArraySortByDER((void **)certReq.reqInfo.attributes, kSecAsn1AttributeTemplate, NULL); @@ -869,13 +870,13 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, require_quiet(signature, out); certReq.signature.Data = (uint8_t *)CFDataGetBytePtr(signature); certReq.signature.Length = 8 * CFDataGetLength(signature); - + /* encode csr */ SecAsn1Item cert_request = {}; - require_quiet(SEC_ASN1EncodeItem(poolp, &cert_request, &certReq, + require_quiet(SEC_ASN1EncodeItem(poolp, &cert_request, &certReq, kSecAsn1CertRequestTemplate), out); csr = CFDataCreate(kCFAllocatorDefault, cert_request.Data, cert_request.Length); - + out: if (allocated_parameters) { free(certReq.reqInfo.subjectPublicKeyInfo.algorithm.parameters.Data); @@ -892,7 +893,7 @@ out: return csr; } -CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, +CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey) { CFDataRef csr = NULL; @@ -901,12 +902,13 @@ CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, SecKeyRef realPublicKey = NULL; /* We calculate this from the private key rather than * trusting the caller to give us the right one. */ bool allocated_parameters = false; - - if (!poolp) + + if (!poolp) { return NULL; + } - NSSCertRequest certReq; - memset(&certReq, 0, sizeof(certReq)); + NSSCertRequest certReq; + memset(&certReq, 0, sizeof(certReq)); /* version */ unsigned char version = 0; @@ -915,7 +917,7 @@ CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, /* subject */ certReq.reqInfo.subject.rdns = make_subject(poolp, (CFArrayRef)subject); - + /* public key info */ realPublicKey = SecKeyCopyPublicKey(privateKey); if (!realPublicKey) { @@ -926,7 +928,7 @@ CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, require_quiet(realPublicKey, out); publicKeyData = make_public_key(realPublicKey, &certReq.reqInfo.subjectPublicKeyInfo, &allocated_parameters); require_quiet(publicKeyData, out); - + certReq.reqInfo.attributes = nss_attributes_from_parameters_dict(poolp, parameters); SecCmsArraySortByDER((void **)certReq.reqInfo.attributes, kSecAsn1AttributeTemplate, NULL); @@ -943,13 +945,13 @@ CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, require_quiet(signature, out); certReq.signature.Data = (uint8_t *)CFDataGetBytePtr(signature); certReq.signature.Length = 8 * CFDataGetLength(signature); - + /* encode csr */ SecAsn1Item cert_request = {}; - require_quiet(SEC_ASN1EncodeItem(poolp, &cert_request, &certReq, + require_quiet(SEC_ASN1EncodeItem(poolp, &cert_request, &certReq, kSecAsn1CertRequestTemplate), out); csr = CFDataCreate(kCFAllocatorDefault, cert_request.Data, cert_request.Length); - + out: if (allocated_parameters) { free(certReq.reqInfo.subjectPublicKeyInfo.algorithm.parameters.Data); @@ -1057,9 +1059,9 @@ bool SecVerifyCertificateRequest(CFDataRef csr, SecKeyRef *publicKey, undecodedCertReq.certRequestBlob.Length, kCFAllocatorNull); require_quiet(alg && signature && data, out); require_quiet(SecKeyVerifySignature(candidatePublicKey, alg, data, signature, NULL), out); - + SecAsn1Item subject_item = { 0 }, extensions_item = { 0 }, challenge_item = { 0 }; - require_quiet(SEC_ASN1EncodeItem(poolp, &subject_item, + require_quiet(SEC_ASN1EncodeItem(poolp, &subject_item, &decodedCertReq.reqInfo.subject, kSecAsn1NameTemplate), out); if (*decodedCertReq.reqInfo.attributes) { @@ -1074,7 +1076,7 @@ bool SecVerifyCertificateRequest(CFDataRef csr, SecKeyRef *publicKey, extensions_item = *attr->attrValue[0]; } } - + if (subject && subject_item.Length) *subject = CFDataCreate(kCFAllocatorDefault, subject_item.Data, subject_item.Length); if (extensions && extensions_item.Length) @@ -1105,19 +1107,19 @@ out: return valid; } -#define HIDIGIT(v) (((v) / 10) + '0') -#define LODIGIT(v) (((v) % 10) + '0') +#define HIDIGIT(v) (((v) / 10) + '0') +#define LODIGIT(v) (((v) % 10) + '0') static OSStatus DER_CFDateToUTCTime(PRArenaPool *poolp, CFAbsoluteTime date, SecAsn1Item * utcTime) { unsigned char *d; - + utcTime->Length = 13; utcTime->Data = d = PORT_ArenaAlloc(poolp, 13); if (!utcTime->Data) return SECFailure; - + __block int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; __block bool result; SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar) { @@ -1125,15 +1127,15 @@ DER_CFDateToUTCTime(PRArenaPool *poolp, CFAbsoluteTime date, SecAsn1Item * utcTi }); if (!result) return SECFailure; - + /* UTC time does not handle the years before 1950 */ if (year < 1950) return SECFailure; - + /* remove the century since it's added to the year by the CFAbsoluteTimeGetGregorianDate routine, but is not needed for UTC time */ year %= 100; - + d[0] = HIDIGIT(year); d[1] = LODIGIT(year); d[2] = HIDIGIT(month); @@ -1151,7 +1153,7 @@ DER_CFDateToUTCTime(PRArenaPool *poolp, CFAbsoluteTime date, SecAsn1Item * utcTi } SecCertificateRef -SecGenerateSelfSignedCertificate(CFArrayRef subject, CFDictionaryRef parameters, +SecGenerateSelfSignedCertificate(CFArrayRef subject, CFDictionaryRef parameters, SecKeyRef __unused publicKey, SecKeyRef privateKey) { SecCertificateRef cert = NULL; @@ -1276,7 +1278,7 @@ SecIdentitySignCertificateWithAlgorithm(SecIdentityRef issuer, CFDataRef serialn require_noerr(SecIdentityCopyCertificate(issuer, &issuer_cert), out); CFDataRef issuer_name = SecCertificateCopySubjectSequence(issuer_cert); SecAsn1Item issuer_item = { CFDataGetLength(issuer_name), (uint8_t*)CFDataGetBytePtr(issuer_name) }; - require_noerr_action_quiet(SEC_ASN1DecodeItem(poolp, &cert_tmpl.tbs.issuer.rdns, + require_noerr_action_quiet(SEC_ASN1DecodeItem(poolp, &cert_tmpl.tbs.issuer.rdns, kSecAsn1NameTemplate, &issuer_item), out, CFReleaseNull(issuer_name)); CFReleaseNull(issuer_name); diff --git a/OSX/sec/Security/SecDH.c b/OSX/sec/Security/SecDH.c index 0f5689e0..ecd60a52 100644 --- a/OSX/sec/Security/SecDH.c +++ b/OSX/sec/Security/SecDH.c @@ -53,33 +53,28 @@ static inline ccdh_gp_t SecDH_gp(SecDHContext dh) { - return (ccdh_gp_t)dh; + return (ccdh_gp_t)dh; } static inline ccdh_full_ctx_t SecDH_priv(SecDHContext dh) { ccdh_gp_t gp = SecDH_gp(dh); cc_size s = ccn_sizeof_n(ccdh_gp_n(gp)); - ccdh_full_ctx_t priv = (ccdh_full_ctx_t)((char *) dh + ccdh_gp_size(s)); - - return priv; + return (ccdh_full_ctx_t)cc_pad_align((uintptr_t)dh + ccdh_gp_size(s)); } size_t SecDHGetMaxKeyLength(SecDHContext dh) { ccdh_gp_t gp = SecDH_gp(dh); - cc_size s = ccn_sizeof_n(ccdh_gp_n(gp)); - - return s; + return ccn_sizeof_n(ccdh_gp_n(gp)); } - static inline size_t SecDH_context_size(size_t p_len) { - cc_size n = ccn_nof_size(p_len); - cc_size real_p_len = ccn_sizeof_n(n); - size_t context_size = ccdh_gp_size(real_p_len)+ccdh_full_ctx_size(real_p_len); - return context_size; + cc_size real_p_len = ccn_sizeof_size(p_len); + + // Add padding to allow proper alignment of the ccdh_full_ctx. + return ccdh_gp_size(real_p_len) + (CC_MAX_ALIGNMENT - 1) + ccdh_full_ctx_size(real_p_len); } /* Shared static functions. */ @@ -210,7 +205,7 @@ OSStatus SecDHCreateFromParameters(const uint8_t *params, } cc_size n = ccn_nof_size(decodedParams.p.length); cc_size p_len = ccn_sizeof_n(n); - size_t context_size = ccdh_gp_size(p_len)+ccdh_full_ctx_size(p_len); + size_t context_size = SecDH_context_size(p_len); void *context = malloc(context_size); if(context==NULL) return errSecAllocate; diff --git a/OSX/sec/Security/SecECKey.m b/OSX/sec/Security/SecECKey.m index 4e9b26d6..5b343f6b 100644 --- a/OSX/sec/Security/SecECKey.m +++ b/OSX/sec/Security/SecECKey.m @@ -96,6 +96,10 @@ static ccoid_t ccoid_secp224r1 = CC_EC_OID_SECP224R1; static ccoid_t ccoid_secp384r1 = CC_EC_OID_SECP384R1; static ccoid_t ccoid_secp521r1 = CC_EC_OID_SECP521R1; +// OID_CERTICOM is wrong +static ccoid_t ccoid_libder_secp384r1 = ((unsigned char *)"\x06\x04\x2B\x84\x00\x22"); +static ccoid_t ccoid_libder_secp521r1 = ((unsigned char *)"\x06\x04\x2B\x84\x00\x23"); + static ccec_const_cp_t ccec_cp_for_oid(const unsigned char *oid) { if (oid!=NULL) { @@ -105,9 +109,9 @@ static ccec_const_cp_t ccec_cp_for_oid(const unsigned char *oid) return ccec_cp_256(); } else if (ccoid_equal(oid, ccoid_secp224r1)) { return ccec_cp_224(); - } else if (ccoid_equal(oid, ccoid_secp384r1)) { + } else if (ccoid_equal(oid, ccoid_secp384r1) || ccoid_equal(oid, ccoid_libder_secp384r1)) { return ccec_cp_384(); - } else if (ccoid_equal(oid, ccoid_secp521r1)) { + } else if (ccoid_equal(oid, ccoid_secp521r1) || ccoid_equal(oid, ccoid_libder_secp521r1)) { return ccec_cp_521(); } } @@ -128,10 +132,11 @@ static OSStatus SecECPublicKeyInit(SecKeyRef key, break; } - ccec_const_cp_t cp = getCPForPublicSize(derKey->keyLength); + require_action_quiet(derKey->parameters && derKey->parametersLength > 2 && + derKey->parameters[1] <= derKey->parametersLength - 2, errOut, err = errSecDecode); + ccec_const_cp_t cp = ccec_cp_for_oid(derKey->parameters); require_action_quiet(cp, errOut, err = errSecDecode); - /* TODO: Parse and use real params from passed in derKey->algId.params */ err = (ccec_import_pub(cp, derKey->keyLength, derKey->key, pubkey) ? errSecDecode : errSecSuccess); break; diff --git a/OSX/sec/Security/SecExports.exp-in b/OSX/sec/Security/SecExports.exp-in index d5f82152..2320866d 100644 --- a/OSX/sec/Security/SecExports.exp-in +++ b/OSX/sec/Security/SecExports.exp-in @@ -71,7 +71,6 @@ __P_DO_EXPORT_##ISPUBLIC(NAME) #if TARGET_OS_OSX _kSecPolicyAppleiChat #endif -_kSecPolicyAppleIDValidationRecordSigningPolicy _kSecPolicyMacAppStoreReceipt _kSecPolicyNameAppleAIDCService _kSecPolicyNameAppleAMPService @@ -87,6 +86,7 @@ _kSecPolicyNameAppleIDSService _kSecPolicyNameAppleMapsService _kSecPolicyNameAppleMMCSService _kSecPolicyNameAppleParsecService +_kSecPolicyNameApplePushCertPortal _kSecPolicyNameApplePPQService _kSecPolicyNameApplePushService _kSecPolicyNameAppleSiriService @@ -138,6 +138,9 @@ _kSecPolicyKU_NonRepudiation #endif _SecDNSIsTLD +_CreateCFDataFromBase64CFString +_parseNSPinnedDomains +_SecPolicyReconcilePinningRequiredIfInfoSpecified #undef POLICYCHECKMACRO #define __PC_DO_EXPORT_(NAME) @@ -157,7 +160,6 @@ _SecPolicySetName _SecPolicySetOptionsValue #if TARGET_OS_OSX _SecPolicyCopy -_SecPolicyCopyAll _SecPolicyCreateAppleTimeStampingAndRevocationPolicies _SecPolicyCreateItemImplInstance _SecPolicyCreateWithOID @@ -222,6 +224,7 @@ _SecTrustCopyFailureDescription _SecTrustCopyFilteredDetails _SecTrustCopyInfo _SecTrustCopyInputCertificates +_SecTrustCopyKey _SecTrustCopyPolicies _SecTrustCopyProperties _SecTrustCopyPublicKey @@ -267,6 +270,7 @@ _SecTrustSetPolicies _SecTrustSetSignedCertificateTimestamps _SecTrustSetTrustedLogs _SecTrustSetVerifyDate +_SecTrustTriggerValidUpdate #if TARGET_OS_OSX _SecTrustCopyAnchorCertificates _SecTrustCopyExtendedResult @@ -292,15 +296,18 @@ _SecTrustSettingsCopyCertificatesForUserAdminDomains _SecTrustSettingsCopyModificationDate _SecTrustSettingsCopyQualifiedCerts _SecTrustSettingsCopyTrustSettings +_SecTrustSettingsCopyTrustSettings_Cached _SecTrustSettingsCopyUnrestrictedRoots _SecTrustSettingsCreateExternalRepresentation _SecTrustSettingsEvaluateCert _SecTrustSettingsImportExternalRepresentation +_SecTrustSettingsPurgeCache _SecTrustSettingsPurgeUserAdminCertsCache _SecTrustSettingsRemoveTrustSettings _SecTrustSettingsSetTrustSettings _SecTrustSettingsSetTrustSettingsExternal _SecTrustSettingsSetTrustedCertificateForSSLHost +_SecTrustSettingsUserAdminDomainsContain _SecTrustedApplicationCopyData _SecTrustedApplicationCopyExternalRepresentation _SecTrustedApplicationCopyRequirement @@ -318,7 +325,6 @@ _SecTrustedApplicationValidateWithPath #endif -#if TARGET_OS_IPHONE _SecTrustStoreContains _SecTrustStoreCopyAll _SecTrustStoreCopyUsageConstraints @@ -327,15 +333,21 @@ _SecTrustStoreGetSettingsVersionNumber _SecTrustStoreGetSettingsAssetVersionNumber _SecTrustStoreRemoveCertificate _SecTrustStoreSetTrustSettings +#if TARGET_OS_IPHONE _SecTrustGetExceptionResetCount _SecTrustIncrementExceptionResetCount #endif _SecTrustStoreSetCTExceptions _SecTrustStoreCopyCTExceptions +_SecTrustStoreSetCARevocationAdditions +_SecTrustStoreCopyCARevocationAdditions _kSecCTExceptionsCAsKey _kSecCTExceptionsDomainsKey _kSecCTExceptionsHashAlgorithmKey _kSecCTExceptionsSPKIHashKey +_kSecCARevocationAdditionsKey +_kSecCARevocationHashAlgorithmKey +_kSecCARevocationSPKIHashKey // // Identity @@ -355,6 +367,7 @@ _kSecCertificateDetailSHA1Digest _kSecCertificateEscrowFileName _kSecCertificateProductionEscrowKey _kSecCertificateProductionPCSEscrowKey +_SecCertificateCopyAppleExternalRoots _SecCertificateCopyAttributeDictionary _SecCertificateCopyCommonName _SecCertificateCopyCommonNames @@ -364,7 +377,6 @@ _SecCertificateCopyCountry _SecCertificateCopyCTLogForKeyID _SecCertificateCopyDNSNames _SecCertificateCopyDNSNamesFromSAN -_SecCertificateCopyDNSNamesFromSubject _SecCertificateCopyData _SecCertificateCopyEmailAddresses _SecCertificateCopyEscrowRoots @@ -372,8 +384,8 @@ _SecCertificateCopyExtendedKeyUsage _SecCertificateCopyExtensionValue _SecCertificateCopyiAPAuthCapabilities _SecCertificateCopyiAPSWAuthCapabilities +_SecCertificateCopyIPAddressDatas _SecCertificateCopyIPAddresses -_SecCertificateCopyIPAddressesFromSubject _SecCertificateCopyiPhoneDeviceCAChain _SecCertificateCopyIssuerSHA1Digest _SecCertificateCopyIssuerSequence @@ -391,13 +403,20 @@ _SecCertificateCopyOrganizationalUnit _SecCertificateCopyPrecertTBS _SecCertificateCopyProperties _SecCertificateCopyPublicKey +#if TARGET_OS_OSX && TARGET_CPU_ARM64 +_SecCertificateCopyPublicKey$LEGACYMAC +#endif _SecCertificateCopyPublicKeySHA1Digest _SecCertificateCopyRFC822Names _SecCertificateCopyRFC822NamesFromSubject _SecCertificateCopySerialNumber _SecCertificateCopySerialNumberData +#if TARGET_OS_OSX && TARGET_CPU_ARM64 +_SecCertificateCopySerialNumber$LEGACYMAC +#endif _SecCertificateCopySHA256Digest _SecCertificateCopySignedCertificateTimestamps +_SecCertificateCopySubjectAttributeValue _SecCertificateCopySubjectPublicKeyInfoSHA1Digest _SecCertificateCopySubjectPublicKeyInfoSHA256Digest _SecCertificateCopySubjectSequence @@ -462,6 +481,7 @@ _SecCertificateShow _SecCertificateVersion _SecDistinguishedNameCopyNormalizedContent _SecDistinguishedNameCopyNormalizedSequence +_SecSignatureHashAlgorithmForAlgorithmOid _SecCertificateArrayCopyXPCArray _SecCertificateAppendToXPCArray @@ -504,16 +524,6 @@ _SecCertificateSetPreference _SecCertificateSetPreferred #endif -// -// CertificateBundle -// - -#if TARGET_OS_OSX -_SecCertifcateBundleExport -_SecCertificateBundleExport -_SecCertificateBundleImport -#endif /* TARGET_OS_OSX */ - #if TARGET_OS_IPHONE // // SCEP @@ -561,7 +571,6 @@ _SecGenerateCertificateRequestSubject // _SecOTRPacketTypeString -_SecOTRSEndSession _SecOTRSPrecalculateKeys _SecOTRSessionCreateRemote _SecOTRSessionProcessPacketRemote @@ -621,6 +630,7 @@ _AES_CTR_IV0_Transform _SecOTRSessionIsSessionInAwaitingState _SecOTRFullIdentityCreateFromSecKeyRef +_SecOTRFullIdentityCreateFromSecKeyRefSOS _SecOTRSIsForKeys _SecOTRPublicIdentityCreateFromSecKeyRef _SecOTRSAppendRestartPacket @@ -1526,6 +1536,13 @@ _kSecAttrPCSPlaintextPublicKey _kSecAttrPCSPlaintextPublicIdentity _kSecAttrSHA1 +_kSecDataInetExtraNotes +_kSecDataInetExtraHistory +_kSecDataInetExtraClientDefined0 +_kSecDataInetExtraClientDefined1 +_kSecDataInetExtraClientDefined2 +_kSecDataInetExtraClientDefined3 + #include "keychain/SecureObjectSync/SOSViews.exp-in" _kSecClass @@ -1566,7 +1583,6 @@ _kSecReturnPersistentRef _kSecReturnRef _SecItemAdd _SecItemCertificateExists -_SecItemCopyDisplayNames _SecItemCopyMatching _SecItemCopyParentCertificates_ios _SecItemDelete @@ -1595,18 +1611,18 @@ __SecKeychainWriteBackupToFileDescriptor __SecKeychainCopyKeybagUUIDFromFileDescriptor _SecItemBackupWithRegisteredBackups +_SecItemBackupWithRegisteredViewBackup _SecItemBackupSetConfirmedManifest _SecItemBackupRestore _SecBackupKeybagAdd _SecBackupKeybagDelete -_SecItemBackupCopyMatching _SecItemBackupCreateManifest _SecItemBackupWithChanges _SecBackupKeybagAdd _SecBackupKeybagDelete __SecKeychainRollKeys -#if TARGET_OS_IPHONE +#if TARGET_OS_IPHONE || TARGET_OS_OSX || TARGET_OS_MACCATALYST _SecAddSharedWebCredential _SecRequestSharedWebCredential @@ -1620,7 +1636,7 @@ __SecSecuritydCopyWhoAmI __SecSyncBubbleTransfer __SecSystemKeychainTransfer __SecSyncDeleteUserViews -_SecItemUpdateTokenItems +_SecItemUpdateTokenItemsForAccessGroups _SecItemDeleteAllWithAccessGroups _SecTokenItemValueCopy @@ -1647,6 +1663,7 @@ _SecCopyDecryptedForServer _sSecDERErrorDomain _der_sizeof_plist _der_encode_plist +_der_encode_plist_repair _der_decode_plist _CFPropertyListCreateDERData _CFPropertyListCreateWithDERData @@ -1746,10 +1763,9 @@ _sec_protocol_options_access_handle _sec_protocol_metadata_access_handle _sec_protocol_metadata_get_server_name _sec_protocol_options_set_output_handler_access_block -_sec_protocol_options_set_tls_SIKE503_exchange_enabled -_sec_protocol_options_set_tls_HRSS_exchange_enabled _sec_protocol_options_set_eddsa_enabled _sec_protocol_options_set_tls_grease_enabled +_sec_protocol_options_set_allow_unknown_alpn_protos _sec_protocol_options_set_tls_delegated_credentials_enabled _sec_protocol_options_set_tls_ticket_request_count _sec_protocol_options_set_local_certificates @@ -1763,6 +1779,8 @@ _sec_protocol_options_set_quic_transport_parameters _sec_protocol_options_set_session_state _sec_protocol_options_set_session_update_block _sec_protocol_options_add_tls_application_protocol +_sec_protocol_options_add_transport_specific_application_protocol +_sec_protocol_options_copy_transport_specific_application_protocol _sec_protocol_options_append_tls_ciphersuite _sec_protocol_options_append_tls_ciphersuite_group _sec_protocol_options_add_tls_ciphersuite @@ -1789,6 +1807,7 @@ _sec_protocol_options_set_tls_is_fallback_attempt _sec_protocol_options_set_verify_block _sec_protocol_options_set_tls_diffie_hellman_parameters _sec_protocol_options_set_peer_authentication_required +_sec_protocol_options_set_peer_authentication_optional _sec_protocol_options_set_experiment_identifier _sec_protocol_metadata_get_experiment_identifier _sec_protocol_options_create_config @@ -1813,6 +1832,7 @@ _sec_protocol_configuration_tls_required_for_address _sec_protocol_configuration_builder_create _sec_protocol_configuration_create_with_builder _sec_protocol_options_set_tls_encryption_secret_update_block +_sec_protocol_options_set_tls_encryption_level_update_block _sec_protocol_options_append_tls_key_exchange_group _sec_protocol_options_append_tls_key_exchange_group_set _sec_protocol_options_add_tls_key_exchange_group @@ -1829,6 +1849,11 @@ _sec_protocol_metadata_access_pre_shared_keys _sec_protocol_metadata_copy_connection_id _sec_protocol_options_set_pre_shared_key_selection_block _sec_protocol_helper_ciphersuite_group_to_ciphersuite_list +_sec_protocol_helper_ciphersuite_group_contains_ciphersuite +_sec_protocol_helper_ciphersuite_minimum_TLS_version +_sec_protocol_helper_ciphersuite_maximum_TLS_version +_sec_protocol_helper_get_ciphersuite_name +_sec_protocol_options_set_tls_block_length_padding _sec_release _sec_retain _sec_trust_copy_ref @@ -1853,7 +1878,3 @@ _sec_experiment_set_sampling_disabled _SSLCiphersuiteGroupToCiphersuiteList _SSLCiphersuiteMaximumTLSVersion _SSLCiphersuiteMinimumTLSVersion - -#if __OBJC2__ && (TARGET_OS_IPHONE || (TARGET_OS_OSX && __x86_64__)) -_OBJC_CLASS_$_SFSignInAnalytics -#endif //__OBJC2__ && IPHONE || OSX diff --git a/OSX/sec/Security/SecFramework.c b/OSX/sec/Security/SecFramework.c index b054999d..909ec7f9 100644 --- a/OSX/sec/Security/SecFramework.c +++ b/OSX/sec/Security/SecFramework.c @@ -32,18 +32,8 @@ #endif #include "SecFramework.h" -#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include /* Security.framework's bundle id. */ #if TARGET_OS_IPHONE @@ -64,19 +54,3 @@ CFStringRef SecFrameworkCopyLocalizedString(CFStringRef key, return CFRetainSafe(key); } - -CFURLRef SecFrameworkCopyResourceURL(CFStringRef resourceName, - CFStringRef resourceType, CFStringRef subDirName) { - CFURLRef url = NULL; - CFBundleRef bundle = SecFrameworkGetBundle(); - if (bundle) { - url = CFBundleCopyResourceURL(bundle, resourceName, - resourceType, subDirName); - if (!url) { - secwarning("resource: %@.%@ in %@ not found", resourceName, - resourceType, subDirName); - } - } - - return url; -} diff --git a/OSX/sec/Security/SecFramework.h b/OSX/sec/Security/SecFramework.h index 29c74c60..a1c35eff 100644 --- a/OSX/sec/Security/SecFramework.h +++ b/OSX/sec/Security/SecFramework.h @@ -43,9 +43,6 @@ __BEGIN_DECLS CFStringRef SecFrameworkCopyLocalizedString(CFStringRef key, CFStringRef tableName); -CFURLRef SecFrameworkCopyResourceURL(CFStringRef resourceName, - CFStringRef resourceType, CFStringRef subDirName); - /* Return the SHA1 digest of a chunk of data as newly allocated CFDataRef. */ CFDataRef SecSHA1DigestCreate(CFAllocatorRef allocator, const UInt8 *data, CFIndex length); diff --git a/OSX/sec/Security/SecFrameworkStrings.h b/OSX/sec/Security/SecFrameworkStrings.h index 9404603c..0d6db54a 100644 --- a/OSX/sec/Security/SecFrameworkStrings.h +++ b/OSX/sec/Security/SecFrameworkStrings.h @@ -284,17 +284,19 @@ __BEGIN_DECLS #define SEC_TRUST_ERROR_LeafMarkersProdAndQA SecStringWithDefaultValue("Missing project-specific extension OID", "Trust", 0, "Missing project-specific extension OID", "Error for leaf marker OID allowing prod or QA") #define SEC_TRUST_ERROR_BlackListedLeaf SecStringWithDefaultValue("Certificate is blocked", "Trust", 0, "Certificate is blocked", "Error for blocklisted certificates") #define SEC_TRUST_ERROR_GrayListedLeaf SecStringWithDefaultValue("Certificate is listed as untrusted", "Trust", 0, "Certificate is listed as untrusted", "Error for graylisted certificates") +#define SEC_TRUST_ERROR_LeafSPKISHA256 SecStringWithDefaultValue("Public key does not match pinned value", "Trust", 0, "Public key does not match pinned value", "Error for leaf public key pin") +#define SEC_TRUST_ERROR_NotCA SecStringWithDefaultValue("Leaf certificate is a CA", "Trust", 0, "Leaf certificate is a CA", "Error for leaf CA") #define SEC_TRUST_ERROR_IssuerCommonName SecStringWithDefaultValue("Common Name does not match expected name", "Trust", 0, "Common Name does not match expected name", "Error for issuer common name mismatch") #define SEC_TRUST_ERROR_BasicConstraints SecStringWithDefaultValue("Basic constraints are required but missing", "Trust", 0, "Basic constraints are required but missing", "Error for missing basic constraints") #define SEC_TRUST_ERROR_BasicConstraintsCA SecStringWithDefaultValue("Non-CA certificate used as a CA", "Trust", 0, "Non-CA certificate used as a CA", "Error for CA basic constraints") #define SEC_TRUST_ERROR_BasicConstraintsPathLen SecStringWithDefaultValue("Chain exceeded constrained path length", "Trust", 0, "Chain exceeded constrained path length", "Error for path length basic constraints") #define SEC_TRUST_ERROR_IntermediateSPKISHA256 SecStringWithDefaultValue("Public key does not match pinned value", "Trust", 0, "Public key does not match pinned value", "Error for intermediate public key pin") +#define SEC_TRUST_ERROR_CAspkiSHA256 SecStringWithDefaultValue("Public key does not match pinned value", "Trust", 0, "Public key does not match pinned value", "Error for CA public key pin") #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_IntermediateMarkerOidWithoutValueCheck 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 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") #define SEC_TRUST_ERROR_MissingIntermediate SecStringWithDefaultValue("Unable to build chain to root (possible missing intermediate)", "Trust", 0, "Unable to build chain to root (possible missing intermediate)", "Error for missing intermediates") diff --git a/OSX/sec/Security/SecItem.c b/OSX/sec/Security/SecItem.c index 22a1cdfe..4f325ec9 100644 --- a/OSX/sec/Security/SecItem.c +++ b/OSX/sec/Security/SecItem.c @@ -70,12 +70,12 @@ #include #include #include -#include -#include +#include #include #include #include #include +#include #include #include "keychain/SecureObjectSync/SOSInternal.h" @@ -95,10 +95,11 @@ #include #include -#include #include +#include "SecItemRateLimit.h" + /* * See corresponding definition in SecDbKeychainItemV7. This is the unserialized * maximum, so the daemon's limit is not exactly the same. @@ -461,15 +462,6 @@ SecItemCreateFromAttributeDictionary(CFDictionaryRef refAttributes) { return ref; } -#if !TARGET_OS_OSX -OSStatus -SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames) -{ - // @@@ TBI - return -1 /* errSecUnimplemented */; -} -#endif // TARGET_OS_OSX - typedef OSStatus (*secitem_operation)(CFDictionaryRef attributes, CFTypeRef *result); static bool explode_identity(CFDictionaryRef attributes, secitem_operation operation, @@ -543,7 +535,7 @@ static bool explode_identity(CFDictionaryRef attributes, secitem_operation opera if (result) { if (!status) { /* result is a persistent ref to a cert */ - sqlite_int64 rowid; + sqlite_int64 rowid = -1; CFDictionaryRef tokenAttrs = NULL; if (_SecItemParsePersistentRef(result, NULL, &rowid, &tokenAttrs)) { *return_result = _SecItemCreatePersistentRef(kSecClassIdentity, rowid, tokenAttrs); @@ -674,21 +666,31 @@ static void infer_cert_label(SecCFDictionaryCOW *attributes) } } -static CFDataRef CreateTokenPersistentRefData(CFTypeRef class, CFDictionaryRef attributes) -{ +static CFDataRef CreateTokenPersistentRefData(CFTypeRef class, CFDictionaryRef attributes) { CFDataRef tokenPersistentRef = NULL; - CFStringRef tokenId; + CFStringRef tokenID = NULL; + CFDataRef tokenData = NULL; + CFDataRef oid = NULL; CFDictionaryRef itemValue = NULL; - require_quiet(tokenId = CFCast(CFString, CFDictionaryGetValue(attributes, kSecAttrTokenID)), out); - if (CFEqual(class, kSecClassIdentity)) { - itemValue = SecTokenItemValueCopy(CFDictionaryGetValue(attributes, kSecAttrIdentityCertificateData), NULL); + + oid = CFDictionaryGetValue(attributes, kSecAttrTokenOID); + if (oid != NULL) { + require_quiet(tokenID = CFCast(CFString, CFDictionaryGetValue(attributes, kSecAttrTokenID)), out); } else { - itemValue = SecTokenItemValueCopy(CFDictionaryGetValue(attributes, kSecValueData), NULL); + // Identities are identified by their contained certificate, so we need to get tokenID and OID from certificate, + // not from the key. + if (CFEqual(class, kSecClassIdentity) && oid == NULL) { + require_quiet(tokenID = CFCast(CFString, CFDictionaryGetValue(attributes, kSecAttrIdentityCertificateTokenID)), out); + require_quiet(tokenData = CFCast(CFData, CFDictionaryGetValue(attributes, kSecAttrIdentityCertificateData)), out); + } else { + require_quiet(tokenID = CFCast(CFString, CFDictionaryGetValue(attributes, kSecAttrTokenID)), out); + require_quiet(tokenData = CFCast(CFData, CFDictionaryGetValue(attributes, kSecValueData)), out); + } + require_quiet(itemValue = SecTokenItemValueCopy(tokenData, NULL), out); + require_quiet(oid = CFDictionaryGetValue(itemValue, kSecTokenValueObjectIDKey), out); + require_quiet(CFCast(CFData, oid) != NULL, out); } - require_quiet(itemValue, out); - CFDataRef oid = CFDictionaryGetValue(itemValue, kSecTokenValueObjectIDKey); - require_quiet(oid, out); - CFArrayRef array = CFArrayCreateForCFTypes(kCFAllocatorDefault, class, tokenId, oid, NULL); + CFArrayRef array = CFArrayCreateForCFTypes(kCFAllocatorDefault, class, tokenID, oid, NULL); tokenPersistentRef = CFPropertyListCreateDERData(kCFAllocatorDefault, array, NULL); CFRelease(array); out: @@ -702,9 +704,12 @@ static const uint8_t tk_persistent_ref_id[] = {'t', 'k', 'p', 'r'}; CFDataRef _SecItemCreatePersistentRef(CFTypeRef class, sqlite_int64 rowid, CFDictionaryRef attributes) { CFDataRef result = NULL; - if (attributes && CFDictionaryContainsKey(attributes, CFEqual(class, kSecClassIdentity) ? kSecAttrIdentityCertificateTokenID : kSecAttrTokenID)) { - CFDataRef tokenPersistentRef = CreateTokenPersistentRefData(class, attributes); - require(tokenPersistentRef, out); + CFDataRef tokenPersistentRef = NULL; + if (attributes != NULL) { + tokenPersistentRef = CreateTokenPersistentRefData(class, attributes); + } + + if (tokenPersistentRef != NULL) { CFMutableDataRef tmpData = CFDataCreateMutable(kCFAllocatorDefault, sizeof(tk_persistent_ref_id) + CFDataGetLength(tokenPersistentRef)); CFDataAppendBytes(tmpData, tk_persistent_ref_id, sizeof(tk_persistent_ref_id)); CFDataAppend(tmpData, tokenPersistentRef); @@ -748,7 +753,7 @@ static bool ParseTokenPersistentRefData(CFDataRef persistent_ref, CFStringRef *r CFPropertyListRef pl = NULL; const uint8_t *der = CFDataGetBytePtr(persistent_ref) + sizeof(tk_persistent_ref_id); const uint8_t *der_end = der + (CFDataGetLength(persistent_ref) - sizeof(tk_persistent_ref_id)); - require_quiet(der = der_decode_plist(0, kCFPropertyListImmutable, &pl, NULL, der, der_end), out); + require_quiet(der = der_decode_plist(0, &pl, NULL, der, der_end), out); require_quiet(der == der_end, out); require_quiet(CFGetTypeID(pl) == CFArrayGetTypeID(), out); require_quiet(CFArrayGetCount(pl) == 3, out); @@ -828,11 +833,11 @@ static CFDataRef SecTokenItemValueCreate(CFDataRef oid, CFDataRef access_control } CFDictionaryRef SecTokenItemValueCopy(CFDataRef db_value, CFErrorRef *error) { - CFPropertyListRef plist = NULL; + CFPropertyListRef plist = NULL, result = NULL; require_quiet(CFCastWithError(CFData, db_value, error), out); const uint8_t *der = CFDataGetBytePtr(db_value); const uint8_t *der_end = der + CFDataGetLength(db_value); - require_quiet(der = der_decode_plist(0, kCFPropertyListImmutable, &plist, error, der, der_end), out); + require_quiet(der = der_decode_plist(0, &plist, error, der, der_end), out); require_action_quiet(der == der_end, out, SecError(errSecDecode, error, CFSTR("trailing garbage at end of token data field"))); CFTypeRef value = CFDictionaryGetValue(plist, kSecTokenValueObjectIDKey); require_action_quiet(CFCast(CFData, value) != NULL, out, @@ -841,9 +846,10 @@ CFDictionaryRef SecTokenItemValueCopy(CFDataRef db_value, CFErrorRef *error) { require_quiet(value == NULL || CFCastWithError(CFData, value, error), out); value = CFDictionaryGetValue(plist, kSecTokenValueDataKey); require_quiet(value == NULL || CFCastWithError(CFData, value, error), out); - + result = CFRetainSafe(plist); out: - return plist; + CFReleaseNull(plist); + return result; } TKTokenRef SecTokenCreate(CFStringRef token_id, SecCFDictionaryCOW *auth_params, CFErrorRef *error) { @@ -988,8 +994,11 @@ static bool SecItemResultCopyPrepared(CFTypeRef raw_result, TKTokenRef token, CFDictionaryRef parsed_value = NULL; require_quiet(parsed_value = SecTokenItemValueCopy(value, error), out); object_id = CFRetainSafe(CFDictionaryGetValue(parsed_value, kSecTokenValueObjectIDKey)); + require_quiet(object_id == NULL || CFCastWithError(CFData, object_id, error) != NULL, out); ac_data = CFRetainSafe(CFDictionaryGetValue(parsed_value, kSecTokenValueAccessControlKey)); + require_quiet(ac_data == NULL || CFCastWithError(CFData, ac_data, error) != NULL, out); object_value = CFRetainSafe(CFDictionaryGetValue(parsed_value, kSecTokenValueDataKey)); + require_quiet(object_value == NULL || CFCastWithError(CFData, object_value, error) != NULL, out); CFRelease(parsed_value); if ((wants_data || wants_ref) && object_value == NULL) { // Retrieve value directly from the token. @@ -1057,7 +1066,9 @@ static bool SecItemResultCopyPrepared(CFTypeRef raw_result, TKTokenRef token, CFDictionaryRef parsed_value; require_quiet(parsed_value = SecTokenItemValueCopy(data, error), out); cert_data = CFRetainSafe(CFDictionaryGetValue(parsed_value, kSecTokenValueDataKey)); + require_quiet(cert_data == NULL || CFCastWithError(CFData, cert_data, error) != NULL, out); cert_object_id = CFRetainSafe(CFDictionaryGetValue(parsed_value, kSecTokenValueObjectIDKey)); + require_quiet(cert_object_id == NULL || CFCastWithError(CFData, cert_object_id, error) != NULL, out); CFRelease(parsed_value); if (cert_data == NULL) { // Retrieve value directly from the token. @@ -1123,7 +1134,7 @@ out: } bool SecItemResultProcess(CFDictionaryRef query, CFDictionaryRef auth_params, TKTokenRef token, - CFTypeRef raw_result, CFTypeRef *result, CFErrorRef *error) { + CFTypeRef raw_result, CFTypeRef *result, CFErrorRef *error) { bool ok = false; require_action_quiet(raw_result != NULL, out, ok = true); require_action_quiet(result != NULL, out, ok = true); @@ -1160,7 +1171,6 @@ out: static bool SecItemAttributesPrepare(SecCFDictionaryCOW *attrs, bool forQuery, CFErrorRef *error) { bool ok = false; CFDataRef ac_data = NULL, acm_context = NULL; - void *la_lib = NULL; // If a ref was specified we get its attribute dictionary and parse it. CFTypeRef value = CFDictionaryGetValue(attrs->dictionary, kSecValueRef); @@ -1251,9 +1261,6 @@ static bool SecItemAttributesPrepare(SecCFDictionaryCOW *attrs, bool forQuery, C ok = true; out: - if (la_lib != NULL) { - dlclose(la_lib); - } CFReleaseSafe(ac_data); CFReleaseSafe(acm_context); return ok; @@ -1496,12 +1503,17 @@ bool SecItemAuthDoQuery(SecCFDictionaryCOW *query, SecCFDictionaryCOW *attribute } CFDictionaryRef attrs = (attributes != NULL) ? attributes->dictionary : NULL; - if(!perform(token, query->dictionary, attrs, auth_params.dictionary, error)) { - require_quiet((result = SecItemCreatePairsFromError(error, ac_pairs)) == kSecItemAuthResultOK, out); + if(perform(token, query->dictionary, attrs, auth_params.dictionary, error)) { + result = kSecItemAuthResultOK; + if(error && *error) { + // SecItemAuthDoQuery perform() sometimes returns success and fills in error parameter + secdebug("SecItemAuthDoQuery", "perform() succeded but returned an error: %@", *error); + CFReleaseNull(*error); + } + } else { + result = SecItemCreatePairsFromError(error, ac_pairs); } - result = kSecItemAuthResultOK; - out: return result; }, NULL); @@ -1549,16 +1561,21 @@ static bool dict_to_error_request(enum SecXPCOperation op, CFDictionaryRef query }, NULL); } -static bool cfstring_array_to_error_request(enum SecXPCOperation op, CFStringRef string, CFArrayRef attributes, __unused SecurityClient *client, CFErrorRef *error) +static bool cfstring_array_array_to_error_request(enum SecXPCOperation op, CFStringRef string, CFArrayRef groups, CFArrayRef items, __unused SecurityClient *client, CFErrorRef *error) { return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { if (string) { if (!SecXPCDictionarySetString(message, kSecXPCKeyString, string, error)) return false; } + + if (groups) { + if (!SecXPCDictionarySetPList(message, kSecXPCKeyArray, groups, error)) + return false; + } - if (attributes) { - if (!SecXPCDictionarySetPList(message, kSecXPCKeyQuery, attributes, error)) + if (items) { + if (!SecXPCDictionarySetPList(message, kSecXPCKeyQuery, items, error)) return false; } @@ -1698,6 +1715,16 @@ out: return ok; } +static void countReadOnlyAPICall() { + if (!isReadOnlyAPIRateWithinLimits()) { + } +} + +static void countModifyingAPICall() { + if (!isModifyingAPIRateWithinLimits()) { + } +} + OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) { __block SecCFDictionaryCOW attrs = { attributes }; OSStatus status; @@ -1714,8 +1741,10 @@ OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) { if (token == NULL) { CFTypeRef raw_result = NULL; logUnreasonableDataLength(attributes); - if (!SECURITYD_XPC(sec_item_add, cftype_client_to_bool_cftype_error_request, attributes, SecSecurityClientGet(), &raw_result, error)) + countModifyingAPICall(); + if (!SECURITYD_XPC(sec_item_add, cftype_client_to_bool_cftype_error_request, attributes, SecSecurityClientGet(), &raw_result, error)) { return false; + } bool ok = SecItemResultProcess(attributes, auth_params, token, raw_result, result, error); CFReleaseSafe(raw_result); @@ -1756,8 +1785,10 @@ OSStatus SecItemCopyMatching(CFDictionaryRef inQuery, CFTypeRef *result) { status = SecOSStatusWith(^bool(CFErrorRef *error) { return SecItemAuthDoQuery(&query, NULL, SecItemCopyMatching, error, ^bool(TKTokenRef token, CFDictionaryRef query, CFDictionaryRef attributes, CFDictionaryRef auth_params, CFErrorRef *error) { CFTypeRef raw_result = NULL; - if (!SECURITYD_XPC(sec_item_copy_matching, cftype_client_to_bool_cftype_error_request, query, SecSecurityClientGet(), &raw_result, error)) + countReadOnlyAPICall(); + if (!SECURITYD_XPC(sec_item_copy_matching, cftype_client_to_bool_cftype_error_request, query, SecSecurityClientGet(), &raw_result, error)) { return false; + } // We intentionally pass NULL as token argument, because we want to be able to decide about token on which the item lives // on per-record basis, not wholesale. Logic inside SecItemResultCopyPrepared will open proper token according @@ -1899,6 +1930,7 @@ SecItemUpdateWithError(CFDictionaryRef inQuery, goto errOut; result = SecItemAuthDoQuery(&query, &attributesToUpdate, SecItemUpdate, error, ^bool(TKTokenRef token, CFDictionaryRef query, CFDictionaryRef attributes, CFDictionaryRef auth_params, CFErrorRef *error) { + countModifyingAPICall(); if (token == NULL) { return SecItemRawUpdate(query, attributes, error); } else { @@ -1953,6 +1985,7 @@ OSStatus SecItemDelete(CFDictionaryRef inQuery) { status = SecOSStatusWith(^bool(CFErrorRef *error) { return SecItemAuthDoQuery(&query, NULL, SecItemDelete, error, ^bool(TKTokenRef token, CFDictionaryRef query, CFDictionaryRef attributes, CFDictionaryRef auth_params, CFErrorRef *error) { + countModifyingAPICall(); if (token == NULL) { return SECURITYD_XPC(sec_item_delete, dict_client_to_error_request, query, SecSecurityClientGet(), error); } else { @@ -2004,75 +2037,50 @@ SecItemDeleteAll(void) }); } -#if 0 -static bool -agrps_client_to_error_request(enum SecXPCOperation op, CFArrayRef agrps, __unused SecurityClient *client, CFErrorRef *error) -{ - return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - return SecXPCDictionarySetPList(message, kSecXPCKeyAccessGroups, agrps, error); - }, NULL); -} -#endif - bool SecItemDeleteAllWithAccessGroups(CFArrayRef accessGroups, CFErrorRef *error) { -#if 0 - os_activity_t activity = os_activity_create("SecItemDeleteAllWithAccessGroups", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); - os_activity_scope(activity); - os_release(activity); - - return SECURITYD_XPC(sec_delete_items_with_access_groups, agrps_client_to_error_request, accessGroups, - SecSecurityClientGet(), error); -#else return true; -#endif } OSStatus -#if SECITEM_SHIM_OSX -SecItemUpdateTokenItems_ios(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes) -#else -SecItemUpdateTokenItems(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes) -#endif +SecItemUpdateTokenItemsForAccessGroups(CFTypeRef tokenID, CFArrayRef accessGroups, CFArrayRef tokenItemsAttributes) { OSStatus status; - os_activity_t activity = os_activity_create("SecItemUpdateTokenItems_ios", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_t activity = os_activity_create("SecItemUpdateTokenItemsForAccessGroups", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); os_activity_scope(activity); os_release(activity); status = SecOSStatusWith(^bool(CFErrorRef *error) { - CFArrayRef tmpArrayRef = tokenItemsAttributes; + bool ok = false; + CFMutableArrayRef tokenItemsForServer = NULL; if (tokenItemsAttributes) { - CFMutableArrayRef tokenItems = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + tokenItemsForServer = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); for (CFIndex i = 0; i < CFArrayGetCount(tokenItemsAttributes); ++i) { CFDictionaryRef itemAttributes = CFArrayGetValueAtIndex(tokenItemsAttributes, i); CFTypeRef accessControl = CFDictionaryGetValue(itemAttributes, kSecAttrAccessControl); CFTypeRef tokenOID = CFDictionaryGetValue(itemAttributes, kSecAttrTokenOID); CFTypeRef valueData = CFDictionaryGetValue(itemAttributes, kSecValueData); if (tokenOID != NULL && accessControl != NULL && CFDataGetTypeID() == CFGetTypeID(accessControl)) { - CFDataRef data = SecTokenItemValueCreate(tokenOID, accessControl, valueData, error); - if (!data) { - CFRelease(tokenItems); - return false; - } - + CFDataRef data; + require_quiet(data = SecTokenItemValueCreate(tokenOID, accessControl, valueData, error), out); CFMutableDictionaryRef attributes = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, itemAttributes); CFDictionarySetValue(attributes, kSecValueData, data); CFDictionarySetValue(attributes, kSecAttrTokenID, tokenID); CFDictionaryRemoveValue(attributes, kSecAttrAccessControl); CFDictionaryRemoveValue(attributes, kSecAttrTokenOID); - CFArrayAppendValue(tokenItems, attributes); - CFRelease(attributes); - CFRelease(data); + CFArrayAppendValue(tokenItemsForServer, attributes); + CFReleaseNull(attributes); + CFReleaseNull(data); + } else { + CFArrayAppendValue(tokenItemsForServer, itemAttributes); } - else - CFArrayAppendValue(tokenItems, itemAttributes); } - - tmpArrayRef = tokenItems; } - return SECURITYD_XPC(sec_item_update_token_items, cfstring_array_to_error_request, tokenID, tmpArrayRef, SecSecurityClientGet(), error); + ok = SECURITYD_XPC(sec_item_update_token_items_for_access_groups, cfstring_array_array_to_error_request, tokenID, accessGroups, tokenItemsForServer, SecSecurityClientGet(), error); + out: + CFReleaseNull(tokenItemsForServer); + return ok; }); return status; diff --git a/OSX/sec/Security/SecItem.m b/OSX/sec/Security/SecItem.m index faa47c88..a9af1e22 100644 --- a/OSX/sec/Security/SecItem.m +++ b/OSX/sec/Security/SecItem.m @@ -30,6 +30,7 @@ #include #include #include +#import #include @@ -52,7 +53,7 @@ OSStatus _SecItemAddAndNotifyOnSync(CFDictionaryRef attributes, CFTypeRef * CF_R __block CFTypeRef raw_result = NULL; __block CFErrorRef raw_error = NULL; - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(false, ^(NSError *error) { syncCallback(false, (__bridge CFErrorRef)error); }); if (rpc == NULL) { @@ -103,7 +104,7 @@ void SecItemSetCurrentItemAcrossAllDevices(CFStringRef accessGroup, os_activity_scope(activity); @autoreleasepool { - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(false, ^(NSError *error) { complete((__bridge CFErrorRef) error); }); [rpc secItemSetCurrentItemAcrossAllDevices:(__bridge NSData*)newCurrentItemReference @@ -129,7 +130,7 @@ void SecItemFetchCurrentItemAcrossAllDevices(CFStringRef accessGroup, os_activity_scope(activity); @autoreleasepool { - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(false, ^(NSError *error) { complete(NULL, (__bridge CFErrorRef) error); }); [rpc secItemFetchCurrentItemAcrossAllDevices:(__bridge NSString*)accessGroup @@ -147,7 +148,7 @@ void _SecItemFetchDigests(NSString *itemClass, NSString *accessGroup, void (^com os_activity_t activity = os_activity_create("_SecItemFetchDigests", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); os_activity_scope(activity); - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(false, ^(NSError *error) { complete(NULL, error); }); [rpc secItemDigest:itemClass accessGroup:accessGroup complete:complete]; @@ -167,7 +168,7 @@ void _SecKeychainDeleteMultiUser(NSString *musr, void (^complete)(bool, NSError uuid_t musrUUID; [uuid getUUIDBytes:musrUUID]; - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(false, ^(NSError *error) { complete(false, error); }); [rpc secKeychainDeleteMultiuser:[NSData dataWithBytes:musrUUID length:sizeof(uuid_t)] complete:^(bool status, NSError *error) { @@ -179,9 +180,28 @@ void SecItemVerifyBackupIntegrity(BOOL lightweight, void(^completion)(NSDictionary* results, NSError* error)) { @autoreleasepool { - id rpc = SecuritydXPCProxyObject(^(NSError *error) { + id rpc = SecuritydXPCProxyObject(true, ^(NSError *error) { completion(@{@"summary" : @"XPC Error"}, error); }); [rpc secItemVerifyBackupIntegrity:lightweight completion:completion]; } } + +OSStatus SecItemDeleteKeychainItemsForAppClip(CFStringRef applicationIdentifier) +{ + __block OSStatus status = errSecInternal; + @autoreleasepool { + id rpc = SecuritydXPCProxyObject(true, ^(NSError *error) { + secerror("xpc: failure to obtain XPC proxy object for app clip deletion, %@", error); + }); + [rpc secItemDeleteForAppClipApplicationIdentifier:(__bridge NSString*)applicationIdentifier + completion:^(OSStatus xpcStatus) { + // Other errors turn into errSecInternal for caller + secnotice("xpc", "app clip deletion result: %i", (int)xpcStatus); + if (xpcStatus == errSecMissingEntitlement || xpcStatus == errSecSuccess) { + status = xpcStatus; + } + }]; + } + return status; +} diff --git a/OSX/sec/Security/SecItemBackup.c b/OSX/sec/Security/SecItemBackup.c index 614e40d8..9581cb8b 100644 --- a/OSX/sec/Security/SecItemBackup.c +++ b/OSX/sec/Security/SecItemBackup.c @@ -124,6 +124,17 @@ static bool string_string_data_data_data_to_bool_error_request(enum SecXPCOperat }); } +static CFStringRef string_to_string_error_request(enum SecXPCOperation op, CFStringRef viewName, CFErrorRef *error) +{ + __block CFStringRef result = NULL; + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + return SecXPCDictionarySetString(message, kSecXPCKeyString, viewName, error); + }, ^bool(xpc_object_t response, CFErrorRef *error) { + return result = SecXPCDictionaryCopyString(response, kSecXPCKeyResult, error); + }); + return result; +} + static CFArrayRef to_array_error_request(enum SecXPCOperation op, CFErrorRef *error) { __block CFArrayRef result = NULL; @@ -346,6 +357,25 @@ bool SecItemBackupWithRegisteredBackups(CFErrorRef *error, void(^backup)(CFStrin return true; } +static CFStringRef SecItemBackupViewAndCopyBackupPeerID(CFStringRef viewName, CFErrorRef *error) +{ + __block CFStringRef result; + os_activity_initiate("SecItemBackupViewAndCopyBackupPeerID", OS_ACTIVITY_FLAG_DEFAULT, ^{ + result = SECURITYD_XPC(sec_item_backup_ensure_copy_view, string_to_string_error_request, viewName, error); + }); + return result; +} + +bool SecItemBackupWithRegisteredViewBackup(CFStringRef viewName, CFErrorRef *error) { + CFStringRef backupName = SecItemBackupViewAndCopyBackupPeerID(viewName, error); + if(backupName == NULL) { + return false; + } + CFReleaseNull(backupName); + return true; +} + + static bool SecItemBackupDoResetEventBody(const uint8_t *der, const uint8_t *der_end, CFErrorRef *error, void (^handleEvent)(SecBackupEventType et, CFTypeRef key, CFTypeRef item)) { size_t sequence_len; const uint8_t *sequence_body = ccder_decode_len(&sequence_len, der, der_end); @@ -377,7 +407,7 @@ static bool SecItemBackupDoResetEventBody(const uint8_t *der, const uint8_t *der static bool SecItemBackupDoAddEvent(const uint8_t *der, const uint8_t *der_end, CFErrorRef *error, void (^handleEvent)(SecBackupEventType et, CFTypeRef key, CFTypeRef item)) { CFDictionaryRef eventDict = NULL; - const uint8_t *der_end_of_dict = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &eventDict, error, der, der_end); + const uint8_t *der_end_of_dict = der_decode_dictionary(kCFAllocatorDefault, &eventDict, error, der, der_end); if (der_end_of_dict && der_end_of_dict != der_end) { // Can't ever happen! SecError(errSecDecode, error, CFSTR("trailing junk after add")); @@ -589,11 +619,6 @@ void SecItemBackupRestore(CFStringRef backupName, CFStringRef peerID, CFDataRef CFReleaseSafe(localError); } -CFDictionaryRef SecItemBackupCopyMatching(CFDataRef keybag, CFDataRef secret, CFDictionaryRef backup, CFDictionaryRef query, CFErrorRef *error) { - SecError(errSecUnimplemented, error, CFSTR("SecItemBackupCopyMatching unimplemented")); - return NULL; -} - bool SecBackupKeybagAdd(CFDataRef passcode, CFDataRef *identifier, CFURLRef *pathinfo, CFErrorRef *error) { __block bool result = false; os_activity_initiate("_SecServerBackupKeybagAdd", OS_ACTIVITY_FLAG_DEFAULT, ^{ diff --git a/OSX/sec/Security/SecItemBackup.h b/OSX/sec/Security/SecItemBackup.h index b6b73679..c6047c6d 100644 --- a/OSX/sec/Security/SecItemBackup.h +++ b/OSX/sec/Security/SecItemBackup.h @@ -54,6 +54,8 @@ typedef enum SecBackupEventType { bool SecItemBackupWithRegisteredBackups(CFErrorRef *error, void(^backup)(CFStringRef backupName)); +bool SecItemBackupWithRegisteredViewBackup(CFStringRef viewName, CFErrorRef *error); + /*! @function SecItemBackupWithChanges @abstract Tell securityd which keybag (via a persistent ref) to use to backup @@ -85,24 +87,6 @@ bool SecItemBackupSetConfirmedManifest(CFStringRef backupName, CFDataRef keybagD @discussion CloudServices iterates over all the backups, calling this for each backup with peer infos matching the chosen device. */ void SecItemBackupRestore(CFStringRef backupName, CFStringRef peerID, CFDataRef keybag, CFDataRef secret, CFTypeRef backup, void (^completion)(CFErrorRef error)); -/*! - @function SecItemBackupCopyMatching - @abstract Query the contents of a backup dictionary. - @param keybag The bag protecting the backup data. - @param secret Credential to unlock keybag. - @param backup Dictionary returned from SecItemBackupDataSource. - @param query A dictionary containing an item class specification and - optional attributes for controlling the search. See the "Keychain - Search Attributes" section of SecItemCopyMatching for a description of - currently defined search attributes. - @result CFTypeRef reference to the found item(s). The - exact type of the result is based on the search attributes supplied - in the query. Returns NULL and sets *error if there is a failure. - @discussion This allows clients to "restore" a backup and fetch an item from - it without restoring the backup to the keychain, and in particular without - even having a writable keychain around, such as when running in the restore OS. */ -CFDictionaryRef SecItemBackupCopyMatching(CFDataRef keybag, CFDataRef secret, CFDictionaryRef backup, CFDictionaryRef query, CFErrorRef *error); - // Utility function to compute a confirmed manifest from a v0 backup dictionary. CFDataRef SecItemBackupCreateManifest(CFDictionaryRef backup, CFErrorRef *error); diff --git a/OSX/sec/Security/SecItemConstants.c b/OSX/sec/Security/SecItemConstants.c index 38904fe6..a5fd1aa8 100644 --- a/OSX/sec/Security/SecItemConstants.c +++ b/OSX/sec/Security/SecItemConstants.c @@ -120,6 +120,13 @@ SEC_CONST_DECL (kSecAttrPCSPlaintextServiceIdentifier, "pcss"); SEC_CONST_DECL (kSecAttrPCSPlaintextPublicKey, "pcsk"); SEC_CONST_DECL (kSecAttrPCSPlaintextPublicIdentity, "pcsi"); +SEC_CONST_DECL (kSecDataInetExtraNotes, "binn"); +SEC_CONST_DECL (kSecDataInetExtraHistory, "bini"); +SEC_CONST_DECL (kSecDataInetExtraClientDefined0, "bin0"); +SEC_CONST_DECL (kSecDataInetExtraClientDefined1, "bin1"); +SEC_CONST_DECL (kSecDataInetExtraClientDefined2, "bin2"); +SEC_CONST_DECL (kSecDataInetExtraClientDefined3, "bin3"); + /* Predefined access groups constants */ SEC_CONST_DECL (kSecAttrAccessGroupToken, "com.apple.token"); diff --git a/OSX/sec/Security/SecItemInternal.h b/OSX/sec/Security/SecItemInternal.h index 50cc4c6a..33b184f1 100644 --- a/OSX/sec/Security/SecItemInternal.h +++ b/OSX/sec/Security/SecItemInternal.h @@ -105,6 +105,11 @@ CFArrayRef SecItemCopyParentCertificates_ios(CFDataRef normalizedIssuer, CFArray bool SecItemCertificateExists(CFDataRef normalizedIssuer, CFDataRef serialNumber, CFArrayRef accessGroups, CFErrorRef *error); +/*! + @constant kSecAttrAppClipItem Boolean attribute indicating whether the origin of this item is an App Clip client +*/ +static const CFStringRef kSecAttrAppClipItem = CFSTR("clip"); + __END_DECLS #endif /* !_SECURITY_SECITEMINTERNAL_H_ */ diff --git a/OSX/sec/Security/SecItemRateLimit.h b/OSX/sec/Security/SecItemRateLimit.h new file mode 100644 index 00000000..b5503a8a --- /dev/null +++ b/OSX/sec/Security/SecItemRateLimit.h @@ -0,0 +1,9 @@ +#ifndef SECITEMRATELIMIT_H_ +#define SECITEMRATELIMIT_H_ + +#include + +bool isReadOnlyAPIRateWithinLimits(void); +bool isModifyingAPIRateWithinLimits(void); + +#endif // SECITEMRATELIMIT_H_ diff --git a/OSX/sec/Security/SecItemRateLimit.m b/OSX/sec/Security/SecItemRateLimit.m new file mode 100644 index 00000000..c18f9edf --- /dev/null +++ b/OSX/sec/Security/SecItemRateLimit.m @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2020 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@ + */ + +#import "SecItemRateLimit.h" +#import "SecItemRateLimit_tests.h" + +#import +#import +#import "ipc/securityd_client.h" + +#import +#import + +// Dressed-down version of RateLimiter which directly computes the rate of one bucket and resets when it runs out of tokens + +// Broken out so the test-only reset method can reinit this +static SecItemRateLimit* ratelimit; + +@implementation SecItemRateLimit { + bool _forceEnabled; + dispatch_queue_t _dataQueue; +} + ++ (instancetype)instance { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + ratelimit = [SecItemRateLimit new]; + }); + return ratelimit; +} + +- (instancetype)init { + if (self = [super init]) { + _roCapacity = 25; // allow burst of this size + _roRate = 3.0; // allow sustained rate of this many per second + _rwCapacity = 25; + _rwRate = 1.0; + _roBucket = nil; + _rwBucket = nil; + _forceEnabled = false; + _limitMultiplier = 5.0; // Multiply capacity and rate by this much after exceeding limit + _dataQueue = dispatch_queue_create("com.apple.keychain.secitemratelimit.dataqueue", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + } + + return self; +} + +- (bool)isEnabled { + return _forceEnabled || [self shouldCountAPICalls]; +} + +- (void)forceEnabled:(bool)force { + _forceEnabled = force; + secnotice("secitemratelimit", "%sorcing SIRL to be enabled (effective: %i)", force ? "F" : "Not f", [self isEnabled]); +} + +- (bool)isReadOnlyAPICallWithinLimits { + if (![self consumeTokenFromBucket:false]) { + secnotice("secitemratelimit", "Readonly API rate exceeded"); + return false; + } else { + return true; + } +} + +- (bool)isModifyingAPICallWithinLimits { + if (![self consumeTokenFromBucket:true]) { + secnotice("secitemratelimit", "Modifying API rate exceeded"); + return false; + } else { + return true; + } +} + +- (bool)consumeTokenFromBucket:(bool)readwrite { + if (![self shouldCountAPICalls] && !_forceEnabled) { + return true; + } + + __block bool ok = false; + dispatch_sync(_dataQueue, ^{ + int* capacity = readwrite ? &_rwCapacity : &_roCapacity; + double* rate = readwrite ? &_rwRate : &_roRate; + NSDate* __strong* bucket = readwrite ? &_rwBucket : &_roBucket; + + NSDate* now = [NSDate now]; + NSDate* fullBucket = [now dateByAddingTimeInterval:-(*capacity * (1.0 / *rate))]; + // bucket has more tokens than a 'full' bucket? This prevents occasional-but-bursty activity slipping through + if (!*bucket || [*bucket timeIntervalSinceDate: fullBucket] < 0) { + *bucket = fullBucket; + } + + *bucket = [*bucket dateByAddingTimeInterval:1.0 / *rate]; + ok = [*bucket timeIntervalSinceDate:now] <= 0; + + // Get a new bucket next time so we only complain every now and then + if (!ok) { + *bucket = nil; + *capacity *= _limitMultiplier; + *rate *= _limitMultiplier; + } + }); + + return ok; +} + +- (bool)shouldCountAPICalls { + static bool shouldCount = false; + static dispatch_once_t shouldCountToken; + dispatch_once(&shouldCountToken, ^{ + if (!SecIsInternalRelease()) { + secnotice("secitemratelimit", "Not internal release, disabling SIRL"); + return; + } + + // gSecurityd is the XPC elision mechanism for testing; don't want simcrashes during tests + if (gSecurityd != nil) { + secnotice("secitemratelimit", "gSecurityd non-nil, disabling SIRL for testing"); + return; + } + + if (!os_feature_enabled(Security, SecItemRateLimiting)) { + secnotice("secitemratelimit", "SIRL disabled via feature flag"); + return; + } + + SecTaskRef task = SecTaskCreateFromSelf(NULL); + NSMutableArray* exempt = [NSMutableArray arrayWithArray:@[@"com.apple.pcsstatus", @"com.apple.protectedcloudstorage.protectedcloudkeysyncing", @"com.apple.cloudd", @"com.apple.pcsctl"]]; + CFStringRef identifier = NULL; + require_action_quiet(task, cleanup, secerror("secitemratelimit: unable to get task from self, disabling SIRL")); + + // If not a valid or debugged platform binary, don't count + uint32_t flags = SecTaskGetCodeSignStatus(task); + require_action_quiet((flags & (CS_VALID | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) == (CS_VALID | CS_PLATFORM_BINARY) || + (flags & (CS_DEBUGGED | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) == (CS_DEBUGGED | CS_PLATFORM_BINARY), + cleanup, secnotice("secitemratelimit", "Not valid/debugged platform binary, disabling SIRL")); + + // Some processes have legitimate need to query or modify a large number of items + identifier = SecTaskCopySigningIdentifier(task, NULL); + require_action_quiet(identifier, cleanup, secerror("secitemratelimit: unable to get signing identifier, disabling SIRL")); +#if TARGET_OS_OSX + [exempt addObjectsFromArray:@[@"com.apple.keychainaccess", @"com.apple.Safari"]]; +#elif TARGET_OS_IOS + [exempt addObjectsFromArray:@[@"com.apple.mobilesafari", @"com.apple.Preferences"]]; +#endif + if ([exempt containsObject:(__bridge NSString*)identifier]) { + secnotice("secitemratelimit", "%@ exempt from SIRL", identifier); + goto cleanup; + } + + secnotice("secitemratelimit", "valid/debugged platform binary %@ on internal release, enabling SIRL", identifier); + shouldCount = true; + +cleanup: + CFReleaseNull(task); + CFReleaseNull(identifier); + }); + return shouldCount; +} + +// Testing ++ (instancetype)getStaticRateLimit { + return [SecItemRateLimit instance]; +} + +// Testing and super thread-UNsafe. Caveat emptor. ++ (void)resetStaticRateLimit { + ratelimit = [SecItemRateLimit new]; +} + +@end + +bool isReadOnlyAPIRateWithinLimits(void) { + return [[SecItemRateLimit instance] isReadOnlyAPICallWithinLimits]; +} + +bool isModifyingAPIRateWithinLimits(void) { + return [[SecItemRateLimit instance] isModifyingAPICallWithinLimits]; +} diff --git a/OSX/sec/Security/SecItemRateLimit_tests.h b/OSX/sec/Security/SecItemRateLimit_tests.h new file mode 100644 index 00000000..c79c9472 --- /dev/null +++ b/OSX/sec/Security/SecItemRateLimit_tests.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 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@ + */ + +#ifndef SecItemRateLimit_tests_h +#define SecItemRateLimit_tests_h + +#import "SecItemRateLimit.h" +#import + +// Broken out into header for testing convenience. +// If you need this, why? +@interface SecItemRateLimit : NSObject + +@property (nonatomic, readonly) int roCapacity; +@property (nonatomic, readonly) double roRate; +@property (nonatomic, readonly) int rwCapacity; +@property (nonatomic, readonly) double rwRate; +@property (nonatomic, readonly) double limitMultiplier; + +@property (nonatomic, readonly) NSDate* roBucket; +@property (nonatomic, readonly) NSDate* rwBucket; + +- (bool)shouldCountAPICalls; +- (bool)isEnabled; +- (void)forceEnabled:(bool)force; + ++ (instancetype)getStaticRateLimit; ++ (void)resetStaticRateLimit; + +@end + +#endif /* SecItemRateLimit_tests_h */ diff --git a/OSX/sec/Security/SecItemShim.h b/OSX/sec/Security/SecItemShim.h index 02b89f36..862dd996 100644 --- a/OSX/sec/Security/SecItemShim.h +++ b/OSX/sec/Security/SecItemShim.h @@ -47,7 +47,6 @@ OSStatus SecItemAdd_ios(CFDictionaryRef attributes, CFTypeRef *result); OSStatus SecItemCopyMatching_ios(CFDictionaryRef query, CFTypeRef *result); OSStatus SecItemUpdate_ios(CFDictionaryRef query, CFDictionaryRef attributesToUpdate); OSStatus SecItemDelete_ios(CFDictionaryRef query); -OSStatus SecItemUpdateTokenItems_ios(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes); OSStatus SecKeyGeneratePair_ios(CFDictionaryRef parameters, SecKeyRef *publicKey, SecKeyRef *privateKey); SecKeyRef SecKeyCreateRandomKey_ios(CFDictionaryRef parameters, CFErrorRef *error); @@ -58,7 +57,6 @@ SecKeyRef SecKeyCreateRandomKey_ios(CFDictionaryRef parameters, CFErrorRef *erro #define SecItemCopyMatching SecItemCopyMatching_ios #define SecItemUpdate SecItemUpdate_ios #define SecItemDelete SecItemDelete_ios -#define SecItemUpdateTokenItems SecItemUpdateTokenItems_ios #define SecKeyGeneratePair SecKeyGeneratePair_ios #define SecKeyCreateRandomKey SecKeyCreateRandomKey_ios diff --git a/OSX/sec/Security/SecKey.m b/OSX/sec/Security/SecKey.m index 218f1a9b..35c0afab 100644 --- a/OSX/sec/Security/SecKey.m +++ b/OSX/sec/Security/SecKey.m @@ -1199,7 +1199,7 @@ OSStatus SecKeyCopyPersistentRef(SecKeyRef key, CFDataRef* persistentRef) if (!persistentRef) { secerror("SecKeyCopyPersistentRef: Need a persistentRef pointer for this to work"); return errSecParam; - } + } CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecReturnPersistentRef, kCFBooleanTrue, diff --git a/OSX/sec/Security/SecKeyAdaptors.m b/OSX/sec/Security/SecKeyAdaptors.m index 07a8b98b..3e0868cf 100644 --- a/OSX/sec/Security/SecKeyAdaptors.m +++ b/OSX/sec/Security/SecKeyAdaptors.m @@ -716,12 +716,12 @@ static CFTypeRef SecKeyECDHCopyX963Result(SecKeyOperationContext *context, const CFMutableDataRef kdfResult = CFDataCreateMutableWithScratch(kCFAllocatorDefault, requestedSize); int err = ccansikdf_x963(di, CFDataGetLength(sharedSecret), CFDataGetBytePtr(sharedSecret), sharedInfoLength, sharedInfo, requestedSize, CFDataGetMutableBytePtr(kdfResult)); - require_noerr_action_quiet(err, out, (CFReleaseNull(result), + require_noerr_action_quiet(err, out, (CFReleaseNull(kdfResult), SecError(errSecParam, error, CFSTR("ECDHKeyExchange wrong input (%d)"), err))); CFAssignRetained(result, kdfResult); } else { // In test-only mode, propagate result (YES/NO) of underlying operation. - result = CFRetainAssign(result, sharedSecret); + CFRetainAssign(result, sharedSecret); } out: CFReleaseNull(sharedSecret); @@ -949,8 +949,11 @@ out: 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); + CFMutableDataRef plaintext = NULL; + CFMutableDataRef tag = NULL; + require_action_quiet(CFDataGetLength(inData) >= kSecKeyIESTagLength, out, SecError(errSecParam, error, CFSTR("ECIES: Input data too short"))); + plaintext = CFDataCreateMutableWithScratch(kCFAllocatorDefault, CFDataGetLength(inData) - kSecKeyIESTagLength); + tag = CFDataCreateMutableWithScratch(SecCFAllocatorZeroize(), kSecKeyIESTagLength); CFDataGetBytes(inData, CFRangeMake(CFDataGetLength(inData) - kSecKeyIESTagLength, kSecKeyIESTagLength), CFDataGetMutableBytePtr(tag)); CFIndex aesKeySize = CFDataGetLength(keyExchangeResult) - sizeof(kSecKeyIESIV); diff --git a/OSX/sec/Security/SecKeyProxy.m b/OSX/sec/Security/SecKeyProxy.m index 94855948..b5a0e980 100644 --- a/OSX/sec/Security/SecKeyProxy.m +++ b/OSX/sec/Security/SecKeyProxy.m @@ -136,7 +136,11 @@ @implementation SecKeyProxy - (instancetype)initWithKey:(SecKeyRef)key certificate:(nullable NSData *)certificate { if (self = [super init]) { - _key = CFBridgingRelease(CFRetain(key)); + if (key != nil) { + _key = CFBridgingRelease(CFRetainSafe(key)); + } else { + _key = nil; + } _certificate = certificate; _listener = [NSXPCListener anonymousListener]; _listener.delegate = self; diff --git a/OSX/sec/Security/SecOTR.h b/OSX/sec/Security/SecOTR.h index 743320a2..d79b0ebe 100644 --- a/OSX/sec/Security/SecOTR.h +++ b/OSX/sec/Security/SecOTR.h @@ -56,8 +56,13 @@ typedef struct _SecOTRPublicIdentity* SecOTRPublicIdentityRef; * Full identity functions */ SecOTRFullIdentityRef SecOTRFullIdentityCreate(CFAllocatorRef allocator, CFErrorRef *error); - + +// This variant is used by MessageProtection that doesn't use persistent references anymore. SecOTRFullIdentityRef SecOTRFullIdentityCreateFromSecKeyRef(CFAllocatorRef allocator, SecKeyRef privateKey, + CFErrorRef *error); + +// This variant is used by SOS, and still relies on privateKey having a persistent reference. +SecOTRFullIdentityRef SecOTRFullIdentityCreateFromSecKeyRefSOS(CFAllocatorRef allocator, SecKeyRef privateKey, CFErrorRef *error); SecOTRFullIdentityRef SecOTRFullIdentityCreateFromData(CFAllocatorRef allocator, CFDataRef serializedData, CFErrorRef *error); diff --git a/OSX/sec/Security/SecOTRDHKey.c b/OSX/sec/Security/SecOTRDHKey.c index 221274d7..492eef0e 100644 --- a/OSX/sec/Security/SecOTRDHKey.c +++ b/OSX/sec/Security/SecOTRDHKey.c @@ -31,8 +31,7 @@ #include #include #include - -#include +#include #define kECKeySize 256 @@ -177,7 +176,7 @@ fail: OSStatus SecFDHKNewKey(SecOTRFullDHKeyRef fullKey) { - struct ccrng_state *rng=ccDRBGGetRngState(); + struct ccrng_state *rng=ccrng(NULL); // We need compact keys, maybe we should be using // ccecdh_generate_key or ccechd_generate_compact_key, but for now ecdh are fine for compact use IFF we don't diff --git a/OSX/sec/Security/SecOTRFullIdentity.c b/OSX/sec/Security/SecOTRFullIdentity.c index 877863eb..c38b51ca 100644 --- a/OSX/sec/Security/SecOTRFullIdentity.c +++ b/OSX/sec/Security/SecOTRFullIdentity.c @@ -186,7 +186,7 @@ errOut: SecOTRFullIdentityRef SecOTRFullIdentityCreate(CFAllocatorRef allocator, CFErrorRef *error) { SecKeyRef signingKey = SecOTRCreateSigningKey(allocator); - SecOTRFullIdentityRef newID = SecOTRFullIdentityCreateFromSecKeyRef(allocator, signingKey, error); + SecOTRFullIdentityRef newID = SecOTRFullIdentityCreateFromSecKeyRefSOS(allocator, signingKey, error); CFReleaseNull(signingKey); return newID; @@ -298,7 +298,8 @@ OSStatus SecOTRFIInitFromV2Bytes(SecOTRFullIdentityRef newID, CFAllocatorRef all --*size; require_noerr_quiet(status = SecOTRFICreateKeysFromReadPersistentRefAndPublicKey(bytes, size, &newID->publicSigningKey, &newID->privateSigningKey, &newID->privateKeyPersistentRef, &CreateECPublicKeyFrom), fail); - + newID->isMessageProtectionKey = false; + return status; fail: @@ -309,6 +310,49 @@ fail: return status; } +static +OSStatus SecOTRFIInitFromV3Bytes(SecOTRFullIdentityRef newID, CFAllocatorRef allocator, + const uint8_t **bytes,size_t *size) { + OSStatus status = errSecInvalidData; + require_action(**bytes == 3, fail, status = errSecParam); + ++*bytes; + --*size; + + uint16_t dataSize; + require_noerr_quiet(readSize(bytes, size, &dataSize), fail); + + int32_t keysz32 = 256; + CFNumberRef ksizeNumber = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFDataRef keyBytes = CFDataCreate(allocator, *bytes, dataSize); + + CFDictionaryRef dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom, + kSecAttrKeyClass, kSecAttrKeyClassPrivate, + kSecAttrKeySizeInBits, ksizeNumber, + kSecAttrIsPermanent, kCFBooleanFalse, NULL); + + CFErrorRef error; + SecKeyRef key = SecKeyCreateWithData(keyBytes, dict, &error); + + CFReleaseSafe(dict); + CFReleaseSafe(keyBytes); + CFReleaseSafe(ksizeNumber); + + if (key == NULL) { + CFRelease(error); + return errSecInvalidData; + } + + newID->privateKeyPersistentRef = NULL; + newID->isMessageProtectionKey = true; + newID->privateSigningKey = key; + newID->publicSigningKey = SecKeyCopyPublicKey(newID->privateSigningKey); + status = errSecSuccess; + +fail: + return status; +} + // TODO: Probably move to SecKey static CFDataRef SecKeyCreatePersistentRef(SecKeyRef theKey, CFErrorRef *error) { CFDataRef persistentRef = NULL; @@ -320,13 +364,27 @@ static CFDataRef SecKeyCreatePersistentRef(SecKeyRef theKey, CFErrorRef *error) SecOTRFullIdentityRef SecOTRFullIdentityCreateFromSecKeyRef(CFAllocatorRef allocator, SecKeyRef privateKey, CFErrorRef *error) { - // TODO - make sure this is an appropriate key type - SecOTRFullIdentityRef newID = CFTypeAllocate(SecOTRFullIdentity, struct _SecOTRFullIdentity, allocator); - CFRetainAssign(newID->privateSigningKey, privateKey); - require_action(newID->publicSigningKey = SecKeyCreatePublicFromPrivate(privateKey), fail, - SecError(errSecInternalComponent, error, CFSTR("Failed to extract public key from private key"))); + // TODO - make sure this is an appropriate key type + SecOTRFullIdentityRef newID = CFTypeAllocate(SecOTRFullIdentity, struct _SecOTRFullIdentity, allocator); + CFRetainAssign(newID->privateSigningKey, privateKey); + require_action(newID->publicSigningKey = SecKeyCreatePublicFromPrivate(privateKey), fail, + SecError(errSecInternalComponent, error, CFSTR("Failed to extract public key from private key"))); + // MessageProtection keys are no longer having persistent references. + newID->privateKeyPersistentRef = NULL; + newID->isMessageProtectionKey = true; + + require(SecOTRFICachePublicHash(newID, error), fail); + return newID; + fail: + CFReleaseNull(newID); + return NULL; +} + +SecOTRFullIdentityRef SecOTRFullIdentityCreateFromSecKeyRefSOS(CFAllocatorRef allocator, SecKeyRef privateKey, + CFErrorRef *error) { + SecOTRFullIdentityRef newID = SecOTRFullIdentityCreateFromSecKeyRef(allocator, privateKey, error); require(newID->privateKeyPersistentRef = SecKeyCreatePersistentRef(privateKey, error), fail); - require(SecOTRFICachePublicHash(newID, error), fail); + newID->isMessageProtectionKey = false; return newID; fail: CFReleaseNull(newID); @@ -347,6 +405,9 @@ SecOTRFullIdentityRef SecOTRFullIdentityCreateFromBytes(CFAllocatorRef allocator case 2: require_noerr_action_quiet(status = SecOTRFIInitFromV2Bytes(newID, allocator, bytes, size), fail, SecError(status, error, CFSTR("failed to decode v2 otr session: %d"), (int)status)); break; + case 3: + require_noerr_action_quiet(status = SecOTRFIInitFromV3Bytes(newID, allocator, bytes, size), fail, SecError(status, error, CFSTR("failed to decode v3 otr session: %d"), (int)status)); + break; case 0: // Version 0 was used in seeds of 5.0, transition from those seeds unsupported - keys were in exported data. default: SecError(errSecParam, error, CFSTR("unknown otr session version %hhu"), **bytes); @@ -432,6 +493,23 @@ bool SecOTRFIPurgeAllFromKeychain(CFErrorRef *error) } } +static OSStatus SecOTRFIAppendV3Serialization(SecOTRFullIdentityRef fullID, CFMutableDataRef serializeInto) +{ + const uint8_t version = 3; + CFIndex start = CFDataGetLength(serializeInto); + CFDataAppendBytes(serializeInto, &version, sizeof(version)); + CFErrorRef error = nil; + CFDataRef privKeyBytes = SecKeyCopyExternalRepresentation(fullID->privateSigningKey, &error); + require(privKeyBytes != nil, fail); + appendSizeAndData(privKeyBytes, serializeInto); + CFReleaseSafe(privKeyBytes); + return errSecSuccess; + +fail: + CFDataSetLength(serializeInto, start); + + return errSecParam; +} static OSStatus SecOTRFIAppendV2Serialization(SecOTRFullIdentityRef fullID, CFMutableDataRef serializeInto) { @@ -452,7 +530,13 @@ fail: bool SecOTRFIAppendSerialization(SecOTRFullIdentityRef fullID, CFMutableDataRef serializeInto, CFErrorRef *error) { - OSStatus status = SecOTRFIAppendV2Serialization(fullID, serializeInto); + OSStatus status = errSecParam; + if (fullID->isMessageProtectionKey) { + status = SecOTRFIAppendV3Serialization(fullID, serializeInto); + } else { + status = SecOTRFIAppendV2Serialization(fullID, serializeInto); + } + if (errSecSuccess == status) { return true; } else { diff --git a/OSX/sec/Security/SecOTRIdentityPriv.h b/OSX/sec/Security/SecOTRIdentityPriv.h index 8ce081c9..61b288ea 100644 --- a/OSX/sec/Security/SecOTRIdentityPriv.h +++ b/OSX/sec/Security/SecOTRIdentityPriv.h @@ -52,7 +52,8 @@ struct _SecOTRFullIdentity { SecKeyRef publicSigningKey; SecKeyRef privateSigningKey; CFDataRef privateKeyPersistentRef; - + + bool isMessageProtectionKey; uint8_t publicIDHash[kMPIDHashSize]; }; diff --git a/OSX/sec/Security/SecOTRPacketData.h b/OSX/sec/Security/SecOTRPacketData.h index 3fe80994..fc84f8c4 100644 --- a/OSX/sec/Security/SecOTRPacketData.h +++ b/OSX/sec/Security/SecOTRPacketData.h @@ -39,80 +39,84 @@ #include +#include + __BEGIN_DECLS -static CC_NONNULL((1,2)) -OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected); +CF_ASSUME_NONNULL_BEGIN + +static +OSStatus ReadAndVerifyByte(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, uint8_t expected); -static CC_NONNULL((1,2)) -OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected); +static +OSStatus ReadAndVerifyShort(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, uint16_t expected); -static CC_NONNULL((1,2)) -OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected); +static +OSStatus ReadAndVerifyMessageType(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, OTRMessageType expected); -static CC_NONNULL((1,2,3,4)) -OSStatus SizeAndSkipDATA(const uint8_t **bytes, size_t *size, - const uint8_t **dataBytes, size_t *dataSize); -static CC_NONNULL((1,2,3,4)) -OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size, - const uint8_t **mpiBytes, size_t *mpiSize); +static +OSStatus SizeAndSkipDATA(const uint8_t *_Nonnull *_Nonnull bytes, size_t *size, + const uint8_t *_Nonnull *_Nonnull dataBytes, size_t *dataSize); +static +OSStatus SizeAndSkipMPI(const uint8_t *_Nonnull *_Nonnull bytes, size_t *size, + const uint8_t *_Nonnull *_Nonnull mpiBytes, size_t *mpiSize); -static CC_NONNULL((1,2,3)) -OSStatus ReadLongLongCompact(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value); +static +OSStatus ReadLongLongCompact(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint64_t* value); -static CC_NONNULL((1,2,3)) -OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value); +static +OSStatus ReadLongLong(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint64_t* value); -static CC_NONNULL((1,2,3)) -OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value); +static +OSStatus ReadLong(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint32_t* value); -static CC_NONNULL((1,2,3)) -OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value); +static +OSStatus ReadShort(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint16_t* value); -static CC_NONNULL((1,2,3)) -OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t* value); +static +OSStatus ReadByte(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint8_t* value); -static CC_NONNULL((1,2,3)) -OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type); +static +OSStatus ReadMessageType(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, OTRMessageType* type); -static CC_NONNULL((1,2,4)) -OSStatus ReadMPI(const uint8_t**bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x); +static +OSStatus ReadMPI(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x); -static CC_NONNULL((1,2,3,4)) -OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data); +static +OSStatus ReadDATA(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data); -static CC_NONNULL((1,2,3)) -OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId); +static +OSStatus CreatePublicKey(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, _Nonnull SecOTRPublicIdentityRef *_Nonnull publicId); -static CC_NONNULL((2,3)) -CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr); +static +CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef _Nullable allocator, const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr); -static CC_NONNULL((1)) +static void AppendLongLongCompact(CFMutableDataRef appendTo, uint64_t value); -static CC_NONNULL((1)) +static void AppendLongLong(CFMutableDataRef appendTo, uint64_t value); -static CC_NONNULL((1)) +static void AppendLong(CFMutableDataRef appendTo, uint32_t value); -static CC_NONNULL((1)) +static void AppendShort(CFMutableDataRef appendTo, uint16_t value); -static CC_NONNULL((1)) +static void AppendByte(CFMutableDataRef appendTo, uint8_t type); -static CC_NONNULL((1)) +static void AppendMessageType(CFMutableDataRef appendTo, OTRMessageType type); -static CC_NONNULL((1,3)) +static void AppendMPI(CFMutableDataRef appendTo, cc_size n, const cc_unit *x); -static CC_NONNULL((1,3)) +static void AppendDATA(CFMutableDataRef appendTo, size_t size, const uint8_t*data); -static CC_NONNULL((1,2)) +static void AppendPublicKey(CFMutableDataRef appendTo, SecOTRPublicIdentityRef publicId); @@ -122,7 +126,7 @@ void AppendPublicKey(CFMutableDataRef appendTo, SecOTRPublicIdentityRef publicId static uint16_t kCurrentOTRVersion = 0x2; -static inline OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value) +static inline OSStatus ReadLongLong(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint64_t* value) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -146,7 +150,7 @@ fail: return errSecParam; } -static inline OSStatus ReadLongLongCompact(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value) +static inline OSStatus ReadLongLongCompact(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint64_t* value) { bool moreBytes = true; @@ -172,7 +176,7 @@ fail: return !moreBytes ? errSecSuccess : errSecDecode; } -static inline OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value) +static inline OSStatus ReadLong(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint32_t* value) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -192,7 +196,7 @@ fail: return errSecParam; } -static inline OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value) +static inline OSStatus ReadShort(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint16_t* value) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -210,7 +214,7 @@ fail: return errSecParam; } -static inline OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t* value) +static inline OSStatus ReadByte(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, uint8_t* value) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -227,7 +231,7 @@ fail: return errSecParam; } -static inline OSStatus ReadByteAsBool(const uint8_t**bytesPtr, size_t*sizePtr, bool* value) +static inline OSStatus ReadByteAsBool(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, bool* value) { uint8_t byte = 0; @@ -239,7 +243,7 @@ static inline OSStatus ReadByteAsBool(const uint8_t**bytesPtr, size_t*sizePtr, b return result; } -static inline OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type) +static inline OSStatus ReadMessageType(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, OTRMessageType* type) { OSStatus result = errSecParam; uint8_t value; @@ -252,7 +256,7 @@ fail: return result; } -static inline OSStatus ReadMPI(const uint8_t**bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x) +static inline OSStatus ReadMPI(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, cc_size n, cc_unit *x) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -276,7 +280,7 @@ fail: } -static inline OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data) +static inline OSStatus ReadDATA(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, size_t* dataSize, uint8_t* data) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -301,7 +305,7 @@ fail: } -static inline OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId) +static inline OSStatus CreatePublicKey(const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr, _Nonnull SecOTRPublicIdentityRef *_Nonnull publicId) { require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); @@ -336,7 +340,7 @@ fail: } -static inline CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr) +static inline CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef _Nullable allocator, const uint8_t *_Nonnull *_Nonnull bytesPtr, size_t*sizePtr) { CFMutableDataRef result = NULL; uint32_t sizeInStream; @@ -359,7 +363,7 @@ exit: // // Parse and verify functions // -static inline OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected) +static inline OSStatus ReadAndVerifyByte(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, uint8_t expected) { uint8_t found; OSStatus result = ReadByte(bytes, size, &found); @@ -369,7 +373,7 @@ exit: return result; } -static inline OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected) +static inline OSStatus ReadAndVerifyShort(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, uint16_t expected) { uint16_t found; OSStatus result = ReadShort(bytes, size, &found); @@ -379,7 +383,7 @@ exit: return result; } -static inline OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected) +static inline OSStatus ReadAndVerifyMessageType(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, OTRMessageType expected) { OTRMessageType found; OSStatus result = ReadMessageType(bytes, size, &found); @@ -389,12 +393,12 @@ exit: return result; } -static inline OSStatus ReadAndVerifyVersion(const uint8_t**bytes, size_t*size) +static inline OSStatus ReadAndVerifyVersion(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size) { return ReadAndVerifyShort(bytes, size, kCurrentOTRVersion); } -static inline OSStatus ReadAndVerifyHeader(const uint8_t**bytes, size_t*size, OTRMessageType expected) +static inline OSStatus ReadAndVerifyHeader(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, OTRMessageType expected) { OSStatus result = ReadAndVerifyVersion(bytes, size); require_noerr_quiet(result, exit); @@ -406,7 +410,7 @@ exit: return result; } -static inline OSStatus ReadHeader(const uint8_t**bytes, size_t*size, OTRMessageType *messageType) +static inline OSStatus ReadHeader(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, OTRMessageType *messageType) { OSStatus result = ReadAndVerifyVersion(bytes, size); require_noerr_quiet(result, exit); @@ -418,8 +422,8 @@ exit: return result; } -static inline OSStatus SizeAndSkipDATA(const uint8_t **bytes, size_t *size, - const uint8_t **dataBytes, size_t *dataSize) +static inline OSStatus SizeAndSkipDATA(const uint8_t *_Nonnull *_Nonnull bytes, size_t *size, + const uint8_t *_Nonnull *_Nonnull dataBytes, size_t *dataSize) { OSStatus result; uint32_t sizeRead; @@ -436,8 +440,8 @@ exit: return result; } -static inline OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size, - const uint8_t **mpiBytes, size_t *mpiSize) +static inline OSStatus SizeAndSkipMPI(const uint8_t *_Nonnull *_Nonnull bytes, size_t *size, + const uint8_t *_Nonnull *_Nonnull mpiBytes, size_t *mpiSize) { // MPIs looke like data for skipping. return SizeAndSkipDATA(bytes, size, mpiBytes, mpiSize); @@ -550,6 +554,8 @@ static inline void AppendHeader(CFMutableDataRef appendTo, OTRMessageType type) AppendMessageType(appendTo, type); } +CF_ASSUME_NONNULL_END + __END_DECLS #endif diff --git a/OSX/sec/Security/SecOTRPublicIdentity.c b/OSX/sec/Security/SecOTRPublicIdentity.c index b0f666db..37cc0faa 100644 --- a/OSX/sec/Security/SecOTRPublicIdentity.c +++ b/OSX/sec/Security/SecOTRPublicIdentity.c @@ -186,6 +186,7 @@ SecOTRPublicIdentityRef SecOTRPublicIdentityCreateFromBytes(CFAllocatorRef alloc const uint8_t* fullSequenceEnd = *bytes + *size; const uint8_t* keyData = ccder_decode_sequence_tl(&fullSequenceEnd, *bytes, fullSequenceEnd); + require(keyData != NULL, fail); size_t fullSize = (size_t)(fullSequenceEnd - *bytes); size_t keyDataSize; diff --git a/OSX/sec/Security/SecOTRSession.c b/OSX/sec/Security/SecOTRSession.c index 7e4ec347..de5ad666 100644 --- a/OSX/sec/Security/SecOTRSession.c +++ b/OSX/sec/Security/SecOTRSession.c @@ -1359,12 +1359,6 @@ abort: } -OSStatus SecOTRSEndSession(SecOTRSessionRef session, - CFMutableDataRef messageToSend) -{ - return errSecUnimplemented; -} - static CFDataRef data_to_data_error_request(enum SecXPCOperation op, CFDataRef publicPeerId, CFErrorRef *error) { __block CFDataRef result = NULL; securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { diff --git a/OSX/sec/Security/SecOTRSession.h b/OSX/sec/Security/SecOTRSession.h index 652a8000..05ac05d7 100644 --- a/OSX/sec/Security/SecOTRSession.h +++ b/OSX/sec/Security/SecOTRSession.h @@ -80,10 +80,6 @@ OSStatus SecOTRSProcessPacket(SecOTRSessionRef session, CFDataRef incomingPacket, CFMutableDataRef negotiationResponse); -OSStatus SecOTRSEndSession(SecOTRSessionRef session, - CFMutableDataRef messageToSend); - - bool SecOTRSIsForKeys(SecOTRSessionRef session, SecKeyRef myPublic, SecKeyRef theirPublic); bool SecOTRSGetIsReadyForMessages(SecOTRSessionRef session); bool SecOTRSGetIsIdle(SecOTRSessionRef session); diff --git a/OSX/sec/Security/SecPolicy.c b/OSX/sec/Security/SecPolicy.c index 2e15999c..5e32b6eb 100644 --- a/OSX/sec/Security/SecPolicy.c +++ b/OSX/sec/Security/SecPolicy.c @@ -45,9 +45,12 @@ #include #include #include +#include #include +#include + #undef POLICYCHECKMACRO #define POLICYCHECKMACRO(NAME, TRUSTRESULT, SUBTYPE, LEAFCHECK, PATHCHECK, LEAFONLY, CSSMERR, OSSTATUS) \ const CFStringRef kSecPolicyCheck##NAME = CFSTR(#NAME); @@ -76,7 +79,6 @@ const CFStringRef kSecPolicyApple##NAME = CFSTR("1.2.840.113635.100.1."#OID); #include "SecPolicy.list" //Some naming exceptions SEC_CONST_DECL(kSecPolicyMacAppStoreReceipt, "1.2.840.113635.100.1.19") -SEC_CONST_DECL(kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113635.100.1.30"); SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid"); SEC_CONST_DECL (kSecPolicyName, "SecPolicyName"); @@ -134,48 +136,9 @@ SEC_CONST_DECL (kSecPolicyNameAppleAMPService, "AMP"); SEC_CONST_DECL (kSecPolicyNameAppleSiriService, "Siri"); SEC_CONST_DECL (kSecPolicyNameAppleHomeAppClipUploadService, "HomeAppClipUploadService"); SEC_CONST_DECL (kSecPolicyNameAppleUpdatesService, "Updates"); +SEC_CONST_DECL (kSecPolicyNameApplePushCertPortal, "PushCertPortal"); -#define kSecPolicySHA1Size 20 -#define kSecPolicySHA256Size 32 -__unused const UInt8 kAppleCASHA1[kSecPolicySHA1Size] = { - 0x61, 0x1E, 0x5B, 0x66, 0x2C, 0x59, 0x3A, 0x08, 0xFF, 0x58, - 0xD1, 0x4A, 0xE2, 0x24, 0x52, 0xD1, 0x98, 0xDF, 0x6C, 0x60 -}; - -__unused static const UInt8 kAppleTESTCASHA1[kSecPolicySHA1Size] = { - 0xbc, 0x30, 0x55, 0xc8, 0xc8, 0xd3, 0x48, 0x3f, 0xf4, 0x8d, - 0xfe, 0x3d, 0x51, 0x75, 0x31, 0xc9, 0xf4, 0xd7, 0x4a, 0xf7 -}; - -static const UInt8 kITMSCASHA1[kSecPolicySHA1Size] = { - 0x1D, 0x33, 0x42, 0x46, 0x8B, 0x10, 0xBD, 0xE6, 0x45, 0xCE, - 0x44, 0x6E, 0xBB, 0xE8, 0xF5, 0x03, 0x5D, 0xF8, 0x32, 0x22 -}; - -static const UInt8 kFactoryDeviceCASHA1[kSecPolicySHA1Size] = { - 0xef, 0x68, 0x73, 0x17, 0xa4, 0xf8, 0xf9, 0x4b, 0x7b, 0x21, - 0xe2, 0x2f, 0x09, 0x8f, 0xfd, 0x6a, 0xae, 0xc0, 0x0d, 0x63 -}; - -static const UInt8 kApplePKISettingsAuthority[kSecPolicySHA1Size] = { - 0x1D, 0x0C, 0xBA, 0xAD, 0x17, 0xFD, 0x7E, 0x9E, 0x9F, 0xF1, - 0xC9, 0xA2, 0x66, 0x79, 0x60, 0x00, 0x8B, 0xAE, 0x70, 0xB8 -}; - -static const UInt8 kAppleTestPKISettingsAuthority[kSecPolicySHA1Size] = { - 0xDB, 0xBA, 0x25, 0x0B, 0xD8, 0x62, 0x71, 0x87, 0x54, 0x7E, - 0xD7, 0xEF, 0x11, 0x94, 0x7E, 0x82, 0xE6, 0xD8, 0x1C, 0x9A -}; - -static const UInt8 kTestAppleRootCA_ECC_SHA1[kSecPolicySHA1Size] = { - 0x62, 0x0A, 0xED, 0x83, 0xD2, 0x97, 0x4A, 0x77, 0x56, 0x33, - 0x83, 0xBE, 0xDB, 0xF9, 0xA1, 0xBD, 0x5F, 0xFE, 0x55, 0x7B -}; - -__unused static const UInt8 kAppleRootCA_ECC_SHA1[kSecPolicySHA1Size] = { - 0xB5, 0x2C, 0xB0, 0x2F, 0xD5, 0x67, 0xE0, 0x35, 0x9F, 0xE8, - 0xFA, 0x4D, 0x4C, 0x41, 0x03, 0x79, 0x70, 0xFE, 0x01, 0xB0 -}; +#define kSecPolicySHA256Size CC_SHA256_DIGEST_LENGTH // MARK: - // MARK: SecPolicy @@ -390,6 +353,8 @@ SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, policy = SecPolicyCreateAppleBasicAttestationUser(rootDigest); } else if (CFEqual(policyIdentifier, kSecPolicyAppleComponentCertificate)) { policy = SecPolicyCreateAppleComponentCertificate(rootDigest); + } else if (CFEqual(policyIdentifier, kSecPolicyAppleAggregateMetricTransparency)) { + policy = SecPolicyCreateAggregateMetricTransparency(!client); } /* For a couple of common patterns we use the macro, but some of the * policies are deprecated (or not yet available), so we need to ignore the warning. */ @@ -1227,29 +1192,13 @@ errOut: return result; } -static bool SecPolicyAddAnchorSHA1Options(CFMutableDictionaryRef options, - const UInt8 anchorSha1[kSecPolicySHA1Size]) -{ - bool success = false; - CFDataRef anchorData = NULL; - - require(anchorData = CFDataCreate(kCFAllocatorDefault, anchorSha1, kSecPolicySHA1Size), errOut); - add_element(options, kSecPolicyCheckAnchorSHA1, anchorData); - - success = true; - -errOut: - CFReleaseSafe(anchorData); - return success; -} - static bool SecPolicyAddAnchorSHA256Options(CFMutableDictionaryRef options, - const UInt8 anchorSha1[kSecPolicySHA256Size]) + const UInt8 anchorSha256[kSecPolicySHA256Size]) { bool success = false; CFDataRef anchorData = NULL; - require(anchorData = CFDataCreate(kCFAllocatorDefault, anchorSha1, kSecPolicySHA256Size), errOut); + require(anchorData = CFDataCreate(kCFAllocatorDefault, anchorSha256, kSecPolicySHA256Size), errOut); add_element(options, kSecPolicyCheckAnchorSHA256, anchorData); success = true; @@ -1325,18 +1274,223 @@ static bool SecPolicyAddAppleAnchorOptions(CFMutableDictionaryRef options, CFStr return true; } +CFDataRef CreateCFDataFromBase64CFString(CFStringRef base64string) +{ + __block CFDataRef cfData = NULL; + + require_quiet(base64string, errOut); + + CFStringPerformWithCStringAndLength(base64string, ^(const char *base64string_buf, size_t base64string_buf_length) { + void *data = NULL; + + require_quiet(base64string_buf != NULL, errOut); + require_quiet(base64string_buf_length != 0, errOut); + + size_t expected_data_length = SecBase64Decode(base64string_buf, base64string_buf_length, NULL, 0); + require_quiet(expected_data_length != 0, errOut); + + data = malloc(expected_data_length); + require(data != NULL, errOut); + + size_t actual_data_length = SecBase64Decode(base64string_buf, base64string_buf_length, data, expected_data_length); + require_quiet(actual_data_length != 0, errOut); + + cfData = CFDataCreate(kCFAllocatorDefault, (const uint8_t *)data, actual_data_length); + + errOut: + free(data); + return; + }); + +errOut: + return cfData; +} + +static CFStringRef CopyParentDomainNameFromHostName(CFStringRef hostName) +{ + CFStringRef parentDomainName = NULL; + + require_quiet(hostName, errOut); + + CFIndex hostNameLength = CFStringGetLength(hostName); + require_quiet(hostNameLength != 0, errOut); + + CFRange nextLabel = CFStringFind(hostName, CFSTR("."), 0); + require_quiet(nextLabel.location != kCFNotFound && nextLabel.location < (hostNameLength - 1), errOut); + + CFRange parentDomainNameRange = CFRangeMake(nextLabel.location + 1, hostNameLength - nextLabel.location - 1); + parentDomainName = CFStringCreateWithSubstring(NULL, hostName, parentDomainNameRange); + +errOut: + return parentDomainName; +} + +CFArrayRef parseNSPinnedDomains(CFDictionaryRef nsPinnedDomainsDict, CFStringRef hostName, CFStringRef nsPinnedIdentityType) +{ + CFMutableArrayRef targetSPKISHA256 = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + + __block bool hostNamePinned = false; + + // Strip the trailing dot if any. + CFIndex hostNameLength = CFStringGetLength(hostName); + if (hostNameLength > 0 && '.' == CFStringGetCharacterAtIndex(hostName, hostNameLength - 1)) { + hostName = CFStringCreateWithSubstring(NULL, hostName, CFRangeMake(0, hostNameLength - 1)); + require_quiet(hostName, errOut); + } else { + CFRetainSafe(hostName); + } + + CFDictionaryForEach(nsPinnedDomainsDict, ^(const void *key, const void *value) { + CFStringRef parentDomainName = NULL; + + require_quiet(isString(key), errOutNSPinnedDomainsDict); + require_quiet(isDictionary(value), errOutNSPinnedDomainsDict); + + // Match one of the pinned domains to the current endpoint's hostname. + CFStringRef domainName = (CFStringRef)key; + bool hostNameMatched = (CFStringCompare(domainName, hostName, kCFCompareCaseInsensitive) == kCFCompareEqualTo); + + // Match one of the pinned domains to the current endpoint's parent domain if allowed. + if (hostNameMatched == false) { + CFTypeRef nsIncludesSubdomains = CFDictionaryGetValue(value, CFSTR("NSIncludesSubdomains")); + require_quiet(nsIncludesSubdomains == kCFBooleanTrue, errOutNSPinnedDomainsDict); + + parentDomainName = CopyParentDomainNameFromHostName(hostName); + require_quiet(parentDomainName != NULL, errOutNSPinnedDomainsDict); + + hostNameMatched = (CFStringCompare(domainName, parentDomainName, kCFCompareCaseInsensitive) == kCFCompareEqualTo); + } + require_quiet(hostNameMatched, errOutNSPinnedDomainsDict); + + CFTypeRef nsPinnedIdentities = CFDictionaryGetValue(value, nsPinnedIdentityType); + require_quiet(nsPinnedIdentities, errOutNSPinnedDomainsDict); + hostNamePinned = true; + + require_quiet(isArray(nsPinnedIdentities), errOutNSPinnedDomainsDict); + CFArrayForEach(nsPinnedIdentities, ^(const void *v) { + CFDataRef spkiSHA256 = NULL; + + require_quiet(isDictionary(v), errOutNSPinnedIdentities); + + CFTypeRef spkiSHA256base64 = CFDictionaryGetValue(v, CFSTR("SPKI-SHA256-BASE64")); + require_quiet(isString(spkiSHA256base64), errOutNSPinnedIdentities); + + spkiSHA256 = CreateCFDataFromBase64CFString(spkiSHA256base64); + require_quiet(spkiSHA256, errOutNSPinnedIdentities); + + CFArrayAppendValue(targetSPKISHA256, spkiSHA256); + + errOutNSPinnedIdentities: + CFReleaseSafe(spkiSHA256); + }); + + errOutNSPinnedDomainsDict: + CFReleaseSafe(parentDomainName); + return; + }); + +errOut: + CFReleaseSafe(hostName); + if (hostNamePinned == false) { + CFReleaseNull(targetSPKISHA256); + } + return targetSPKISHA256; +} + +static CFArrayRef getNSPinnedIdentitiesForHostName(CFStringRef hostName, CFStringRef nsPinnedIdentityType) +{ + CFMutableArrayRef targetSPKISHA256 = NULL; + + static CFDictionaryRef nsPinnedDomainsDict = NULL; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + CFBundleRef bundle = CFBundleGetMainBundle(); + require(bundle, initializationIncomplete); + + CFTypeRef nsAppTransportSecurityDict = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("NSAppTransportSecurity")); + require_quiet(isDictionary(nsAppTransportSecurityDict), initializationIncomplete); + + nsPinnedDomainsDict = CFDictionaryGetValue(nsAppTransportSecurityDict, CFSTR("NSPinnedDomains")); + require(isDictionary(nsPinnedDomainsDict), initializationIncomplete); + return; + + initializationIncomplete: + nsPinnedDomainsDict = NULL; + }); + // To proceed, this or a previous call must have found NSPinnedDomains in the info dictionary. + require_quiet(nsPinnedDomainsDict, errOut); + + targetSPKISHA256 = (CFMutableArrayRef)parseNSPinnedDomains(nsPinnedDomainsDict, hostName, nsPinnedIdentityType); + + // Return NULL if the hostname (or its parent domain name) is not among the pinned domains. + // Otherwise return an array of zero or more SPKI SHA256 identities. +errOut: + return targetSPKISHA256; +} + +static void SecPolicyAddATSpinningIfInfoSpecified(CFMutableDictionaryRef options) +{ + CFStringRef hostname = CFDictionaryGetValue(options, kSecPolicyCheckSSLHostname); + require_quiet(isString(hostname), errOut); + + CFArrayRef leafSPKISHA256 = getNSPinnedIdentitiesForHostName(hostname, CFSTR("NSPinnedLeafIdentities")); + if (leafSPKISHA256) { + add_element(options, kSecPolicyCheckLeafSPKISHA256, leafSPKISHA256); + } + + CFArrayRef caSPKISHA256 = getNSPinnedIdentitiesForHostName(hostname, CFSTR("NSPinnedCAIdentities")); + if (caSPKISHA256) { + add_element(options, kSecPolicyCheckCAspkiSHA256, caSPKISHA256); + } + +errOut: + return; +} + +void SecPolicyReconcilePinningRequiredIfInfoSpecified(CFMutableDictionaryRef options) +{ + bool hasPinningRequiredKey = false; + CFArrayRef leafSPKISHA256 = NULL; + CFArrayRef caSPKISHA256 = NULL; + + hasPinningRequiredKey = CFDictionaryContainsKey(options, kSecPolicyCheckPinningRequired); + require_quiet(hasPinningRequiredKey, errOut); + + // A non-NULL, empty, leafSPKISHA256 array allows all leaves and thus excludes this hostname from pinning. + leafSPKISHA256 = CFDictionaryGetValue(options, kSecPolicyCheckLeafSPKISHA256); + caSPKISHA256 = CFDictionaryGetValue(options, kSecPolicyCheckCAspkiSHA256); + if (isArray(leafSPKISHA256) && CFArrayGetCount(leafSPKISHA256) == 0 && + isArray(caSPKISHA256) && CFArrayGetCount(caSPKISHA256) == 0) { + CFDictionaryRemoveValue(options, kSecPolicyCheckPinningRequired); + } + + // kSecPolicyCheckPinningRequired and (kSecPolicyCheckLeafSPKISHA256, kSecPolicyCheckCAspkiSHA256) are mutually exclusive. + CFDictionaryRemoveValue(options, kSecPolicyCheckLeafSPKISHA256); + CFDictionaryRemoveValue(options, kSecPolicyCheckCAspkiSHA256); + +errOut: + return; +} + static bool SecPolicyAddPinningRequiredIfInfoSpecified(CFMutableDictionaryRef options) { - CFBundleRef bundle = CFBundleGetMainBundle(); - if (bundle) { - CFTypeRef value = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("SecTrustPinningRequired")); - if (isBoolean(value) && CFBooleanGetValue(value)) { - add_element(options, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + static bool result = false; + static bool hasPinningRequiredKey = false; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + CFBundleRef bundle = CFBundleGetMainBundle(); + if (bundle) { + CFTypeRef value = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("SecTrustPinningRequired")); + if (isBoolean(value) && CFBooleanGetValue(value)) { + hasPinningRequiredKey = true; + } + result = true; } - } else { - return false; + }); + if (result && hasPinningRequiredKey) { + add_element(options, kSecPolicyCheckPinningRequired, kCFBooleanTrue); } - return true; + return result; } // @@ -1380,6 +1534,8 @@ SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) { require_quiet(SecPolicyRemoveWeakHashOptions(options), errOut); require_quiet(SecPolicyAddStrongKeySizeOptions(options), errOut); require_quiet(SecPolicyAddPinningRequiredIfInfoSpecified(options), errOut); + SecPolicyAddATSpinningIfInfoSpecified(options); + SecPolicyReconcilePinningRequiredIfInfoSpecified(options); CFDictionaryAddValue(options, kSecPolicyCheckValidityPeriodMaximums, kCFBooleanTrue); CFDictionaryAddValue(options, kSecPolicyCheckServerAuthEKU, kCFBooleanTrue); // enforces stricter EKU rules than set_ssl_ekus below for certain anchor types #if !TARGET_OS_BRIDGE @@ -1417,6 +1573,8 @@ SecPolicyRef SecPolicyCreateLegacySSL(Boolean server, CFStringRef hostname) { if (server) { // fewer requirements than the standard SSL policy require_quiet(SecPolicyAddPinningRequiredIfInfoSpecified(options), errOut); + SecPolicyAddATSpinningIfInfoSpecified(options); + SecPolicyReconcilePinningRequiredIfInfoSpecified(options); CFDictionaryAddValue(options, kSecPolicyCheckValidityPeriodMaximums, kCFBooleanTrue); #if !TARGET_OS_BRIDGE CFDictionaryAddValue(options, kSecPolicyCheckSystemTrustedCTRequired, kCFBooleanTrue); @@ -1513,7 +1671,7 @@ fail: SecPolicyRef SecPolicyCreateAppleSSLPinned(CFStringRef policyName, CFStringRef hostname, CFStringRef intermediateMarkerOID, CFStringRef leafMarkerOID) { - CFMutableDictionaryRef options = NULL, appleAnchorOptions = NULL; + CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; if (!policyName || !hostname || !leafMarkerOID) { @@ -1578,7 +1736,6 @@ SecPolicyRef SecPolicyCreateAppleSSLPinned(CFStringRef policyName, CFStringRef h errOut: CFReleaseSafe(options); - CFReleaseSafe(appleAnchorOptions); return result; } @@ -1653,6 +1810,13 @@ errOut: return result; } +/* subject:/C=US/O=Apple Inc./OU=Apple iPhone/CN=[TEST] Apple iPhone Device CA */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=[TEST] Apple iPhone Certification Authority */ +const uint8_t kFactoryDeviceCASHA256[CC_SHA256_DIGEST_LENGTH] = { + 0x7b, 0x8e, 0xc8, 0x78, 0xff, 0x3a, 0xcf, 0x61, 0xdd, 0xe6, 0x53, 0x77, 0x2b, 0xe7, 0x32, 0xc5, + 0x97, 0xf4, 0x6b, 0x9c, 0xa6, 0x00, 0xc5, 0x2c, 0xc1, 0x25, 0x85, 0x02, 0x03, 0x06, 0x97, 0x96 +}; + SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void) { CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; @@ -1662,16 +1826,9 @@ SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void) { SecPolicyAddBasicCertOptions(options); -#if 0 - CFDictionaryAddValue(options, kSecPolicyCheckKeyUsage, - kCFBooleanTrue); - CFDictionaryAddValue(options, kSecPolicyCheckExtendedKeyUsage, - kCFBooleanTrue); -#endif - /* Basic X.509 policy with the additional requirements that the chain is anchored at the factory device certificate issuer. */ - require(SecPolicyAddAnchorSHA1Options(options, kFactoryDeviceCASHA1), errOut); + require(SecPolicyAddAnchorSHA256Options(options, kFactoryDeviceCASHA256), errOut); require(result = SecPolicyCreate(kSecPolicyAppleFactoryDeviceCertificate, kSecPolicyNameFactoryDeviceCertificate, options), @@ -1710,6 +1867,13 @@ errOut: return result; } +/* subject:/O=Apple Inc./OU=iTunes Store/CN=iTunes Store Root/C=US/ST=California/L=Cupertino */ +/* issuer :/O=Apple Inc./OU=iTunes Store/CN=iTunes Store Root/C=US/ST=California/L=Cupertino */ +const uint8_t kITMS_CA_SHA256[CC_SHA256_DIGEST_LENGTH] = { + 0xa1, 0xdc, 0x36, 0x23, 0x84, 0xb4, 0xba, 0x0f, 0xaf, 0xea, 0x2a, 0xd4, 0xac, 0xc4, 0x86, 0x8f, + 0xfb, 0xae, 0x57, 0x21, 0x4d, 0x20, 0x88, 0xc8, 0x82, 0xe7, 0x65, 0x13, 0x47, 0xab, 0x81, 0xd7 +}; + SecPolicyRef SecPolicyCreateiTunesStoreURLBag(void) { CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; @@ -1726,7 +1890,7 @@ SecPolicyRef SecPolicyCreateiTunesStoreURLBag(void) { CFSTR("iTunes Store URL Bag")); require(SecPolicyAddChainLengthOptions(options, 2), errOut); - require(SecPolicyAddAnchorSHA1Options(options, kITMSCASHA1), errOut); + require(SecPolicyAddAnchorSHA256Options(options, kITMS_CA_SHA256), errOut); require(result = SecPolicyCreate(kSecPolicyAppleiTunesStoreURLBag, kSecPolicyNameiTunesStoreURLBag, options), errOut); @@ -2093,6 +2257,10 @@ SecPolicyRef SecPolicyCreateOCSPSigner(void) { /* Require id-kp-OCSPSigning extendedKeyUsage to be present, not optional. */ add_eku(options, &oidExtendedKeyUsageOCSPSigning); + /* Check for digitalSignature KU and CA:FALSE. See */ + add_ku(options, kSecKeyUsageDigitalSignature); + CFDictionarySetValue(options, kSecPolicyCheckNotCA, kCFBooleanTrue); + require(result = SecPolicyCreate(kSecPolicyAppleOCSPSigner, kSecPolicyNameOCSPSigner, options), errOut); @@ -2175,7 +2343,6 @@ SecPolicyRef SecPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email) { if (smimeUsage & kSecSignSMIMEUsage) { add_ku(options, kSecKeyUsageUnspecified); add_ku(options, kSecKeyUsageDigitalSignature); - add_ku(options, kSecKeyUsageNonRepudiation); } if (smimeUsage & kSecKeyEncryptSMIMEUsage) { add_ku(options, kSecKeyUsageKeyEncipherment); @@ -2183,31 +2350,18 @@ SecPolicyRef SecPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email) { if (smimeUsage & kSecDataEncryptSMIMEUsage) { add_ku(options, kSecKeyUsageDataEncipherment); } - if (smimeUsage & kSecKeyExchangeDecryptSMIMEUsage) { - add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageDecipherOnly); - } - if (smimeUsage & kSecKeyExchangeEncryptSMIMEUsage) { - add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageEncipherOnly); - } - if (smimeUsage & kSecKeyExchangeBothSMIMEUsage) { - add_ku(options, kSecKeyUsageKeyAgreement | kSecKeyUsageEncipherOnly | kSecKeyUsageDecipherOnly); + if (smimeUsage & kSecKeyExchangeDecryptSMIMEUsage || + smimeUsage & kSecKeyExchangeEncryptSMIMEUsage || + smimeUsage & kSecKeyExchangeBothSMIMEUsage) { + /* */ + add_ku(options, kSecKeyUsageKeyAgreement); } if (email) { CFDictionaryAddValue(options, kSecPolicyCheckEmail, email); } - /* RFC 3850 paragraph 4.4.4 - - If the extended key usage extension is present in the certificate - then interpersonal message S/MIME receiving agents MUST check that it - contains either the emailProtection or the anyExtendedKeyUsage OID as - defined in [KEYM]. S/MIME uses other than interpersonal messaging - MAY require the explicit presence of the extended key usage extension - or other OIDs to be present in the extension or both. - */ add_eku(options, NULL); /* eku extension is optional */ - add_eku(options, &oidAnyExtendedKeyUsage); add_eku(options, &oidExtendedKeyUsageEmailProtection); #if !TARGET_OS_IPHONE @@ -2691,21 +2845,19 @@ SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void) return CreateConfigurationProfileSigner(false); } - SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void) { -#if RC_SEED_BUILD - // Seed builds permit the QA signer - return CreateConfigurationProfileSigner(true); -#else // !RC_SEED_BUILD - if (os_variant_has_internal_diagnostics("com.apple.security")) { - // Internal builds permit the QA signer - return CreateConfigurationProfileSigner(true); + CFStringRef releaseType = MGCopyAnswer(kMGQReleaseType, NULL); + SecPolicyRef result = NULL; + if (releaseType == NULL) { + // customer variants do not trust the QA signer + result = CreateConfigurationProfileSigner(false); } else { - // GM builds do not trust the QA signer - return CreateConfigurationProfileSigner(false); + // all other variants (beta, carrier, internal, etc) allow the QA signer + result = CreateConfigurationProfileSigner(true); } -#endif // !RC_SEED_BUILD + CFReleaseNull(releaseType); + return result; } SecPolicyRef SecPolicyCreateOSXProvisioningProfileSigning(void) @@ -2739,54 +2891,6 @@ errOut: return result; } - -SecPolicyRef SecPolicyCreateOTAPKISigner(void) -{ - SecPolicyRef result = NULL; - CFMutableDictionaryRef options = NULL; - require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks), errOut); - SecPolicyAddBasicX509Options(options); - - SecPolicyAddAnchorSHA1Options(options, kApplePKISettingsAuthority); - require(SecPolicyAddChainLengthOptions(options, 2), errOut); - - require(result = SecPolicyCreate(kSecPolicyAppleOTAPKISigner, - kSecPolicyNameOTAPKISigner, options), errOut); - -errOut: - CFReleaseSafe(options); - return result; - -} - - -SecPolicyRef SecPolicyCreateTestOTAPKISigner(void) -{ - /* Guard against use on production devices */ - if (!SecIsInternalRelease()) { - return SecPolicyCreateOTAPKISigner(); - } - - SecPolicyRef result = NULL; - CFMutableDictionaryRef options = NULL; - require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks), errOut); - SecPolicyAddBasicX509Options(options); - - SecPolicyAddAnchorSHA1Options(options, kAppleTestPKISettingsAuthority); - require(SecPolicyAddChainLengthOptions(options, 2), errOut); - - require(result = SecPolicyCreate(kSecPolicyAppleTestOTAPKISigner, - kSecPolicyNameTestOTAPKISigner, options), errOut); - -errOut: - CFReleaseSafe(options); - return result; -} - /*! @function SecPolicyCreateAppleSMPEncryption @abstract Check for intermediate certificate 'Apple System Integration CA - G3' by name, @@ -2830,6 +2934,13 @@ errOut: return result; } +/* subject:/CN=Test Apple Root CA - ECC/OU=Certification Authority/O=Apple Inc./C=US */ +/* issuer :/CN=Test Apple Root CA - ECC/OU=Certification Authority/O=Apple Inc./C=US */ +const uint8_t kTestAppleRootCA_ECC_SHA256[CC_SHA256_DIGEST_LENGTH] = { + 0xe8, 0x6a, 0xd6, 0x5c, 0x74, 0x60, 0x21, 0x14, 0x47, 0xc6, 0x6a, 0xd7, 0x5f, 0xf8, 0x06, 0x7b, + 0xec, 0xb5, 0x52, 0x7e, 0x4e, 0xa1, 0xac, 0x48, 0xcf, 0x3c, 0x53, 0x8f, 0x4d, 0x2b, 0x20, 0xa9 +}; + /*! @function SecPolicyCreateTestAppleSMPEncryption @abstract Check for intermediate certificate 'Test Apple System Integration CA - ECC' by name, @@ -2845,7 +2956,7 @@ SecPolicyRef SecPolicyCreateTestAppleSMPEncryption(void) &kCFTypeDictionaryValueCallBacks), errOut); SecPolicyAddBasicCertOptions(options); - SecPolicyAddAnchorSHA1Options(options, kTestAppleRootCA_ECC_SHA1); + SecPolicyAddAnchorSHA256Options(options, kTestAppleRootCA_ECC_SHA256); require(SecPolicyAddChainLengthOptions(options, 3), errOut); CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, @@ -2923,7 +3034,6 @@ SecPolicyCreateAppleServerAuthCommon(CFStringRef hostname, const DERItem *leafMarkerOID, const DERItem *UATLeafMarkerOID) { - CFMutableDictionaryRef appleAnchorOptions = NULL; CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; CFDataRef oid = NULL, uatoid = NULL; @@ -2986,7 +3096,6 @@ SecPolicyCreateAppleServerAuthCommon(CFStringRef hostname, require(result, errOut); errOut: - CFReleaseSafe(appleAnchorOptions); CFReleaseSafe(options); CFReleaseSafe(oid); CFReleaseSafe(uatoid); @@ -2999,12 +3108,10 @@ errOut: */ SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname) { - SecPolicyRef result = SecPolicyCreateSSL(true, hostname); - - SecPolicySetOid(result, kSecPolicyAppleIDSService); - SecPolicySetName(result, kSecPolicyNameAppleIDSBag); - - return result; + return SecPolicyCreateAppleServerAuthCommon(hostname, NULL, kSecPolicyAppleIDSService, + kSecPolicyNameAppleIDSBag, + &oidAppleCertExtAppleServerAuthenticationIDSProd, + &oidAppleCertExtAppleServerAuthenticationIDSProdQA); } /*! @@ -3483,7 +3590,6 @@ errOut: } SecPolicyRef SecPolicyCreateAppleHomeKitServerAuth(CFStringRef hostname) { - CFMutableDictionaryRef appleAnchorOptions = NULL; CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; CFDataRef oid = NULL; @@ -3521,7 +3627,6 @@ SecPolicyRef SecPolicyCreateAppleHomeKitServerAuth(CFStringRef hostname) { require(result, errOut); errOut: - CFReleaseSafe(appleAnchorOptions); CFReleaseSafe(options); CFReleaseSafe(oid); return result; @@ -3668,9 +3773,6 @@ errOut: SecPolicyRef SecPolicyCreateAppleWarsaw(void) { CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; -#if TARGET_OS_BRIDGE - CFMutableDictionaryRef appleAnchorOptions = NULL; -#endif require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, @@ -3785,9 +3887,6 @@ errOut: SecPolicyRef SecPolicyCreateMobileSoftwareUpdate(void) { CFMutableDictionaryRef options = NULL; SecPolicyRef result = NULL; -#if TARGET_OS_BRIDGE - CFMutableDictionaryRef appleAnchorOptions = NULL; -#endif require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); @@ -4184,6 +4283,140 @@ errOut: return result; } +/* subject:/CN=Apple External EC Root/O=Apple Inc./C=US */ +/* SKID: 3F:A4:C0:94:20:70:CB:3B:DD:A8:54:E6:14:1E:29:CC:4D:14:38:53 */ +/* Not Before: Jan 23 00:46:48 2020 GMT, Not After : Jan 18 00:00:00 2045 GMT */ +/* Signature Algorithm: ecdsa-with-SHA384 */ +const uint8_t AppleExternalECRoot_SHA256[kSecPolicySHA256Size] = { + 0x72, 0x56, 0x6e, 0x6f, 0x66, 0x30, 0x0c, 0xfd, 0x24, 0xe5, 0xe6, 0x85, 0xa2, 0xf1, 0x5a, 0x74, + 0x9d, 0xe0, 0x4b, 0xb0, 0x38, 0x50, 0x77, 0x91, 0x96, 0x63, 0x6e, 0x07, 0x23, 0x0f, 0x91, 0x1e +}; +/* subject:/CN=Test Apple External EC Root/O=Apple Inc./C=US */ +/* SKID: 07:6B:07:47:33:E4:96:B4:FC:6F:FA:32:2C:8E:BE:70:C2:8F:80:3C */ +/* Not Before: Nov 5 18:00:46 2019 GMT, Not After : Oct 29 18:00:46 2044 GMT */ +/* Signature Algorithm: ecdsa-with-SHA384 */ +const uint8_t TestAppleExternalECRoot_SHA256[kSecPolicySHA256Size] = { + 0xf3, 0x98, 0x39, 0xdc, 0x6a, 0x64, 0xf6, 0xe3, 0xa0, 0xdc, 0x97, 0xd7, 0x83, 0x61, 0x6b, 0x84, + 0x9f, 0xdf, 0xa1, 0x70, 0x54, 0x59, 0xae, 0x96, 0x0f, 0x41, 0xe1, 0x16, 0xa3, 0xb4, 0x8b, 0xb5 +}; +SecPolicyRef SecPolicyCreateApplePayQRCodeEncryption(void) { + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + /* Check expiration */ + SecPolicyAddBasicX509Options(options); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Apple External EC CA 1 - G1 */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.22")); + + /* ApplePay QR Code Encryption */ + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.13.3")); + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + require(SecPolicyAddAnchorSHA256Options(options, AppleExternalECRoot_SHA256),errOut); + if (SecIsInternalRelease()) { + require(SecPolicyAddAnchorSHA256Options(options, TestAppleExternalECRoot_SHA256),errOut); + } + + /* Check revocation using any available method */ + add_element(options, kSecPolicyCheckRevocation, kSecPolicyCheckRevocationAny); + + require(result = SecPolicyCreate(kSecPolicyApplePayQRCodeEncryption, + kSecPolicyNamePayQRCodeEncryption, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +SecPolicyRef SecPolicyCreateApplePayQRCodeSigning(void) { + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + /* Check expiration */ + SecPolicyAddBasicX509Options(options); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Apple External EC CA 1 - G1 */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.22")); + + /* ApplePay QR Code Signing */ + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.12.12")); + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + require(SecPolicyAddAnchorSHA256Options(options, AppleExternalECRoot_SHA256),errOut); + if (SecIsInternalRelease()) { + require(SecPolicyAddAnchorSHA256Options(options, TestAppleExternalECRoot_SHA256),errOut); + } + + /* Check revocation using any available method */ + add_element(options, kSecPolicyCheckRevocation, kSecPolicyCheckRevocationAny); + + require(result = SecPolicyCreate(kSecPolicyApplePayQRCodeSigning, + kSecPolicyNamePayQRCodeSigning, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +SecPolicyRef SecPolicyCreateAppleAccessoryUpdateSigning(void) { + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + /* No expiration check */ + SecPolicyAddBasicCertOptions(options); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Apple Anchor */ + require_quiet(SecPolicyAddAppleAnchorOptions(options, kSecPolicyNameAccessoryUpdateSigning), errOut); + + /* Apple External EC CA 1 - G1 */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.17")); + + /* Accessory Manufacturer Firmware Signing Prod */ + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.12.9")); + if (isCFPreferenceInSecurityDomain(CFSTR("AllowAccessoryUpdateSigningBeta"))) { + add_leaf_marker_string(options, CFSTR("1.2.840.113635.100.12.10")); // ProdQA + } + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + /* Check revocation using any available method */ + add_element(options, kSecPolicyCheckRevocation, kSecPolicyCheckRevocationAny); + + require(result = SecPolicyCreate(kSecPolicyAppleAccessoryUpdateSigning, + kSecPolicyNameAccessoryUpdateSigning, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateEscrowServiceIdKeySigning(void) { SecPolicyRef result = NULL; @@ -4235,3 +4468,51 @@ errOut: CFReleaseSafe(options); return result; } + +SecPolicyRef SecPolicyCreateAggregateMetricTransparency(bool facilitator) +{ + CFMutableDictionaryRef options = NULL; + SecPolicyRef result = NULL; + + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + SecPolicyAddBasicX509Options(options); + + /* Anchored to the Apple Roots */ + require(SecPolicyAddAppleAnchorOptions(options, kSecPolicyNameAggregateMetricTransparency), errOut); + + /* Exactly 3 certs in the chain */ + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + /* Intermediate marker OID matches AAICA 6 */ + add_element(options, kSecPolicyCheckIntermediateMarkerOid, CFSTR("1.2.840.113635.100.6.2.26")); + + /* Leaf marker OID matches expected OID for either Facilitator or Partner */ + if (facilitator) { + add_element(options, kSecPolicyCheckLeafMarkerOidWithoutValueCheck, CFSTR("1.2.840.113635.100.12.17")); + } else { + add_element(options, kSecPolicyCheckLeafMarkerOidWithoutValueCheck, CFSTR("1.2.840.113635.100.12.18")); + } + + /* Check revocation using any available method */ + add_element(options, kSecPolicyCheckRevocation, kSecPolicyCheckRevocationAny); + + /* RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. */ + require(SecPolicyAddStrongKeySizeOptions(options), errOut); + + /* Require CT */ + if (!SecIsInternalRelease() || !isCFPreferenceInSecurityDomain(CFSTR("disableAggregateMetricsCTCheck"))) { + add_element(options, kSecPolicyCheckCTRequired, kCFBooleanTrue); + } + + /* Check for weak hashes */ + // require(SecPolicyRemoveWeakHashOptions(options), errOut); // the current WWDR CA cert is signed with SHA1 + require(result = SecPolicyCreate(kSecPolicyAppleAggregateMetricTransparency, + kSecPolicyNameAggregateMetricTransparency, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} diff --git a/OSX/sec/Security/SecPolicy.list b/OSX/sec/Security/SecPolicy.list index 621b1855..bd0ddbc4 100644 --- a/OSX/sec/Security/SecPolicy.list +++ b/OSX/sec/Security/SecPolicy.list @@ -35,8 +35,6 @@ POLICYMACRO(EscrowService, 24, E, AppleEscrowService, POLICYMACRO(ProfileSigner, 25, E, AppleProfileSigner, , Y, ConfigurationProfileSigner) POLICYMACRO(QAProfileSigner, 26, E, AppleQAProfileSigner, , Y, QAConfigurationProfileSigner) POLICYMACRO(TestMobileStore, 27, E, AppleTestMobileStore, , Y, TestMobileStoreSigner) -POLICYMACRO(OTAPKISigner, 28, E, AppleOTAPKIAssetSigner, , Y, OTAPKISigner) -POLICYMACRO(TestOTAPKISigner, 29, E, AppleTestOTAPKIAssetSigner, , Y, TestOTAPKISigner) POLICYMACRO(IDValidationRecordSigning, 30, E, AppleIDValidationRecordSigningPolicy, , Y, AppleIDValidationRecordSigningPolicy) POLICYMACRO(SMPEncryption, 31, E, AppleSMPEncryption, , Y, AppleSMPEncryption) POLICYMACRO(TestSMPEncryption, 32, E, AppleTestSMPEncryption, , Y, TestAppleSMPEncryption) @@ -101,6 +99,9 @@ POLICYMACRO(KeyTransparency, 93, E, KT, POLICYMACRO(LegacySSL, 94, E, legacySSL, , , LegacySSL) POLICYMACRO(Alisha, 95, E, Alisha, , Y, Alisha) POLICYMACRO(MeasuredBootPolicySigning, 96, E, MeasuredBootPolicySigning, , Y, MeasuredBootPolicySigning) -// 97-99 used on master +POLICYMACRO(PayQRCodeEncryption, 97, E, ApplePayQRCodeEncryption, , Y, ApplePayQRCodeEncryption) +POLICYMACRO(PayQRCodeSigning, 98, E, ApplePayQRCodeSigning, , Y, ApplePayQRCodeSigning) +POLICYMACRO(AccessoryUpdateSigning, 99, E, AccessoryUpdateSigning, , Y, AppleAccessoryUpdateSigning) POLICYMACRO(EscrowServiceIdKeySigning, 100, E, AppleEscrowServiceIdKeySigning, , Y, EscrowServiceIdKeySigning) POLICYMACRO(PCSEscrowServiceIdKeySigning, 101, E, ApplePCSEscrowServiceIdKeySigning, , Y, PCSEscrowServiceIdKeySigning) +POLICYMACRO(AggregateMetricTransparency, 102, E, AggregateMetricTransparency, , , AggregateMetricTransparency) diff --git a/OSX/sec/Security/SecPolicyChecks.list b/OSX/sec/Security/SecPolicyChecks.list index 18072c46..91f55d0f 100644 --- a/OSX/sec/Security/SecPolicyChecks.list +++ b/OSX/sec/Security/SecPolicyChecks.list @@ -23,7 +23,7 @@ POLICYCHECKMACRO(TemporalValidity, R, E, L, A, O, 0x8001210A, errS POLICYCHECKMACRO(WeakKeySize, F, S, L, A, O, 0x80012115, errSecUnsupportedKeySize) //CSSMERR_TP_INVALID_CERTIFICATE POLICYCHECKMACRO(WeakSignature, F, H, L, A, O, 0x80010955, errSecInvalidDigestAlgorithm) //CSSMERR_CSP_INVALID_DIGEST_ALGORITHM POLICYCHECKMACRO(KeyUsage, R, U, L, , O, 0x80012406, errSecInvalidKeyUsageForPolicy) //CSSMERR_APPLETP_INVALID_KEY_USAGE -POLICYCHECKMACRO(ExtendedKeyUsage, R, U, L, , O, 0x80012407, errSecInvalidExtendedKeyUsage) //CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE +POLICYCHECKMACRO(ExtendedKeyUsage, R, U, L, A, O, 0x80012407, errSecInvalidExtendedKeyUsage) //CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE POLICYCHECKMACRO(SubjectCommonName, R, P, L, , O, 0x8001243B, errSecInvalidSubjectName) //CSSMERR_APPLETP_IDENTIFIER_MISSING POLICYCHECKMACRO(SubjectCommonNamePrefix, R, P, L, , O, 0x8001243B, errSecInvalidSubjectName) //CSSMERR_APPLETP_IDENTIFIER_MISSING POLICYCHECKMACRO(SubjectCommonNameTEST, R, P, L, , O, 0x8001243B, errSecInvalidSubjectName) //CSSMERR_APPLETP_IDENTIFIER_MISSING @@ -36,6 +36,8 @@ POLICYCHECKMACRO(LeafMarkerOidWithoutValueCheck, R, P, L, , O, 0x80012439, errS POLICYCHECKMACRO(LeafMarkersProdAndQA, R, P, L, , O, 0x80012439, errSecMissingRequiredExtension) //CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION POLICYCHECKMACRO(BlackListedLeaf, F, B, L, , , 0x8001210C, errSecCertificateRevoked) //CSSMERR_TP_CERT_REVOKED POLICYCHECKMACRO(GrayListedLeaf, R, T, L, , , 0x8001212A, errSecNotTrusted) //CSSMERR_TP_NOT_TRUSTED +POLICYCHECKMACRO(LeafSPKISHA256, R, P, L, , , 0x8001243D, errSSLATSCertificateTrustViolation) //CSSMERR_APPLETP_LEAF_PIN_MISMATCH +POLICYCHECKMACRO(NotCA, R, C, L, , O, 0x80012116, errSecCertificateIsCA) // CSSMERR_TP_INVALID_CERT_AUTHORITY /******************************************************** *********** Unverified Intermediate Checks ************* @@ -54,11 +56,11 @@ POLICYCHECKMACRO(IntermediateCountry, R, P, , A, , 0x800124 /******************************************************** ************** Unverified Anchor Checks **************** ********************************************************/ -POLICYCHECKMACRO(AnchorSHA1, R, P, , A, , 0x8001243C, errSecInvalidRoot) //CSSMERR_APPLETP_CA_PIN_MISMATCH POLICYCHECKMACRO(AnchorSHA256, R, P, , A, , 0x8001243C, errSecInvalidRoot) //CSSMERR_APPLETP_CA_PIN_MISMATCH POLICYCHECKMACRO(AnchorTrusted, R, T, , , , 0x8001212A, errSecNotTrusted) //CSSMERR_TP_NOT_TRUSTED POLICYCHECKMACRO(MissingIntermediate, R, T, , , , 0x8001212A, errSecCreateChainFailed) //CSSMERR_TP_NOT_TRUSTED POLICYCHECKMACRO(AnchorApple, R, P, , A, , 0x8001243C, errSecInvalidRoot) //CSSMERR_APPLETP_CA_PIN_MISMATCH +POLICYCHECKMACRO(CAspkiSHA256, R, P, , A, , 0x8001243C, errSSLATSCertificateTrustViolation) //CSSMERR_APPLETP_CA_PIN_MISMATCH /******************************************************** *********** Unverified Certificate Checks ************** @@ -66,7 +68,7 @@ POLICYCHECKMACRO(AnchorApple, R, P, , A, , 0x8001243C, errS POLICYCHECKMACRO(NonEmptySubject, R, C, , A, O, 0x80012437, errSecInvalidSubjectName) //CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT POLICYCHECKMACRO(IdLinkage, R, C, , A, , 0x80012404, errSecInvalidIDLinkage) //CSSMERR_APPLETP_INVALID_AUTHORITY_ID POLICYCHECKMACRO(KeySize, R, P, , A, O, 0x80010918, errSecUnsupportedKeySize) //CSSMERR_CSP_UNSUPPORTED_KEY_SIZE -POLICYCHECKMACRO(SignatureHashAlgorithms, R, P, , A, O, 0x80010913, errSecInvalidDigestAlgorithm) //CSSMERR_CSP_ALGID_MISMATCH +POLICYCHECKMACRO(SignatureHashAlgorithms, R, H, , A, O, 0x80010913, errSecInvalidDigestAlgorithm) //CSSMERR_CSP_ALGID_MISMATCH POLICYCHECKMACRO(CertificatePolicy, R, P, , A, O, 0x80012439, errSecInvalidPolicyIdentifiers) //CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION POLICYCHECKMACRO(ValidRoot, R, E, , , , 0x8001210A, errSecCertificateExpired) //CSSMERR_TP_CERT_EXPIRED @@ -81,12 +83,12 @@ POLICYCHECKMACRO(PolicyConstraints, R, C, , , , 0x80012115, errS POLICYCHECKMACRO(GrayListedKey, R, T, , , , 0x8001212A, errSecNotTrusted) //CSSMERR_TP_NOT_TRUSTED POLICYCHECKMACRO(BlackListedKey, F, B, , , , 0x8001210C, errSecCertificateRevoked) //CSSMERR_TP_CERT_REVOKED POLICYCHECKMACRO(UsageConstraints, D, D, , , , 0x80012436, errSecTrustSettingDeny) //CSSMERR_APPLETP_TRUST_SETTING_DENY -POLICYCHECKMACRO(SystemTrustedWeakHash, R, C, , A, , 0x80010955, errSecInvalidDigestAlgorithm) //CSSMERR_CSP_INVALID_DIGEST_ALGORITHM -POLICYCHECKMACRO(SystemTrustedWeakKey, R, C, , A, , 0x80010918, errSecUnsupportedKeySize) //CSSMERR_CSP_UNSUPPORTED_KEY_SIZE +POLICYCHECKMACRO(SystemTrustedWeakHash, R, H, , A, , 0x80010955, errSecInvalidDigestAlgorithm) //CSSMERR_CSP_INVALID_DIGEST_ALGORITHM +POLICYCHECKMACRO(SystemTrustedWeakKey, R, S, , A, , 0x80010918, errSecUnsupportedKeySize) //CSSMERR_CSP_UNSUPPORTED_KEY_SIZE POLICYCHECKMACRO(PinningRequired, R, P, L, , , 0x8001243C, errSecInvalidRoot) //CSSMERR_APPLETP_CA_PIN_MISMATCH POLICYCHECKMACRO(Revocation, F, V, L, , , 0x8001210C, errSecCertificateRevoked) //CSSMERR_TP_CERT_REVOKED POLICYCHECKMACRO(RevocationResponseRequired, R, P, L, , , 0x80012423, errSecIncompleteCertRevocationCheck) //CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK -POLICYCHECKMACRO(CTRequired, R, T, , , , 0x8001212A, errSecNotTrusted) //CSSMERR_TP_NOT_TRUSTED +POLICYCHECKMACRO(CTRequired, R, T, , A, , 0x8001212A, errSecNotTrusted) //CSSMERR_TP_NOT_TRUSTED POLICYCHECKMACRO(SystemTrustedCTRequired, R, C, , A, , 0x80012114, errSecVerifyActionFailed) //CSSMERR_TP_VERIFY_ACTION_FAILED POLICYCHECKMACRO(IssuerPolicyConstraints, F, B, , , , 0x80012120, errSecCertificatePolicyNotAllowed) //CSSMERR_TP_INVALID_POLICY_IDENTIFIERS POLICYCHECKMACRO(IssuerNameConstraints, F, B, , , , 0x8001211F, errSecCertificateNameNotAllowed) //CSSMERR_TP_INVALID_NAME diff --git a/OSX/sec/Security/SecPolicyLeafCallbacks.c b/OSX/sec/Security/SecPolicyLeafCallbacks.c index d7562db8..36d614e4 100644 --- a/OSX/sec/Security/SecPolicyLeafCallbacks.c +++ b/OSX/sec/Security/SecPolicyLeafCallbacks.c @@ -62,6 +62,10 @@ static bool keyusage_allows(SecKeyUsage keyUsage, CFTypeRef xku) { SInt32 dku; CFNumberGetValue((CFNumberRef)xku, kCFNumberSInt32Type, &dku); SecKeyUsage ku = (SecKeyUsage)dku; + /* kSecKeyUsageUnspecified is a special sentinel for allowing a missing KU extension */ + if (ku == kSecKeyUsageUnspecified) { + return (keyUsage == ku); + } return (keyUsage & ku) == ku; } @@ -303,15 +307,13 @@ bool SecPolicyCheckCertSSLHostname(SecCertificateRef cert, CFTypeRef pvcValue) { obtained by SecCertificateCopyIPAddresses. Comparisons must always use the canonical data representation of the address, since string notation may omit zeros, etc. */ - CFArrayRef ipAddresses = SecCertificateCopyIPAddresses(cert); + CFArrayRef ipAddresses = SecCertificateCopyIPAddressDatas(cert); CFIndex ix, count = (ipAddresses) ? CFArrayGetCount(ipAddresses) : 0; for (ix = 0; ix < count && !dnsMatch; ++ix) { - CFStringRef ipAddress = (CFStringRef)CFArrayGetValueAtIndex(ipAddresses, ix); - CFDataRef addrData = SecFrameworkCopyIPAddressData(ipAddress); - if (CFEqualSafe(hostIPData, addrData)) { + CFDataRef ipAddress = (CFDataRef)CFArrayGetValueAtIndex(ipAddresses, ix); + if (CFEqualSafe(hostIPData, ipAddress)) { dnsMatch = true; } - CFReleaseSafe(addrData); } CFReleaseSafe(ipAddresses); CFReleaseSafe(hostIPData); @@ -693,6 +695,13 @@ bool SecPolicyCheckCertUnparseableExtension(SecCertificateRef cert, CFTypeRef pv return true; } +bool SecPolicyCheckCertNotCA(SecCertificateRef cert, CFTypeRef pvcValue) { + if (SecCertificateIsCA(cert)) { + return false; + } + return true; +} + /* * MARK: SecLeafPVC functions */ diff --git a/OSX/sec/Security/SecRSAKey.c b/OSX/sec/Security/SecRSAKey.c index fb8f2c51..66f9f239 100644 --- a/OSX/sec/Security/SecRSAKey.c +++ b/OSX/sec/Security/SecRSAKey.c @@ -607,12 +607,13 @@ static CFDataRef SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_ful { const size_t result_size = ccrsa_export_priv_size(fullkey); - CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size); + CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size); - if (pkcs1 == NULL) + if (pkcs1 == NULL) { return NULL; + } - CFDataSetLength(pkcs1, result_size); + CFDataSetLength(pkcs1, result_size); uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1); diff --git a/OSX/sec/Security/SecRecoveryKey.m b/OSX/sec/Security/SecRecoveryKey.m index a59b922a..5f400e02 100644 --- a/OSX/sec/Security/SecRecoveryKey.m +++ b/OSX/sec/Security/SecRecoveryKey.m @@ -9,9 +9,9 @@ #import #import #import +#import #import -#import #import @@ -301,7 +301,7 @@ RKBackupCreateECKey(SecRecoveryKey *rk, bool returnFullkey) status = ccec_generate_key_deterministic(cp, CFDataGetLength(derivedSecret), CFDataGetBytePtr(derivedSecret), - ccDRBGGetRngState(), + ccrng(NULL), CCEC_GENKEY_DETERMINISTIC_COMPACT, fullKey); require_noerr(status, fail); diff --git a/OSX/sec/Security/SecServerEncryptionSupport.c b/OSX/sec/Security/SecServerEncryptionSupport.c index 507a181b..e43f0f6b 100644 --- a/OSX/sec/Security/SecServerEncryptionSupport.c +++ b/OSX/sec/Security/SecServerEncryptionSupport.c @@ -327,11 +327,7 @@ CFDataRef SecCopyDecryptedForServer(SecKeyRef serverFullKey, CFDataRef blob, CFE CFDataRef SecCopyEncryptedToServer(SecTrustRef trustedEvaluation, CFDataRef dataToEncrypt, CFErrorRef *error) { CFDataRef result = NULL; -#if TARGET_OS_OSX - SecKeyRef trustKey = SecTrustCopyPublicKey_ios(trustedEvaluation); -#else - SecKeyRef trustKey = SecTrustCopyPublicKey(trustedEvaluation); -#endif + SecKeyRef trustKey = SecTrustCopyKey(trustedEvaluation); require_action_quiet(trustKey, fail, SecError(errSecInteractionNotAllowed, error, CFSTR("Failed to get key out of trust ref, was it evaluated?"))); diff --git a/OSX/sec/Security/SecSharedCredential.c b/OSX/sec/Security/SecSharedCredential.c index b9ec9bf6..f77c9af2 100644 --- a/OSX/sec/Security/SecSharedCredential.c +++ b/OSX/sec/Security/SecSharedCredential.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2014-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -36,9 +36,29 @@ /* forward declarations */ OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, CFStringRef account, CFStringRef password, CFErrorRef *error); OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, CFErrorRef *error); +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST +OSStatus SecCopySharedWebCredentialSyncUsingAuthSvcs(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, CFErrorRef *error); +#endif #if SHAREDWEBCREDENTIALS +// OSX now has SWC enabled, but cannot link SharedWebCredentials framework: rdar://59958701 +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST + +OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, + CFStringRef account, + CFStringRef password, + CFErrorRef *error) +{ + OSStatus status = errSecUnimplemented; + if (error) { + SecError(status, error, CFSTR("SecAddSharedWebCredentialSync not supported on this platform")); + } + return status; +} + +#else + OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, CFStringRef account, CFStringRef password, @@ -59,7 +79,7 @@ OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, } status = SecOSStatusWith(^bool (CFErrorRef *error) { CFTypeRef raw_result = NULL; - bool xpc_result; + bool xpc_result = false; bool internal_spi = false; // TODO: support this for SecurityDevTests if(internal_spi && gSecurityd && gSecurityd->sec_add_shared_web_credential) { xpc_result = gSecurityd->sec_add_shared_web_credential(args, NULL, NULL, NULL, SecAccessGroupsGetCurrent(), &raw_result, error); @@ -84,6 +104,7 @@ OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, return status; } +#endif /* !TARGET_OS_OSX || !TARGET_OS_MACCATALYST */ #endif /* SHAREDWEBCREDENTIALS */ void SecAddSharedWebCredential(CFStringRef fqdn, @@ -147,6 +168,23 @@ void SecAddSharedWebCredential(CFStringRef fqdn, } #if SHAREDWEBCREDENTIALS + +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST + +OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, + CFStringRef account, + CFArrayRef *credentials, + CFErrorRef *error) +{ + OSStatus status = errSecUnimplemented; + if (error) { + SecError(status, error, CFSTR("SecCopySharedWebCredentialSync not supported on this platform")); + } + return status; +} + +#else + OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, @@ -164,7 +202,7 @@ OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, } status = SecOSStatusWith(^bool (CFErrorRef *error) { CFTypeRef raw_result = NULL; - bool xpc_result; + bool xpc_result = false; bool internal_spi = false; // TODO: support this for SecurityDevTests if(internal_spi && gSecurityd && gSecurityd->sec_copy_shared_web_credential) { xpc_result = gSecurityd->sec_copy_shared_web_credential(args, NULL, NULL, NULL, SecAccessGroupsGetCurrent(), &raw_result, error); @@ -192,6 +230,7 @@ OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, return status; } +#endif /* !TARGET_OS_OSX || !TARGET_OS_MACCATALYST */ #endif /* SHAREDWEBCREDENTIALS */ void SecRequestSharedWebCredential(CFStringRef fqdn, @@ -227,7 +266,11 @@ void SecRequestSharedWebCredential(CFStringRef fqdn, __block CFStringRef accountStr = CFRetainSafe(account); dispatch_async(dst_queue, ^{ +#if TARGET_OS_OSX || TARGET_OS_MACCATALYST + OSStatus status = SecCopySharedWebCredentialSyncUsingAuthSvcs(serverStr, accountStr, &result, &error); +#else OSStatus status = SecCopySharedWebCredentialSync(serverStr, accountStr, &result, &error); +#endif CFReleaseSafe(serverStr); CFReleaseSafe(accountStr); @@ -250,7 +293,7 @@ void SecRequestSharedWebCredential(CFStringRef fqdn, } CFReleaseSafe(error); }); -#endif +#endif /* SHAREDWEBCREDENTIALS */ } diff --git a/OSX/sec/Security/SecSharedCredential.m b/OSX/sec/Security/SecSharedCredential.m new file mode 100644 index 00000000..4fd5f188 --- /dev/null +++ b/OSX/sec/Security/SecSharedCredential.m @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2020 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@ + * + * SecSharedCredential.m - Retrieve shared credentials with AuthenticationServices. + * + */ + +#include +#include +#include +#include +#include "SecItemInternal.h" +#include + +#import +#import + +// Forward declaration of the primary function implemented in this file +OSStatus SecCopySharedWebCredentialSyncUsingAuthSvcs(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, CFErrorRef *error); + +// Classes we will load dynamically +static Class kASAuthorizationClass = NULL; +static Class kASAuthorizationControllerClass = NULL; +static Class kASAuthorizationPasswordProviderClass = NULL; +static Class kASPasswordCredentialClass = NULL; +static Class kUIApplicationClass = NULL; +static Class kNSApplicationClass = NULL; + +static void loadAuthenticationServices(void) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + const char *path = "/System/Library/Frameworks/AuthenticationServices.framework/AuthenticationServices"; + if ( [NSProcessInfo processInfo].macCatalystApp == YES ) { + path = "/System/iOSSupport/System/Library/Frameworks/AuthenticationServices.framework/AuthenticationServices"; + } + void* lib_handle = dlopen(path, RTLD_LAZY); + if (lib_handle != NULL) { + kASAuthorizationClass = NSClassFromString(@"ASAuthorization"); + kASAuthorizationControllerClass = NSClassFromString(@"ASAuthorizationController"); + kASAuthorizationPasswordProviderClass = NSClassFromString(@"ASAuthorizationPasswordProvider"); + kASPasswordCredentialClass = NSClassFromString(@"ASPasswordCredential"); + } + }); +} + +static void loadUIKit(void) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + const char *path = "/System/Library/Frameworks/UIKit.framework/UIKit"; + if ( [NSProcessInfo processInfo].macCatalystApp == YES ) { + path = "/System/Library/iOSSupport/System/Library/Frameworks/UIKit.framework/UIKit"; + } + void* lib_handle = dlopen(path, RTLD_LAZY); + if (lib_handle != NULL) { + kUIApplicationClass = NSClassFromString(@"UIApplication"); + } + }); +} + +static void loadAppKit(void) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + const char *path = "/System/Library/Frameworks/AppKit.framework/AppKit"; + void* lib_handle = dlopen(path, RTLD_LAZY); + if (lib_handle != NULL) { + kNSApplicationClass = NSClassFromString(@"NSApplication"); + } + }); +} + +static Class ASAuthorizationClass() { + loadAuthenticationServices(); + return kASAuthorizationClass; +} + +static Class ASAuthorizationControllerClass() { + loadAuthenticationServices(); + return kASAuthorizationControllerClass; +} + +static Class ASAuthorizationPasswordProviderClass() { + loadAuthenticationServices(); + return kASAuthorizationPasswordProviderClass; +} + +static Class ASPasswordCredentialClass() { + loadAuthenticationServices(); + return kASPasswordCredentialClass; +} + +static Class UIApplicationClass() { + loadUIKit(); + return kUIApplicationClass; +} + +static Class NSApplicationClass() { + loadAppKit(); + return kNSApplicationClass; +} + +@interface SharedCredentialController : NSObject + + +-(ASPasswordCredential *)passwordCredential; + +@end + +@implementation SharedCredentialController { + ASAuthorizationPasswordProvider *_provider; + ASAuthorizationController *_controller; + ASPasswordCredential *_passwordCredential; + dispatch_semaphore_t _semaphore; + NSError *_error; + OSStatus _result; +} + +- (void)dealloc { + // Don't want any further callbacks since we are going away + _controller.delegate = nil; + _controller.presentationContextProvider = nil; +} + +- (void)_requestCredential { + if (!_provider) { + _provider = [[ASAuthorizationPasswordProviderClass() alloc] init]; + } + if (!_controller) { + _controller = [[ASAuthorizationControllerClass() alloc] initWithAuthorizationRequests:@[ [_provider createRequest] ]]; + } + _controller.delegate = self; + _controller.presentationContextProvider = self; + _semaphore = dispatch_semaphore_create(0); + _result = errSecItemNotFound; + _error = nil; + + [_controller performRequests]; +} + +- (ASPasswordCredential *)passwordCredential { + if (_passwordCredential) { + return _passwordCredential; + } + BOOL shouldRequest = YES; // ( [NSProcessInfo processInfo].macCatalystApp == YES ); + if (shouldRequest) { + [self _requestCredential]; + // wait synchronously until user picks a credential or cancels + dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER); + } else { + // unable to return a shared credential: + _result = errSecItemNotFound; + _error = [[NSError alloc] initWithDomain:NSOSStatusErrorDomain code:_result userInfo:NULL]; + } + return _passwordCredential; +} + +- (NSError *)error { + return _error; +} + +- (OSStatus)result { + return _result; +} + +- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization { + secinfo("swcagent", "SWC received didCompleteWithAuthorization"); + ASPasswordCredential *passwordCredential = authorization.credential; + if (![passwordCredential isKindOfClass:[ASPasswordCredentialClass() class]]) { + _passwordCredential = nil; + _result = errSecItemNotFound; + } else { + _passwordCredential = passwordCredential; + _result = errSecSuccess; + } + dispatch_semaphore_signal(_semaphore); +} + +- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error { + secinfo("swcagent", "SWC received didCompleteWithError"); + _passwordCredential = nil; + _error = error; + _result = errSecItemNotFound; + dispatch_semaphore_signal(_semaphore); +} + +- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller +{ + ASPresentationAnchor anchorWindow = nil; +#if TARGET_OS_OSX + if ( [NSProcessInfo processInfo].macCatalystApp == NO ) { + anchorWindow = [[NSApplicationClass() sharedApplication] keyWindow]; + } +#endif + if (!anchorWindow) { + anchorWindow = [[UIApplicationClass() sharedApplication] keyWindow]; + } + return anchorWindow; +} + +@end + +OSStatus SecCopySharedWebCredentialSyncUsingAuthSvcs(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, CFErrorRef *error) { + SharedCredentialController *controller = [[SharedCredentialController alloc] init]; + ASPasswordCredential *passwordCredential = [controller passwordCredential]; + OSStatus status = [controller result]; + NSArray *returnedCredentials = @[]; + if (status != errSecSuccess) { + secinfo("swcagent", "SecCopySharedWebCredentialSyncUsingAuthSvcs received result %d", (int)status); + if (error) { + *error = (CFErrorRef)CFBridgingRetain([controller error]); + } + } else if (passwordCredential) { + // Use the .user and .password of the passwordCredential to satisfy the SWC interface. + NSDictionary *credential = @{ + (id)kSecAttrServer : (__bridge NSString*)fqdn, + (id)kSecAttrAccount : passwordCredential.user, + (id)kSecSharedPassword : passwordCredential.password, + }; + returnedCredentials = @[ credential ]; + } else { + secinfo("swcagent", "SecCopySharedWebCredentialSyncUsingAuthSvcs found no credential"); + status = errSecItemNotFound; + } + if (credentials) { + *credentials = (CFArrayRef)CFBridgingRetain(returnedCredentials); + } + return status; +} diff --git a/OSX/sec/Security/SecTrust.c b/OSX/sec/Security/SecTrust.c index d64de6dd..ba6a8f66 100644 --- a/OSX/sec/Security/SecTrust.c +++ b/OSX/sec/Security/SecTrust.c @@ -1834,15 +1834,7 @@ CFStringRef SecTrustCopyFailureDescription(SecTrustRef trust) { return reason; } -#if TARGET_OS_OSX -/* On OS X we need SecTrustCopyPublicKey to give us a CDSA-based SecKeyRef, - so we will refer to this one internally as SecTrustCopyPublicKey_ios, - and call it from SecTrustCopyPublicKey. - */ -SecKeyRef SecTrustCopyPublicKey_ios(SecTrustRef trust) -#else -SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) -#endif +SecKeyRef SecTrustCopyKey(SecTrustRef trust) { if (!trust) { return NULL; @@ -1870,7 +1862,20 @@ SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) } }); } - return publicKey; + return publicKey; +} + +#if TARGET_OS_OSX +/* On OS X we need SecTrustCopyPublicKey to give us a CDSA-based SecKeyRef, + so we will refer to this one internally as SecTrustCopyPublicKey_ios, + and call it from SecTrustCopyPublicKey. + */ +SecKeyRef SecTrustCopyPublicKey_ios(SecTrustRef trust) +#else +SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) +#endif +{ + return SecTrustCopyKey(trust); } CFIndex SecTrustGetCertificateCount(SecTrustRef trust) { @@ -2222,7 +2227,6 @@ static void applyDetailProperty(const void *_key, const void *_value, } else if (CFEqual(key, kSecPolicyCheckCriticalExtensions)) { tf->unknownCritExtn = true; } else if (CFEqual(key, kSecPolicyCheckAnchorTrusted) - || CFEqual(key, kSecPolicyCheckAnchorSHA1) || CFEqual(key, kSecPolicyCheckAnchorSHA256) || CFEqual(key, kSecPolicyCheckAnchorApple)) { tf->untrustedAnchor = true; @@ -2576,6 +2580,18 @@ CFDictionaryRef SecTrustOTASecExperimentCopyAsset(CFErrorRef *error) { return result; } +bool SecTrustTriggerValidUpdate(CFErrorRef *error) { + do_if_registered(sec_valid_update, error); + + os_activity_t activity = os_activity_create("SecTrustTriggerValidUpdate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_scope(activity); + + uint64_t num = do_ota_pki_op(kSecXPCOpValidUpdate, error); + + os_release(activity); + return num; +} + bool SecTrustReportTLSAnalytics(CFStringRef eventName, xpc_object_t eventAttributes, CFErrorRef *error) { if (!eventName || !eventAttributes) { return false; diff --git a/OSX/sec/Security/SecTrustInternal.h b/OSX/sec/Security/SecTrustInternal.h index 4921bdd9..8d11e5fc 100644 --- a/OSX/sec/Security/SecTrustInternal.h +++ b/OSX/sec/Security/SecTrustInternal.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2015-2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2015-2020 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, @@ -17,7 +17,7 @@ * 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@ */ @@ -44,6 +44,7 @@ __BEGIN_DECLS #define kSecTrustTrustedLogsKey "trustedLogs" #define kSecTrustVerifyDateKey "verifyDate" #define kSecTrustExceptionsKey "exceptions" +#define kSecTrustRevocationAdditionsKey "revocationCheck" /* args_out keys. */ #define kSecTrustDetailsKey "details" diff --git a/OSX/sec/Security/SecTrustStore.c b/OSX/sec/Security/SecTrustStore.c index 32f84c3b..c6a51c86 100644 --- a/OSX/sec/Security/SecTrustStore.c +++ b/OSX/sec/Security/SecTrustStore.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2007-2018 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2007-2020 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, @@ -17,11 +17,11 @@ * 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@ */ -/* +/* * SecTrustStore.c - CertificateSource API to a system root certificate store */ #include @@ -95,12 +95,12 @@ Boolean SecTrustStoreContains(SecTrustStoreRef ts, require(ts, errOut); require(digest = SecCertificateGetSHA1Digest(certificate), errOut); - + ok = (SecOSStatusWith(^bool (CFErrorRef *error) { return TRUSTD_XPC(sec_trust_store_contains, string_data_to_bool_bool_error, ts, digest, &contains, error); }) == errSecSuccess); - + errOut: return ok && contains; } @@ -206,7 +206,7 @@ OSStatus SecTrustStoreSetTrustSettings(SecTrustStoreRef ts, Boolean isSelfSigned = false; require_noerr_quiet(result = SecCertificateIsSelfSigned(certificate, &isSelfSigned), out); require_noerr_quiet(result = validateTrustSettings(isSelfSigned, trustSettingsDictOrArray, &validatedTrustSettings), out); - + os_activity_initiate("SecTrustStoreSetTrustSettings", OS_ACTIVITY_FLAG_DEFAULT, ^{ result = SecOSStatusWith(^bool (CFErrorRef *error) { return TRUSTD_XPC(sec_trust_store_set_trust_settings, string_cert_cftype_to_error, ts, certificate, validatedTrustSettings, error); @@ -229,7 +229,7 @@ OSStatus SecTrustStoreRemoveCertificate(SecTrustStoreRef ts, require(ts, errOut); require(digest = SecCertificateGetSHA1Digest(certificate), errOut); require(gTrustd || ts == (SecTrustStoreRef)kSecTrustStoreUserName, errOut); - + status = SecOSStatusWith(^bool (CFErrorRef *error) { return TRUSTD_XPC(sec_trust_store_remove_certificate, string_data_to_bool_error, ts, digest, error); }); @@ -262,12 +262,12 @@ OSStatus SecTrustStoreGetSettingsAssetVersionNumber(SecTrustSettingsAssetVersion if (NULL == p_settings_asset_version_number) { return errSecParam; } - + OSStatus status = errSecSuccess; CFErrorRef error = nil; uint64_t versionNumber = SecTrustGetAssetVersionNumber(&error); *p_settings_asset_version_number = (SecTrustSettingsAssetVersionNumber)versionNumber; - + if (error) { status = (OSStatus)CFErrorGetCode(error); } @@ -404,3 +404,73 @@ CFDictionaryRef SecTrustStoreCopyCTExceptions(CFStringRef applicationIdentifier, return NULL; #endif // TARGET_OS_BRIDGE } + +/* MARK: CA Revocation Additions */ + +/* Specify explicit additions to the list of known CAs for which revocation will be checked. + * Input: dictionary with following key and value: + * Key = kSecCARevocationAdditionsKey; Value = Array of dictionaries + * For revocation checking to be enabled for certificates issued by a CA, the CA must be specified as a + * dictionary entry containing the hash of the subjectPublicKeyInfo that appears in the CA certificate: + * Key = kSecCARevocationHashAlgorithmKey; Value = String. Currently, must be ”sha256”. + * Key = kSecCARevocationSPKIHashKey; Value = Data. Created by applying the specified hash algorithm + * to the DER encoding of the certificate's subjectPublicKeyInfo. +*/ + +const CFStringRef kSecCARevocationAdditionsKey = CFSTR("EnabledForCAs"); +const CFStringRef kSecCARevocationHashAlgorithmKey = CFSTR("HashAlgorithm"); +const CFStringRef kSecCARevocationSPKIHashKey = CFSTR("SubjectPublicKeyInfoHash"); + +bool SecTrustStoreSetCARevocationAdditions(CFStringRef applicationIdentifier, CFDictionaryRef additions, CFErrorRef *error) { +#if !TARGET_OS_BRIDGE + if (applicationIdentifier && gTrustd && gTrustd->sec_trust_store_set_ca_revocation_additions) { + return gTrustd->sec_trust_store_set_ca_revocation_additions(applicationIdentifier, additions, error); + } else if (gTrustd && gTrustd->sec_trust_store_set_ca_revocation_additions) { + /* When calling from the TrustTests, we need to pass the appID for the tests. Ordinarily, + * this is done by trustd using the client's entitlements. */ + return gTrustd->sec_trust_store_set_ca_revocation_additions(CFSTR("com.apple.trusttests"), additions, error); + } + + os_activity_t activity = os_activity_create("SecTrustStoreSetCARevocationAdditions", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_scope(activity); + + __block bool result = false; + securityd_send_sync_and_do(kSecXPCOpSetCARevocationAdditions, error, ^bool(xpc_object_t message, CFErrorRef *block_error) { + SecXPCDictionarySetPListOptional(message, kSecTrustRevocationAdditionsKey, additions, block_error); + SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error); + return true; + }, ^bool(xpc_object_t response, CFErrorRef *block_error) { + result = SecXPCDictionaryGetBool(response, kSecXPCKeyResult, block_error); + return true; + }); + + os_release(activity); + return result; +#else // TARGET_OS_BRIDGE + return SecError(errSecReadOnly, error, CFSTR("SecTrustStoreSetCARevocationAdditions not supported on bridgeOS")); +#endif // TARGET_OS_BRIDGE +} + +CFDictionaryRef SecTrustStoreCopyCARevocationAdditions(CFStringRef applicationIdentifier, CFErrorRef *error) { +#if !TARGET_OS_BRIDGE + do_if_registered(sec_trust_store_copy_ca_revocation_additions, applicationIdentifier, error); + + os_activity_t activity = os_activity_create("SecTrustStoreCopyCARevocationAdditions", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); + os_activity_scope(activity); + + __block CFDictionaryRef result = NULL; + securityd_send_sync_and_do(kSecXPCOpCopyCARevocationAdditions, error, ^bool(xpc_object_t message, CFErrorRef *block_error) { + SecXPCDictionarySetStringOptional(message, kSecTrustEventApplicationID, applicationIdentifier, block_error); + return true; + }, ^bool(xpc_object_t response, CFErrorRef *block_error) { + (void)SecXPCDictionaryCopyDictionaryOptional(response, kSecTrustRevocationAdditionsKey, &result, block_error); + return true; + }); + + os_release(activity); + return result; +#else // TARGET_OS_BRIDGE + SecError(errSecReadOnly, error, CFSTR("SecTrustStoreCopyCARevocationAdditions not supported on bridgeOS")); + return NULL; +#endif // TARGET_OS_BRIDGE +} diff --git a/OSX/sec/Security/SecuritydXPC.c b/OSX/sec/Security/SecuritydXPC.c index 698ae145..08576003 100644 --- a/OSX/sec/Security/SecuritydXPC.c +++ b/OSX/sec/Security/SecuritydXPC.c @@ -143,24 +143,14 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("RejectApplicants"); case kSecXPCOpRemoveThisDeviceFromCircle: return CFSTR("RemoveThisDeviceFromCircle"); - case kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics: - return CFSTR("RemoveThisDeviceFromCircleWithAnalytics"); case kSecXPCOpRemovePeersFromCircle: return CFSTR("RemovePeersFromCircle"); - case kSecXPCOpRemovePeersFromCircleWithAnalytics: - return CFSTR("RemovePeersFromCircleWithAnalytics"); case kSecXPCOpRequestToJoin: return CFSTR("RequestToJoin"); - case kSecXPCOpRequestToJoinWithAnalytics: - return CFSTR("RequestToJoinWithAnalytics"); case kSecXPCOpRequestToJoinAfterRestore: return CFSTR("RequestToJoinAfterRestore"); - case kSecXPCOpRequestToJoinAfterRestoreWithAnalytics: - return CFSTR("RequestToJoinAfterRestoreWithAnalytics"); case kSecXPCOpResetToEmpty: return CFSTR("ResetToEmpty"); - case kSecXPCOpResetToEmptyWithAnalytics: - return CFSTR("ResetToEmptyWithAnalytics"); case kSecXPCOpResetToOffering: return CFSTR("ResetToOffering"); case kSecXPCOpRollKeys: @@ -175,8 +165,6 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("SetUserCredentials"); case kSecXPCOpSetUserCredentialsAndDSID: return CFSTR("SetUserCredentialsAndDSID"); - case kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics: - return CFSTR("SetUserCredentialsAndDSIDWithAnalytics"); case kSecXPCOpTryUserCredentials: return CFSTR("TryUserCredentials"); case kSecXPCOpValidateUserPublic: @@ -195,6 +183,8 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("add"); case sec_item_backup_copy_names_id: return CFSTR("backup_copy_names"); + case sec_item_backup_ensure_copy_view_id: + return CFSTR("backup_register_view"); case sec_item_backup_handoff_fd_id: return CFSTR("backup_handoff_fd"); case sec_item_backup_restore_id: @@ -249,7 +239,7 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("WhoAmI"); case kSecXPCOpTransmogrifyToSyncBubble: return CFSTR("TransmogrifyToSyncBubble"); - case sec_item_update_token_items_id: + case sec_item_update_token_items_for_access_groups_id: return CFSTR("UpdateTokenItems"); case sec_delete_items_with_access_groups_id: return CFSTR("sec_delete_items_with_access_groups_id"); @@ -283,22 +273,34 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("GetExceptionResetCount"); case sec_trust_increment_exception_reset_count_id: return CFSTR("IncrementExceptionResetCount"); + case kSecXPCOpSetCARevocationAdditions: + return CFSTR("SetCARevocationAdditions"); + case kSecXPCOpCopyCARevocationAdditions: + return CFSTR("CopyCARevocationAdditions"); + case kSecXPCOpValidUpdate: + return CFSTR("ValidUpdate"); default: return CFSTR("Unknown xpc operation"); } } bool SecXPCDictionarySetPList(xpc_object_t message, const char *key, CFTypeRef object, CFErrorRef *error) +{ + return SecXPCDictionarySetPListWithRepair(message, key, object, false, error); +} + +bool SecXPCDictionarySetPListWithRepair(xpc_object_t message, const char *key, CFTypeRef object, bool repair, CFErrorRef *error) { if (!object) return SecError(errSecParam, error, CFSTR("object for key %s is NULL"), key); size_t size = der_sizeof_plist(object, error); - if (!size) + if (!size) { return false; + } uint8_t *der = malloc(size); uint8_t *der_end = der + size; - uint8_t *der_start = der_encode_plist(object, error, der, der_end); + uint8_t *der_start = der_encode_plist_repair(object, error, repair, der, der_end); if (!der_start) { free(der); return false; @@ -492,10 +494,16 @@ CFTypeRef SecXPCDictionaryCopyPList(xpc_object_t message, const char *key, CFErr const uint8_t *der_end = der + size; /* use the sensitive allocator so that the dictionary is zeroized upon deallocation */ - const uint8_t *decode_end = der_decode_plist(SecCFAllocatorZeroize(), kCFPropertyListImmutable, + const uint8_t *decode_end = der_decode_plist(SecCFAllocatorZeroize(), &cfobject, error, der, der_end); if (decode_end != der_end) { - SecError(errSecParam, error, CFSTR("trailing garbage after der decoded object for key %s"), key); + CFStringRef description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("trailing garbage after der decoded object for key %s"), key); + SecError(errSecParam, error, CFSTR("%@"), description); + if (error) { // The no-error case is handled in SecError directly + secerror("xpc: %@", *error); + } + __security_simulatecrash(description, __sec_exception_code_CorruptItem); + CFReleaseNull(description); CFReleaseNull(cfobject); } diff --git a/OSX/sec/Security/SecuritydXPC.h b/OSX/sec/Security/SecuritydXPC.h index da93c9fa..92d6df73 100644 --- a/OSX/sec/Security/SecuritydXPC.h +++ b/OSX/sec/Security/SecuritydXPC.h @@ -35,6 +35,7 @@ bool SecXPCDictionarySetDataOptional(xpc_object_t message, const char *key, CFDa bool SecXPCDictionarySetBool(xpc_object_t message, const char *key, bool value, CFErrorRef *error); bool SecXPCDictionarySetPList(xpc_object_t message, const char *key, CFTypeRef object, CFErrorRef *error); +bool SecXPCDictionarySetPListWithRepair(xpc_object_t message, const char *key, CFTypeRef object, bool repair, CFErrorRef *error); bool SecXPCDictionarySetPListOptional(xpc_object_t message, const char *key, CFTypeRef object, CFErrorRef *error); bool SecXPCDictionarySetString(xpc_object_t message, const char *key, CFStringRef string, CFErrorRef *error); diff --git a/OSX/sec/Security/ios_tapi_hacks.h b/OSX/sec/Security/ios_tapi_hacks.h index 92e3c930..e068beeb 100644 --- a/OSX/sec/Security/ios_tapi_hacks.h +++ b/OSX/sec/Security/ios_tapi_hacks.h @@ -76,6 +76,9 @@ bool securityd_message_no_error(xpc_object_t message, CFErrorRef *error); void SecAccessGroupsSetCurrent(CFArrayRef accessGroups); CFArrayRef SecAccessGroupsGetCurrent(void); +void SecSecurityClientRegularToAppClip(void); +void SecSecurityClientAppClipToRegular(void); +void SecSecurityClientSetApplicationIdentifier(CFStringRef identifier); #include extern os_log_t secLogObjForScope(const char *scope); diff --git a/OSX/sec/Security/p12pbegen.c b/OSX/sec/Security/p12pbegen.c index 17abc062..3f33e888 100644 --- a/OSX/sec/Security/p12pbegen.c +++ b/OSX/sec/Security/p12pbegen.c @@ -31,6 +31,8 @@ #include "p12pbegen.h" +#include + static uint8_t *concatenate_to_blocksize(const uint8_t *data, size_t data_length, size_t blocksize, size_t *blocklength) { diff --git a/OSX/sec/SharedWebCredential/swcagent.m b/OSX/sec/SharedWebCredential/swcagent.m index 6c873d22..bdf13306 100644 --- a/OSX/sec/SharedWebCredential/swcagent.m +++ b/OSX/sec/SharedWebCredential/swcagent.m @@ -47,7 +47,7 @@ #include #endif -#if TARGET_OS_IPHONE && !TARGET_OS_WATCH +#if TARGET_OS_IPHONE && !TARGET_OS_WATCH && !TARGET_OS_TV #include #include @@ -85,7 +85,7 @@ typedef WBSAutoFillDataClasses (*WBUAutoFillGetEnabledDataClasses_f)(void); #import #import #import -#import +#import #endif static NSString *swca_string_table = @"SharedWebCredentials"; diff --git a/OSX/sec/ipc/client.c b/OSX/sec/ipc/client.c index 5dd78112..274a8767 100644 --- a/OSX/sec/ipc/client.c +++ b/OSX/sec/ipc/client.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2009,2012-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,2012-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -69,27 +70,33 @@ struct trustd *gTrustd; /* Hardcoded Access Groups for the server itself */ static CFArrayRef SecServerCopyAccessGroups(void) { - return CFArrayCreateForCFTypes(kCFAllocatorDefault, + CFArrayRef accessGroups = CFArrayCreateForCFTypes(kCFAllocatorDefault, #if NO_SERVER - CFSTR("test"), - CFSTR("apple"), - CFSTR("lockdown-identities"), - CFSTR("123456.test.group"), - CFSTR("123456.test.group2"), - CFSTR("com.apple.cfnetwork"), - CFSTR("com.apple.bluetooth"), + CFSTR("test"), + CFSTR("apple"), + CFSTR("lockdown-identities"), + CFSTR("123456.test.group"), + CFSTR("123456.test.group2"), + CFSTR("com.apple.cfnetwork"), + CFSTR("com.apple.bluetooth"), #endif - CFSTR("sync"), - CFSTR("com.apple.security.sos"), - CFSTR("com.apple.security.ckks"), - CFSTR("com.apple.security.octagon"), - CFSTR("com.apple.security.egoIdentities"), - CFSTR("com.apple.security.sos-usercredential"), - CFSTR("com.apple.sbd"), - CFSTR("com.apple.lakitu"), - CFSTR("com.apple.security.securityd"), - kSecAttrAccessGroupToken, - NULL); + CFSTR("sync"), + CFSTR("com.apple.security.sos"), + CFSTR("com.apple.security.ckks"), + CFSTR("com.apple.security.octagon"), + CFSTR("com.apple.security.egoIdentities"), + CFSTR("com.apple.security.sos-usercredential"), + CFSTR("com.apple.sbd"), + CFSTR("com.apple.lakitu"), + CFSTR("com.apple.security.securityd"), + NULL); + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + CFMutableArrayRef mutableGroups = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, accessGroups); + CFArrayAppendValue(mutableGroups, kSecAttrAccessGroupToken); + CFAssignRetained(accessGroups, mutableGroups); + } + + return accessGroups; } static SecurityClient gClient; @@ -137,6 +144,8 @@ SecSecurityClientGet(void) gClient.activeUser = 501; gClient.musr = NULL; #endif + gClient.applicationIdentifier = NULL; + gClient.isAppClip = false; }); return &gClient; } @@ -150,8 +159,30 @@ CFArrayRef SecAccessGroupsGetCurrent(void) { // Only for testing. void SecAccessGroupsSetCurrent(CFArrayRef accessGroups) { // Not thread safe at all, but OK because it is meant to be used only by tests. - CFReleaseNull(gClient.accessGroups); - gClient.accessGroups = CFRetainSafe(accessGroups); + SecurityClient* client = SecSecurityClientGet(); + CFReleaseNull(client->accessGroups); + client->accessGroups = CFRetainSafe(accessGroups); +} + +// Testing +void SecSecurityClientRegularToAppClip(void) { + SecurityClient* client = SecSecurityClientGet(); + client->isAppClip = true; +} + +// Testing +void SecSecurityClientAppClipToRegular(void) { + SecurityClient* client = SecSecurityClientGet(); + client->isAppClip = false; +} + +// Testing +void SecSecurityClientSetApplicationIdentifier(CFStringRef identifier) { + SecurityClient* client = SecSecurityClientGet(); + CFReleaseNull(client->applicationIdentifier); + if (identifier) { + client->applicationIdentifier = CFRetain(identifier); + } } #if !TARGET_OS_IPHONE @@ -227,6 +258,9 @@ static bool is_trust_operation(enum SecXPCOperation op) { case kSecXPCOpCopyCTExceptions: case sec_trust_get_exception_reset_count_id: case sec_trust_increment_exception_reset_count_id: + case kSecXPCOpSetCARevocationAdditions: + case kSecXPCOpCopyCARevocationAdditions: + case kSecXPCOpValidUpdate: return true; default: break; diff --git a/OSX/sec/ipc/client_endpoint.m b/OSX/sec/ipc/client_endpoint.m index b9957cc7..e9d8975c 100644 --- a/OSX/sec/ipc/client_endpoint.m +++ b/OSX/sec/ipc/client_endpoint.m @@ -26,6 +26,7 @@ #import #import #import +#import #include @@ -59,37 +60,7 @@ ofReply:0]; #if OCTAGON - static NSMutableSet *errClasses; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - // By finding classes by strings at runtime, we'll only get the CloudKit helpers if you link CloudKit - // Plus, we don't have to weak-link cloudkit from Security.framework - - errClasses = [[NSMutableSet alloc] init]; - char *classes[] = { - "NSError", - "NSArray", - "NSString", - "NSNumber", - "NSData", - "NSDate", - "CKReference", - "CKAsset", - "CLLocation", - "CKPackage", - "CKArchivedAnchoredPackage", - "CKPrettyError", - "CKRecordID", - "NSURL", - }; - - for (unsigned n = 0; n < sizeof(classes)/sizeof(classes[0]); n++) { - Class cls = objc_getClass(classes[n]); - if (cls) { - [errClasses addObject:cls]; - } - } - }); + NSSet *errClasses = [SecXPCHelper safeErrorClasses]; @try { [rpcCallbackInterface setClasses:errClasses forSelector:@selector(callCallback:error:) argumentIndex:1 ofReply:NO]; @@ -97,14 +68,6 @@ [interface setClasses:errClasses forSelector:@selector(SecItemAddAndNotifyOnSync: syncCallback: complete:) argumentIndex:2 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(secItemFetchCurrentItemAcrossAllDevices: - identifier: - viewHint: - fetchCloudValue: - complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(secItemDigest: - accessGroup: - complete:) argumentIndex:1 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(secItemSetCurrentItemAcrossAllDevices: newCurrentItemHash: accessGroup: @@ -113,12 +76,21 @@ oldCurrentItemReference: oldCurrentItemHash: complete:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(secItemFetchCurrentItemAcrossAllDevices: + identifier: + viewHint: + fetchCloudValue: + complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(secItemDigest: + accessGroup: + complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(secKeychainDeleteMultiuser:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(secItemVerifyBackupIntegrity:completion:) argumentIndex:1 ofReply:YES]; + } @catch(NSException* e) { secerror("Could not configure SecuritydXPCProtocol: %@", e); -#if DEBUG @throw e; -#endif // DEBUG } #endif // OCTAGON } @@ -139,7 +111,7 @@ } @end -id SecuritydXPCProxyObject(void (^rpcErrorHandler)(NSError *)) +id SecuritydXPCProxyObject(bool synchronous, void (^rpcErrorHandler)(NSError *)) { if (gSecurityd && gSecurityd->secd_xpc_server) { return (__bridge id)gSecurityd->secd_xpc_server; @@ -156,7 +128,11 @@ id SecuritydXPCProxyObject(void (^rpcErrorHandler)(NSError rpcErrorHandler([NSError errorWithDomain:@"securityd" code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Could not create SecuritydXPCClient" }]); return NULL; } else { - return [rpc.connection remoteObjectProxyWithErrorHandler: rpcErrorHandler]; + if (synchronous) { + return [rpc.connection synchronousRemoteObjectProxyWithErrorHandler:rpcErrorHandler]; + } else { + return [rpc.connection remoteObjectProxyWithErrorHandler:rpcErrorHandler]; + } } } diff --git a/OSX/sec/ipc/com.apple.secd.plist b/OSX/sec/ipc/com.apple.secd.plist index 59392e17..f9484f12 100644 --- a/OSX/sec/ipc/com.apple.secd.plist +++ b/OSX/sec/ipc/com.apple.secd.plist @@ -55,6 +55,15 @@ Interval 86400 + com.apple.securityd.prng + + Priority + Maintenance + Interval + 3600 + RequiresClassC + + diff --git a/OSX/sec/ipc/com.apple.securityd.plist b/OSX/sec/ipc/com.apple.securityd.plist index e75b5e1b..6be938f5 100644 --- a/OSX/sec/ipc/com.apple.securityd.plist +++ b/OSX/sec/ipc/com.apple.securityd.plist @@ -67,6 +67,15 @@ NetworkTransferDirection Bidirectional + com.apple.securityd.prng + + Priority + Maintenance + Interval + 3600 + RequiresClassC + + com.apple.notifyd.matching diff --git a/OSX/sec/ipc/securityd_client.h b/OSX/sec/ipc/securityd_client.h index ed945f01..289b0ff1 100644 --- a/OSX/sec/ipc/securityd_client.h +++ b/OSX/sec/ipc/securityd_client.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -182,6 +182,7 @@ enum SecXPCOperation { sec_keychain_backup_syncable_id, sec_keychain_restore_syncable_id, sec_item_backup_copy_names_id, + sec_item_backup_ensure_copy_view_id, sec_item_backup_handoff_fd_id, sec_item_backup_set_confirmed_manifest_id, sec_item_backup_restore_id, @@ -216,24 +217,18 @@ enum SecXPCOperation { kSecXPCOpTryUserCredentials, kSecXPCOpSetUserCredentials, kSecXPCOpSetUserCredentialsAndDSID, - kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics, kSecXPCOpCanAuthenticate, kSecXPCOpPurgeUserCredentials, kSecXPCOpDeviceInCircle, kSecXPCOpRequestToJoin, - kSecXPCOpRequestToJoinWithAnalytics, kSecXPCOpRequestToJoinAfterRestore, - kSecXPCOpRequestToJoinAfterRestoreWithAnalytics, kSecXPCOpResetToOffering, kSecXPCOpResetToEmpty, - kSecXPCOpResetToEmptyWithAnalytics, kSecXPCOpView, kSecXPCOpViewSet, - kSecXPCOpViewSetWithAnalytics, kSecXPCOpRemoveThisDeviceFromCircle, - kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics, kSecXPCOpRemovePeersFromCircle, - kSecXPCOpRemovePeersFromCircleWithAnalytics, + kSecXPCOpLoggedIntoAccount, kSecXPCOpLoggedOutOfAccount, kSecXPCOpBailFromCircle, kSecXPCOpAcceptApplicants, @@ -255,7 +250,6 @@ enum SecXPCOperation { kSecXPCOpSetNewPublicBackupKey, kSecXPCOpSetBagForAllSlices, kSecXPCOpWaitForInitialSync, - kSecXPCOpWaitForInitialSyncWithAnalytics, kSecXPCOpCheckPeerAvailability, kSecXPCOpCopyApplication, kSecXPCOpCopyCircleJoiningBlob, @@ -270,7 +264,7 @@ enum SecXPCOperation { kSecXPCOpWhoAmI, kSecXPCOpTransmogrifyToSyncBubble, kSecXPCOpTransmogrifyToSystemKeychain, - sec_item_update_token_items_id, + sec_item_update_token_items_for_access_groups_id, kSecXPCOpDeleteUserView, sec_trust_store_copy_all_id, sec_trust_store_copy_usage_constraints_id, @@ -294,6 +288,9 @@ enum SecXPCOperation { kSecXPCOpOTASecExperimentGetNewAsset, sec_trust_get_exception_reset_count_id, sec_trust_increment_exception_reset_count_id, + kSecXPCOpSetCARevocationAdditions, + kSecXPCOpCopyCARevocationAdditions, + kSecXPCOpValidUpdate, }; @@ -313,6 +310,8 @@ typedef struct SecurityClient { bool inMultiUser; int activeUser; #endif + bool isAppClip; + CFStringRef applicationIdentifier; } SecurityClient; @@ -334,7 +333,7 @@ struct securityd { CFDataRef (*sec_keychain_backup)(SecurityClient *client, CFDataRef keybag, CFDataRef passcode, bool emcs, CFErrorRef* error); bool (*sec_keychain_restore)(CFDataRef backup, SecurityClient *client, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); bool (*sec_roll_keys)(bool force, CFErrorRef* error); - bool (*sec_item_update_token_items)(CFStringRef tokenID, CFArrayRef query, SecurityClient *client, CFErrorRef* error); + bool (*sec_item_update_token_items_for_access_groups)(CFStringRef tokenID, CFArrayRef accessGroups, CFArrayRef tokenItems, SecurityClient *client, CFErrorRef* error); bool (*sec_delete_items_with_access_groups)(CFArrayRef bundleIDs, SecurityClient *client, CFErrorRef *error); /* SHAREDWEBCREDENTIALS */ bool (*sec_add_shared_web_credential)(CFDictionaryRef attributes, SecurityClient *client, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); @@ -343,6 +342,7 @@ struct securityd { CFDictionaryRef (*sec_keychain_backup_syncable)(CFDictionaryRef backup_in, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); bool (*sec_keychain_restore_syncable)(CFDictionaryRef backup, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); CFArrayRef (*sec_item_backup_copy_names)(CFErrorRef *error); + CFStringRef (*sec_item_backup_ensure_copy_view)(CFStringRef viewName, CFErrorRef *error); int (*sec_item_backup_handoff_fd)(CFStringRef backupName, CFErrorRef *error); bool (*sec_item_backup_set_confirmed_manifest)(CFStringRef backupName, CFDataRef keybagDigest, CFDataRef manifest, CFErrorRef *error); bool (*sec_item_backup_restore)(CFStringRef backupName, CFStringRef peerID, CFDataRef keybag, CFDataRef secret, CFDataRef backup, CFErrorRef *error); @@ -351,28 +351,22 @@ struct securityd { bool (*soscc_TryUserCredentials)(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error); bool (*soscc_SetUserCredentials)(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); bool (*soscc_SetUserCredentialsAndDSID)(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error); - bool (*soscc_SetUserCredentialsAndDSIDWithAnalytics)(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error); bool (*soscc_CanAuthenticate)(CFErrorRef *error); bool (*soscc_PurgeUserCredentials)(CFErrorRef *error); SOSCCStatus (*soscc_ThisDeviceIsInCircle)(CFErrorRef* error); bool (*soscc_RequestToJoinCircle)(CFErrorRef* error); - bool (*soscc_RequestToJoinCircleWithAnalytics)(CFDataRef parentEvent, CFErrorRef* error); bool (*soscc_RequestToJoinCircleAfterRestore)(CFErrorRef* error); - bool (*soscc_RequestToJoinCircleAfterRestoreWithAnalytics)(CFDataRef parentEvent, CFErrorRef* error); bool (*soscc_SetToNew)(CFErrorRef *error); bool (*soscc_ResetToOffering)(CFErrorRef* error); bool (*soscc_ResetToEmpty)(CFErrorRef* error); - bool (*soscc_ResetToEmptyWithAnalytics)(CFDataRef parentEvent, CFErrorRef* error); SOSViewResultCode (*soscc_View)(CFStringRef view, SOSViewActionCode action, CFErrorRef *error); bool (*soscc_ViewSet)(CFSetRef enabledViews, CFSetRef disabledViews); - bool (*soscc_ViewSetWithAnalytics)(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent); bool (*soscc_RegisterSingleRecoverySecret)(CFDataRef backupSlice, bool forV0Only, CFErrorRef *error); bool (*soscc_RegisterRecoveryPublicKey)(CFDataRef recovery_key, CFErrorRef *error); CFDataRef (*soscc_CopyRecoveryPublicKey)(CFErrorRef *error); bool (*soscc_RemoveThisDeviceFromCircle)(CFErrorRef* error); - bool (*soscc_RemoveThisDeviceFromCircleWithAnalytics)(CFDataRef parentEvent, CFErrorRef* error); bool (*soscc_RemovePeersFromCircle)(CFArrayRef peers, CFErrorRef* error); - bool (*soscc_RemovePeersFromCircleWithAnalytics)(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error); + bool (*soscc_LoggedIntoAccount)(CFErrorRef* error); bool (*soscc_LoggedOutOfAccount)(CFErrorRef* error); bool (*soscc_BailFromCircle)(uint64_t limit_in_seconds, CFErrorRef* error); bool (*soscc_AcceptApplicants)(CFArrayRef applicants, CFErrorRef* error); @@ -400,7 +394,6 @@ struct securityd { bool (*sec_set_circle_log_settings)(CFTypeRef type, CFErrorRef* error); SOSPeerInfoRef (*soscc_CopyMyPeerInfo)(CFErrorRef*); bool (*soscc_WaitForInitialSync)(CFErrorRef*); - bool (*soscc_WaitForInitialSyncWithAnalytics)(CFDataRef parentEvent, CFErrorRef *error); bool (*soscc_PeerAvailability)(CFErrorRef *error); SOSPeerInfoRef (*soscc_CopyApplicant)(CFErrorRef *error); CFDataRef (*soscc_CopyCircleJoiningBlob)(SOSPeerInfoRef applicant, CFErrorRef *error); @@ -445,6 +438,9 @@ struct trustd { bool (*sec_trust_increment_exception_reset_count)(CFErrorRef *error); uint64_t (*sec_trust_get_exception_reset_count)(CFErrorRef *error); #endif + bool (*sec_trust_store_set_ca_revocation_additions)(CFStringRef appID, CFDictionaryRef additions, CFErrorRef *error); + CFDictionaryRef (*sec_trust_store_copy_ca_revocation_additions)(CFStringRef appID, CFErrorRef *error); + bool (*sec_valid_update)(CFErrorRef *error); }; extern struct trustd *gTrustd; @@ -534,11 +530,14 @@ typedef void (^SecBoolNSErrorCallback) (bool, NSError*); - (void)secItemVerifyBackupIntegrity:(BOOL)lightweight completion:(void (^)(NSDictionary* resultsPerKeyclass, NSError* error))completion; +// Delete all items from the keychain where agrp==identifier and clip==1. Requires App Clip deletion entitlement. +- (void)secItemDeleteForAppClipApplicationIdentifier:(NSString*)identifier + completion:(void (^)(OSStatus status))completion; @end // Call this to receive a proxy object conforming to SecuritydXPCProtocol that you can call methods on. // It's probably a remote object for securityd/secd, but it might be in-process if you've configured it that way. -id SecuritydXPCProxyObject(void (^rpcErrorHandler)(NSError *)); +id SecuritydXPCProxyObject(bool synchronous, void (^rpcErrorHandler)(NSError *)); // Set up a local securityxpcserver: after this call, all securitydxpc calls will be handled in-process instead of actually transferring to securityd id SecCreateLocalSecuritydXPCServer(void) NS_RETURNS_RETAINED; diff --git a/OSX/sec/ipc/server.c b/OSX/sec/ipc/server.c index 1a8eb59e..86935cfe 100644 --- a/OSX/sec/ipc/server.c +++ b/OSX/sec/ipc/server.c @@ -30,6 +30,7 @@ #include #include +#include #include "keychain/SecureObjectSync/SOSPeerInfoDER.h" #include #include @@ -58,6 +59,7 @@ #include "trust/trustd/SecTrustStoreServer.h" #include "keychain/securityd/iCloudTrace.h" #include "keychain/securityd/spi.h" +#include #include #include #include @@ -118,6 +120,51 @@ #include "util.h" +static void refresh_prng(void) +{ + aks_ref_key_t ref = NULL; + + int fd = open("/dev/random", O_WRONLY); + if (fd == -1) { + secerror("failed to open /dev/random (%d)", errno); + goto out; + } + + /* create class F ref-key, and use its public key as an entropy source */ + int err = aks_ref_key_create(bad_keybag_handle, key_class_f, key_type_asym_ec_p256, NULL, 0, &ref); + if (err != kAKSReturnSuccess) { + secerror("failed to create refkey (%d)", err); + goto out; + } + + size_t pub_key_len = 0; + const uint8_t *pub_key = aks_ref_key_get_public_key(ref, &pub_key_len); + if (pub_key_len > ccec_export_pub_size_cp(ccec_cp_256())) { + secerror("invalid pub key (%zu)", pub_key_len); + goto out; + } + + while (pub_key_len > 0) { + ssize_t n = write(fd, pub_key, pub_key_len); + if (n == -1) { + secerror("failed to write /dev/random (%d)", errno); + goto out; + } + + pub_key += n; + pub_key_len -= n; + } + + out: + if (ref) { + aks_ref_key_free(&ref); + } + + if (fd >= 0) { + close(fd); + } +} + #if SECUREOBJECTSYNC CF_RETURNS_RETAINED @@ -191,7 +238,7 @@ static CFDataRef SecXPCDictionaryCopyCFDataRef(xpc_object_t message, const char CFDataRef retval = NULL; const uint8_t *bytes = NULL; size_t len = 0; - + bytes = xpc_dictionary_get_data(message, key, &len); require_action_quiet(bytes, errOut, SOSCreateError(kSOSErrorBadKey, CFSTR("missing CFDataRef info"), NULL, error)); retval = CFDataCreate(NULL, bytes, len); @@ -208,7 +255,7 @@ static CFSetRef CreateCFSetRefFromXPCObject(xpc_object_t xpcSetDER, CFErrorRef* const uint8_t* der = xpc_data_get_bytes_ptr(xpcSetDER); const uint8_t* der_end = der + xpc_data_get_length(xpcSetDER); - der = der_decode_set(kCFAllocatorDefault, kCFPropertyListMutableContainersAndLeaves, &retval, error, der, der_end); + der = der_decode_set(kCFAllocatorDefault, &retval, error, der, der_end); if (der != der_end) { SecError(errSecDecode, error, CFSTR("trailing garbage at end of SecAccessControl data")); goto errOut; @@ -341,6 +388,8 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, .allowSyncBubbleKeychain = false, .isNetworkExtension = false, .canAccessNetworkExtensionAccessGroups = false, + .applicationIdentifier = NULL, + .isAppClip = false, }; secdebug("serverxpc", "entering"); @@ -383,6 +432,16 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFDictionaryGetValue(query, kSecAttrPCSPlaintextPublicIdentity)) { entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateCKKSPlaintextFields, &error); } + if(entitlementsCorrect && + (CFDictionaryGetValue(query, kSecDataInetExtraNotes) || + CFDictionaryGetValue(query, kSecDataInetExtraHistory) || + CFDictionaryGetValue(query, kSecDataInetExtraClientDefined0) || + CFDictionaryGetValue(query, kSecDataInetExtraClientDefined1) || + CFDictionaryGetValue(query, kSecDataInetExtraClientDefined2) || + CFDictionaryGetValue(query, kSecDataInetExtraClientDefined3))) { + entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateInetExpansionFields, &error); + } + if (entitlementsCorrect && CFDictionaryGetValue(query, kSecAttrSysBound)) { entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateSysBound, &error); } @@ -406,7 +465,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, if (query) { CFTypeRef result = NULL; if (_SecItemCopyMatching(query, &client, &result, &error) && result) { - SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + SecXPCDictionarySetPListWithRepair(replyMessage, kSecXPCKeyResult, result, true, &error); CFReleaseNull(result); } CFReleaseNull(query); @@ -429,6 +488,15 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFDictionaryGetValue(attributesToUpdate, kSecAttrPCSPlaintextPublicIdentity)) { entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateCKKSPlaintextFields, &error); } + if(entitlementsCorrect && + (CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraNotes) || + CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraHistory) || + CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined0) || + CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined1) || + CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined2) || + CFDictionaryGetValue(attributesToUpdate, kSecDataInetExtraClientDefined3))) { + entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateInetExpansionFields, &error); + } if (entitlementsCorrect && CFDictionaryGetValue(query, kSecAttrSysBound)) { entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateSysBound, &error); } @@ -456,17 +524,20 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } break; } - case sec_item_update_token_items_id: + case sec_item_update_token_items_for_access_groups_id: { - if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) { + if (EntitlementAbsentOrFalse(sec_item_update_token_items_for_access_groups_id, client.task, kSecEntitlementKeychainDeny, &error) && + EntitlementPresentAndTrue(sec_item_update_token_items_for_access_groups_id, client.task, kSecEntitlementUpdateTokenItems, &error)) { CFStringRef tokenID = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error); - CFArrayRef attributes = SecXPCDictionaryCopyArray(event, kSecXPCKeyQuery, &error); + CFArrayRef accessGroups = SecXPCDictionaryCopyArray(event, kSecXPCKeyArray, &error); + CFArrayRef tokenItems = SecXPCDictionaryCopyArray(event, kSecXPCKeyQuery, &error); if (tokenID) { - bool result = _SecItemUpdateTokenItems(tokenID, attributes, &client, &error); + bool result = _SecItemUpdateTokenItemsForAccessGroups(tokenID, accessGroups, tokenItems, &client, &error); xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); } CFReleaseNull(tokenID); - CFReleaseNull(attributes); + CFReleaseNull(accessGroups); + CFReleaseNull(tokenItems); } break; } @@ -642,6 +713,18 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } break; } + case sec_item_backup_ensure_copy_view_id: + { + if(EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) { + CFStringRef viewName = NULL; + if (SecXPCDictionaryCopyStringOptional(event, kSecXPCKeyString, &viewName, &error)) { + CFStringRef name = SecServerItemBackupEnsureCopyView(viewName, &error); + SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, name, &error); + CFReleaseNull(name); + } + } + break; + } case sec_item_backup_handoff_fd_id: { if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) { @@ -833,19 +916,6 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, }); } break; - case kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server(label, password, dsid, parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetUserCredentialsAndDSID_Server(label, password, dsid, &error)); - } - CFReleaseNull(parentEvent); - }); - } - break; case kSecXPCOpView: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { with_view_and_action(event, ^(CFStringRef view, uint64_t actionCode) { @@ -854,18 +924,13 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, }); } break; - case kSecXPCOpViewSet: // FALLTHROUGH - case kSecXPCOpViewSetWithAnalytics: + case kSecXPCOpViewSet: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { CFSetRef enabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyEnabledViewsKey); CFSetRef disabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyDisabledViewsKey); - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error)){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSetWithAnalytics_Server(enabledViews, disabledViews, parentEvent)); - } + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSet_Server(enabledViews, disabledViews)); CFReleaseNull(enabledViews); CFReleaseNull(disabledViews); - CFReleaseNull(parentEvent); } break; case kSecXPCOpCanAuthenticate: @@ -892,14 +957,6 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SOSCCRequestToJoinCircle_Server(&error)); } break; - case kSecXPCOpRequestToJoinWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDataRef parentEvent = NULL; - SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleWithAnalytics_Server(parentEvent, &error)); - CFReleaseNull(parentEvent); - } - break; case kSecXPCOpAccountHasPublicKey: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, @@ -913,17 +970,6 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SOSCCRequestToJoinCircleAfterRestore_Server(&error)); } break; - case kSecXPCOpRequestToJoinAfterRestoreWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleAfterRestore_Server(&error)); - } - CFReleaseNull(parentEvent); - } - break; case kSecXPCOpRequestDeviceID: case kSecXPCOpSetDeviceID: case kSecXPCOpHandleIDSMessage: @@ -952,33 +998,12 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SOSCCResetToEmpty_Server(&error)); } break; - case kSecXPCOpResetToEmptyWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCResetToEmptyWithAnalytics_Server(parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCResetToEmpty_Server(&error)); - } - } - break; case kSecXPCOpRemoveThisDeviceFromCircle: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemoveThisDeviceFromCircle_Server(&error)); } break; - case kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemoveThisDeviceFromCircleWithAnalytics_Server(parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemoveThisDeviceFromCircle_Server(&error)); - } - CFReleaseNull(parentEvent); - } - break; case kSecXPCOpRemovePeersFromCircle: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { CFArrayRef applicants = SecXPCDictionaryCopyPeerInfoArray(event, kSecXPCKeyPeerInfoArray, &error); @@ -987,19 +1012,13 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFReleaseNull(applicants); } break; - case kSecXPCOpRemovePeersFromCircleWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFArrayRef applicants = SecXPCDictionaryCopyPeerInfoArray(event, kSecXPCKeyPeerInfoArray, &error); - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemovePeersFromCircleWithAnalytics_Server(applicants, parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemovePeersFromCircle_Server(applicants, &error)); + case kSecXPCOpLoggedIntoAccount: + if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { + SOSCCNotifyLoggedIntoAccount_Server(); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + true); } - CFReleaseNull(parentEvent); - CFReleaseNull(applicants); - } - break; + break; case kSecXPCOpLoggedOutOfAccount: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, @@ -1131,7 +1150,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SOSCCCopyViewUnawarePeerInfo_Server(&error), &error); } - break; + break; case kSecXPCOpCopyEngineState: { if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { @@ -1149,7 +1168,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } } break; - case kSecXPCOpCopyPeerPeerInfo: + case kSecXPCOpCopyPeerPeerInfo: if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult, SOSCCCopyPeerPeerInfo_Server(&error), @@ -1231,18 +1250,6 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SOSCCWaitForInitialSync_Server(&error)); } break; - - case kSecXPCOpWaitForInitialSyncWithAnalytics: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { - CFDataRef parentEvent = NULL; - if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWaitForInitialSyncWithAnalytics_Server(parentEvent, &error)); - }else{ - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWaitForInitialSync_Server(&error)); - } - CFReleaseNull(parentEvent); - } - break; case kSecXPCOpPeersHaveViewsEnabled: { CFArrayRef viewSet = SecXPCDictionaryCopyArray(event, kSecXPCKeyArray, &error); @@ -1367,14 +1374,12 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } } break; - case kSecXPCOpKVSKeyCleanup: - if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { + if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) { bool retval = SOSCCCleanupKVSKeys_Server(&error); xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval); } break; - case kSecXPCOpMessageFromPeerIsPending: { SOSPeerInfoRef peer = SecXPCDictionaryCopyPeerInfo(event, kSecXPCKeyPeerInfo, &error); @@ -1499,12 +1504,14 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_connection_send_message(connection, replyMessage); xpc_release(replyMessage); } - if (xpcError) + if (xpcError) { xpc_release(xpcError); + } CFReleaseSafe(error); CFReleaseSafe(client.accessGroups); CFReleaseSafe(client.musr); CFReleaseSafe(client.task); + CFReleaseNull(client.applicationIdentifier); CFReleaseSafe(domains); CFReleaseSafe(clientAuditToken); } @@ -1541,6 +1548,13 @@ static void securityd_xpc_init(const char *service_name) }); #endif + xpc_activity_register("com.apple.securityd.prng", XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) { + xpc_activity_state_t state = xpc_activity_get_state(activity); + if (state == XPC_ACTIVITY_STATE_RUN) { + refresh_prng(); + } + }); + #if OCTAGON && !TARGET_OS_BRIDGE // Kick off reporting tasks. if (os_variant_has_internal_diagnostics("com.apple.security") && !os_variant_is_recovery("securityd")) { @@ -1552,7 +1566,7 @@ static void securityd_xpc_init(const char *service_name) // 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_BRIDGE static void securityd_soscc_lock_hack() { dispatch_queue_t soscc_lock_queue = dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT); int soscc_tok; @@ -1642,22 +1656,29 @@ int main(int argc, char *argv[]) }); #endif + signal(SIGTERM, SIG_IGN); + static dispatch_source_t termSource; + termSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)); + dispatch_source_set_event_handler(termSource, ^{ + secnotice("signal", "SIGTERM, exiting when clean ✌️"); + xpc_transaction_exit_clean(); + }); + dispatch_activate(termSource); + #if TARGET_OS_OSX #define SECD_PROFILE_NAME "com.apple.secd" const char *homedir = homedirPath(); - if (homedir == NULL) + if (homedir == NULL) { errx(1, "failed to get home directory for secd"); + } char *errorbuf = NULL; - const char *sandbox_params[] = { - "_HOME", homedir, - NULL - }; - int32_t rc; - - rc = sandbox_init_with_parameters(SECD_PROFILE_NAME, SANDBOX_NAMED, sandbox_params, &errorbuf); - if (rc) - err(1, "Failed to process in a sandbox: %d %s", rc, errorbuf); + const char *sandbox_params[] = {"_HOME", homedir, NULL}; + int32_t rc = sandbox_init_with_parameters(SECD_PROFILE_NAME, SANDBOX_NAMED, sandbox_params, &errorbuf); + if (rc) { + errx(1, "Failed to instantiate sandbox: %d %s", rc, errorbuf); + /* errx will quit the process */ + } #endif /* TARGET_OS_OSX */ const char *serviceName = kSecuritydXPCServiceName; @@ -1674,11 +1695,12 @@ int main(int argc, char *argv[]) securityd_init_server(); securityd_xpc_init(serviceName); - SecCreateSecuritydXPCServer(); + #if SECUREOBJECTSYNC SOSControlServerInitialize(); #endif + #if OCTAGON CKKSControlServerInitialize(); OctagonControlServerInitialize(); @@ -1686,7 +1708,7 @@ int main(int argc, char *argv[]) #endif // 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_BRIDGE securityd_soscc_lock_hack(); #endif diff --git a/OSX/sec/ipc/server_endpoint.m b/OSX/sec/ipc/server_endpoint.m index 8db291ac..50607d9e 100644 --- a/OSX/sec/ipc/server_endpoint.m +++ b/OSX/sec/ipc/server_endpoint.m @@ -75,6 +75,8 @@ self->_client.inMultiUser = existingClient->inMultiUser; self->_client.activeUser = existingClient->activeUser; #endif + self->_client.applicationIdentifier = CFRetainSafe(existingClient->applicationIdentifier); + self->_client.isAppClip = existingClient->isAppClip; } return self; } @@ -88,6 +90,7 @@ CFReleaseNull(self->_client.task); CFReleaseNull(self->_client.accessGroups); CFReleaseNull(self->_client.musr); + CFReleaseNull(self->_client.applicationIdentifier); } @end diff --git a/OSX/sec/ipc/server_entitlement_helpers.c b/OSX/sec/ipc/server_entitlement_helpers.c index 3dd4c584..f5fbfa98 100644 --- a/OSX/sec/ipc/server_entitlement_helpers.c +++ b/OSX/sec/ipc/server_entitlement_helpers.c @@ -29,10 +29,12 @@ #include #include "ipc/securityd_client.h" #include +#include "sectask/SystemEntitlements.h" #include #include "utilities/SecCFRelease.h" #include "utilities/SecCFWrappers.h" #include "utilities/debugging.h" +#include CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task, CFStringRef entitlement) @@ -70,8 +72,14 @@ CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task, } CFStringRef SecTaskCopyApplicationIdentifier(SecTaskRef task) { - return SecTaskCopyStringForEntitlement(task, - kSecEntitlementApplicationIdentifier); + // Catalyst apps may have the iOS style application identifier. + CFStringRef result = SecTaskCopyStringForEntitlement(task, + kSecEntitlementBasicApplicationIdentifier); + if (!result) { + result = SecTaskCopyStringForEntitlement(task, + kSecEntitlementAppleApplicationIdentifier); + } + return result; } #if TARGET_OS_IOS @@ -85,6 +93,8 @@ CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) { CFMutableArrayRef groups = NULL; + bool onDemandInstallable = SecTaskGetBooleanValueForEntitlement(task, kSystemEntitlementOnDemandInstallCapable); + CFArrayRef keychainAccessGroups, appleSecurityApplicationGroups; CFStringRef appID; CFArrayRef associatedAppIDs; @@ -92,7 +102,7 @@ CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) keychainAccessGroups = SecTaskCopyArrayOfStringsForEntitlement(task, kSecEntitlementKeychainAccessGroups); appleSecurityApplicationGroups = SecTaskCopyArrayOfStringsForEntitlement(task, kSecEntitlementAppleSecurityApplicationGroups); appID = SecTaskCopyApplicationIdentifier(task); - // Marzipan apps (may?) have this entitlement. + // Catalyst apps (may?) have this entitlement. associatedAppIDs = SecTaskCopyArrayOfStringsForEntitlement(task, kSecEntitlementAssociatedApplicationIdentifier); groups = CFArrayCreateMutableForCFTypes(NULL); @@ -118,14 +128,19 @@ CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) CFArrayAppendValue(groups, appID); } if (appleSecurityApplicationGroups) { - CFArrayAppendArray(groups, appleSecurityApplicationGroups, CFRangeMake(0, CFArrayGetCount(appleSecurityApplicationGroups))); + if (onDemandInstallable) { + // This is perfectly legal for other functionality but not for keychain use + secnotice("entitlements", "Ignoring \"%@\" because client is API-restricted", kSecEntitlementAppleSecurityApplicationGroups); + } else { + CFArrayAppendArray(groups, appleSecurityApplicationGroups, CFRangeMake(0, CFArrayGetCount(appleSecurityApplicationGroups))); + } } } else { // Try to provide some hopefully helpful diagnostics for common failure cases. if (CFArrayGetCount(groups) == 0) { if (appID) { secwarning("Entitlement %@=%@ is ignored because of invalid application signature or incorrect provisioning profile", - kSecEntitlementApplicationIdentifier, appID); + kSecEntitlementApplicationIdentifier, appID); } if (appleSecurityApplicationGroups) { secwarning("Entitlement %@=%@ is ignored because of invalid application signature or incorrect provisioning profile", @@ -134,6 +149,21 @@ CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) } } + // Do not allow to explicitly specify com.apple.token if token support is not allowed by feature flags. + CFIndex index = CFArrayGetFirstIndexOfValue(groups, CFRangeMake(0, CFArrayGetCount(groups)), kSecAttrAccessGroupToken); + if (index != kCFNotFound) { + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + // Make sure that com.apple.token is last one. This is because it is always read-only group and therefore updating keychain + // operations without explicitly set kSecAttrAccessGroup attribute would always fail. + CFArrayRemoveValueAtIndex(groups, index); + CFArrayAppendValue(groups, kSecAttrAccessGroupToken); + } else { + secwarning("Keychain access group com.apple.token ignored, feature not available"); + CFArrayRemoveValueAtIndex(groups, index); + } + } + +#if TARGET_OS_OSX /* * We would like to add implicit token access group always, but we avoid doing that in case that application * clearly intended to use non-smartcard functionality of keychain but messed up signing or provisioning. In this case, @@ -142,8 +172,12 @@ CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) */ bool entitlementsFailure = (CFArrayGetCount(groups) == 0 && appID != NULL); if (!entitlementsFailure) { - CFArrayAppendValue(groups, kSecAttrAccessGroupToken); + bool addTokenGroup = os_feature_enabled(CryptoTokenKit, UseTokens); + if (addTokenGroup && !CFArrayContainsValue(groups, CFRangeMake(0, CFArrayGetCount(groups)), kSecAttrAccessGroupToken)) { + CFArrayAppendValue(groups, kSecAttrAccessGroupToken); + } } +#endif CFReleaseNull(associatedAppIDs); CFReleaseNull(appID); diff --git a/OSX/sec/ipc/server_security_helpers.h b/OSX/sec/ipc/server_security_helpers.h index 216018f9..8d878b21 100644 --- a/OSX/sec/ipc/server_security_helpers.h +++ b/OSX/sec/ipc/server_security_helpers.h @@ -46,5 +46,8 @@ bool SecTaskIsEligiblePlatformBinary(SecTaskRef task, CFArrayRef identifiers); // Testing support void SecAccessGroupsSetCurrent(CFArrayRef accessGroups); +void SecSecurityClientRegularToAppClip(void); +void SecSecurityClientAppClipToRegular(void); +void SecSecurityClientSetApplicationIdentifier(CFStringRef identifier); #endif /* server_security_helpers_h */ diff --git a/OSX/sec/ipc/server_security_helpers.m b/OSX/sec/ipc/server_security_helpers.m index b360fc43..b6351c6b 100644 --- a/OSX/sec/ipc/server_security_helpers.m +++ b/OSX/sec/ipc/server_security_helpers.m @@ -30,6 +30,7 @@ #include #include "ipc/securityd_client.h" #include +#include "sectask/SystemEntitlements.h" #include #include #include @@ -108,8 +109,7 @@ fill_security_client(SecurityClient * client, const uid_t uid, audit_token_t aud client->uid = uid; client->musr = NULL; -#if TARGET_OS_IOS -#if HAVE_MOBILE_KEYBAG_SUPPORT +#if TARGET_OS_IOS && HAVE_MOBILE_KEYBAG_SUPPORT if (device_is_multiuser()) { CFErrorRef error = NULL; @@ -139,15 +139,23 @@ fill_security_client(SecurityClient * client, const uid_t uid, audit_token_t aud client->keybag = KEYBAG_DEVICE; } } else -#endif +#endif /* TARGET_OS_IOS && HAVE_MOBILE_KEYBAG_SUPPORT */ +#if TARGET_OS_IOS || TARGET_OS_TV /* - * If the client application is a enterprise app according to usermanager, switch - * to the per enterprise slice of keychain. + * iOS supports Enterprise Data Separation. + * tvOS supports guest users. + * Use the appropriate musr values for either. */ { UMUserPersona * persona = [[UMUserManager sharedManager] currentPersona]; - if (persona && persona.userPersonaType == UMUserPersonaTypeEnterprise) { - secinfo("serverxpc", "securityd client: enterprise user"); + if (persona && +#if TARGET_OS_IOS + persona.userPersonaType == UMUserPersonaTypeEnterprise +#elif TARGET_OS_TV + persona.userPersonaType == UMUserPersonaTypeGuest +#endif + ) { + secinfo("serverxpc", "securityd client: persona user %@", persona.userPersonaNickName); uuid_t uuid; if (uuid_parse([persona.userPersonaUniqueString UTF8String], uuid) != 0) { @@ -156,11 +164,15 @@ fill_security_client(SecurityClient * client, const uid_t uid, audit_token_t aud client->musr = CFDataCreate(NULL, uuid, sizeof(uuid_t)); } } -#endif /* TARGET_OS_IOS */ +#endif /* TARGET_OS_IOS || TARGET_OS_TV */ client->task = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken); - client->accessGroups = SecTaskCopyAccessGroups(client->task); + client->applicationIdentifier = SecTaskCopyApplicationIdentifier(client->task); + client->isAppClip = SecTaskGetBooleanValueForEntitlement(client->task, kSystemEntitlementOnDemandInstallCapable); + if (client->isAppClip) { + secinfo("serverxpc", "securityd client: app clip (API restricted)"); + } #if TARGET_OS_IPHONE client->allowSystemKeychain = SecTaskGetBooleanValueForEntitlement(client->task, kSecEntitlementPrivateSystemKeychain); @@ -173,6 +185,10 @@ fill_security_client(SecurityClient * client, const uid_t uid, audit_token_t aud } #endif if (!sanityCheckClientAccessGroups(client)) { + CFReleaseNull(client->task); + CFReleaseNull(client->accessGroups); + CFReleaseNull(client->musr); + CFReleaseNull(client->applicationIdentifier); return false; } } diff --git a/OSX/sec/ipc/server_xpc.m b/OSX/sec/ipc/server_xpc.m index 27413305..6372a459 100644 --- a/OSX/sec/ipc/server_xpc.m +++ b/OSX/sec/ipc/server_xpc.m @@ -107,6 +107,20 @@ } } + if(attributes[(id)kSecDataInetExtraNotes] || + attributes[(id)kSecDataInetExtraHistory] || + attributes[(id)kSecDataInetExtraClientDefined0] || + attributes[(id)kSecDataInetExtraClientDefined1] || + attributes[(id)kSecDataInetExtraClientDefined2] || + attributes[(id)kSecDataInetExtraClientDefined3]) { + if(![self clientHasBooleanEntitlement:(__bridge NSString*)kSecEntitlementPrivateInetExpansionFields]) { + SecError(errSecMissingEntitlement, &cferror, CFSTR("SecItemAddAndNotifyOnSync: %@ does not have entitlement %@"), _client.task, kSecEntitlementPrivateInetExpansionFields); + complete(NULL, NULL, (__bridge NSError*) cferror); + CFReleaseNull(cferror); + return; + } + } + CFTypeRef cfresult = NULL; NSMutableDictionary* callbackQuery = [attributes mutableCopy]; @@ -363,7 +377,7 @@ (__bridge NSString *)kSecAttrSynchronizable : (__bridge NSString *)kSecAttrSynchronizableAny, }; - Query *q = query_create_with_limit((__bridge CFDictionaryRef)attributes, _client.musr, 0, &cferror); + Query *q = query_create_with_limit((__bridge CFDictionaryRef)attributes, _client.musr, 0, &(_client), &cferror); if (q == NULL) { SecError(errSecParam, &cferror, CFSTR("failed to build query: %@"), _client.task); complete(NULL, (__bridge NSError*) cferror); @@ -425,4 +439,16 @@ [[SecDbBackupManager manager] verifyBackupIntegrity:lightweight completion:completion]; } + +- (void)secItemDeleteForAppClipApplicationIdentifier:(NSString*)identifier + completion:(void (^)(OSStatus))completion +{ + if (![self clientHasBooleanEntitlement:(__bridge NSString*)kSecEntitlementPrivateAppClipDeletion]) { + completion(errSecMissingEntitlement); + return; + } + + completion(SecServerDeleteForAppClipApplicationIdentifier((__bridge CFStringRef)identifier)); +} + @end diff --git a/OSX/sec/os_log/com.apple.security.ckks.plist b/OSX/sec/os_log/com.apple.security.ckks.plist new file mode 100644 index 00000000..b164d1b6 --- /dev/null +++ b/OSX/sec/os_log/com.apple.security.ckks.plist @@ -0,0 +1,37 @@ + + + + + DEFAULT-OPTIONS + + Default-Privacy-Setting + Public + Enabled + True + Persist + Default + Enable-Oversize-Messages + + TTL + Default + Development + + Enabled + True + Persist + Default + TTL + Default + + Debug + + Enabled + True + Persist + True + TTL + 2 + + + + diff --git a/OSX/sec/os_log/com.apple.securityd.plist b/OSX/sec/os_log/com.apple.securityd.plist index 87da5a3d..a293e2d7 100644 --- a/OSX/sec/os_log/com.apple.securityd.plist +++ b/OSX/sec/os_log/com.apple.securityd.plist @@ -80,5 +80,25 @@ 30 + itemDelete + + Default-Privacy-Setting + Public + Enabled + True + Persist + True + TTL + 10d + Development + + Enabled + True + Persist + True + TTL + 10d + + diff --git a/OSX/sectests/SecurityTests-Entitlements.plist b/OSX/sectests/SecurityTests-Entitlements.plist index 35eb8339..9dc36dce 100644 --- a/OSX/sectests/SecurityTests-Entitlements.plist +++ b/OSX/sectests/SecurityTests-Entitlements.plist @@ -33,5 +33,11 @@ 123456.test.group 123456.test.group2 + com.apple.private.AuthorizationServices + + com.apple.trust-settings.admin + + com.apple.private.security.storage.Keychains + diff --git a/OSX/sectests/testlist.h b/OSX/sectests/testlist.h index 44ebadc5..e637efee 100644 --- a/OSX/sectests/testlist.h +++ b/OSX/sectests/testlist.h @@ -5,6 +5,5 @@ /* Don't prevent multiple inclusion of this file. */ #include #include -#include #include diff --git a/OSX/shared_regressions/shared_regressions.h b/OSX/shared_regressions/shared_regressions.h index 83786104..f599fe70 100644 --- a/OSX/shared_regressions/shared_regressions.h +++ b/OSX/shared_regressions/shared_regressions.h @@ -10,18 +10,12 @@ ONE_TEST(si_21_sectrust_asr) ONE_TEST(si_22_sectrust_iap) -#if !TARGET_OS_WATCH -ONE_TEST(si_23_sectrust_ocsp) -#else -DISABLED_ONE_TEST(si_23_sectrust_ocsp) -#endif ONE_TEST(si_24_sectrust_itms) ONE_TEST(si_24_sectrust_diginotar) ONE_TEST(si_24_sectrust_digicert_malaysia) ONE_TEST(si_24_sectrust_passbook) ONE_TEST(si_25_cms_skid) ONE_TEST(si_26_sectrust_copyproperties) -ONE_TEST(si_28_sectrustsettings) ONE_TEST(si_29_cms_chain_mode) ONE_TEST(si_32_sectrust_pinning_required) ONE_TEST(si_34_cms_timestamp) @@ -41,19 +35,10 @@ ONE_TEST(si_62_csr) ONE_TEST(si_64_ossl_cms) ONE_TEST(si_65_cms_cert_policy) ONE_TEST(si_66_smime) -#if !TARGET_OS_WATCH -ONE_TEST(si_67_sectrust_blocklist) -ONE_TEST(si_84_sectrust_allowlist) -#else -DISABLED_ONE_TEST(si_67_sectrust_blocklist) -DISABLED_ONE_TEST(si_84_sectrust_allowlist) -#endif ONE_TEST(si_68_secmatchissuer) ONE_TEST(si_70_sectrust_unified) ONE_TEST(si_71_mobile_store_policy) -ONE_TEST(si_74_OTA_PKI_Signer) ONE_TEST(si_83_seccertificate_sighashalg) -ONE_TEST(si_88_sectrust_valid) ONE_TEST(si_89_cms_hash_agility) ONE_TEST(rk_01_recoverykey) diff --git a/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/bad_SAN_seq_length.cer b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/bad_SAN_seq_length.cer new file mode 100644 index 0000000000000000000000000000000000000000..787be2368e8bcbe51581e42fcec7b8e4fcbcaace GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9Nx={Q)G|{J=cL=WwVX^;U)&V% zk+*bn^4CYRW6OUoE3)~)9PrHex`xNscg`;(uUqn&zLI$)d-CaP9xDO2pf?ZLicIG8 zy*J+f{A$9qYf{GlI2{X5@_et}G0!xvKm2vx6235%rB8p!cRyw>>{eN7`7JNZI;dm2 zn(U6Ay{R{@B;Pv__I!@`N5*15SM>wGWZ0+neiNMKUdqUol5N`m`%`+^SwX>8ql^!m zE*v*bnNj7FU#-ERrx!O_-tTkHHb1T0S;|Ld_k9z*VWCs&6cuuRSM!U#AKaVki(=mk iJUdh=_t2;PSJJgV4=>#aC|N0Q?HKrEZ?@cgwO9Zkz-&GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NhCPP%v-$Yf66 zd*l7juO>{pCT0AO)3NX*&-dyb^GxIV!(Znu;R{n)`t+B4_haV5Zk45$-}1t&gF3dW z$?oXcn|k9)^1TCL&*zALWGwb`RX^}chJ9-9H^Eu%rHouD*{1!!Kc$zQ6%=eW%J{J9 z!g1r28C5>{)fyandU2EG{XXYx^V7*|-#5V<7CN;~Q6cwtHNV*V!M(Y@DE7U; ivqP0~4}IEyC0+aT@Y0Qdl9lq-j)711X3Nc2iv<8F;cQs| literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/san_zero_length_sequence.cer b/OSX/shared_regressions/si-18-certificate-parse/ExtensionFailureCerts/san_zero_length_sequence.cer new file mode 100644 index 0000000000000000000000000000000000000000..b6249ec4be3105a6b3e898c36d1df99e026d8ac3 GIT binary patch literal 812 zcmXqLV%9KdViH)u%*4pVB*<|5-=+H>iuT*RSqj zJPbt*gxQ!wS(t@+TpSH84b2_B4GauS3?&W3A;JR1mBl5gxeDp2d8tK-C8;TfA_hVb zDemIboHX6y%=Em}6azVNUPB85Ljy}gQ$q_AqbPA+BV!=f0?MVLO-+nS$lhRNWngY% zwA5AWHNp1ax|srK@3dUCeUfoWIZ{3FTR>xx>h*T^=% z^D%9Gp#4ws>ilzUTOKZNthKLvrLaLg|KrZ}O^X7*am}vutW4=<{~y1he){}uri`P` zheNfZ3g;Z%%X@-Zq~0>OIq}XH?XNRp4{8NWW!$~+Xy=A67rSkK8Wt^(U3qH7wO5AL zOKUpF|w4%gM>t!oUMC=1!yE?l_&Equ?Hhuj{QboGx_NArj-RG*i z9Gxn+Kbj<^8{kosGUE{$SDWU5y1^(Q0CAYrn z6Xmqs&jvsKfBl9H0AUYomh9{oe8uyAN+WVZ7JAHat|L>g}VHt)>h*6YdGmnXAdIDupM%g1xp+ zS#Og48%%LpI zJSr}!WvMy&1*t^}o-PW`sYNB3X_?81C7Jno3XY{E8Tmz-C6$J11}Y%s+&r?51qC^& zIMoRo2!hmc@o+)ZdFCbS8FCwNf&|%wnL>jNh&tTBR$i>ve$jESy>FS}@vtF-NRXHLF) zP~nq<#kQP{3w)%PeSB(i<;I2&COz6q_RICBd{CVqn<|&MD>*|f{T_Fj>fiO7_shO& zYJJ*pJV{!7b6nV~E0%MXTh5kWd;MW;p~q9n;2BwrB8tIJGBfQzAIQ;dsz~-*^@QjB z;hDjwq&U7z^-%6VDST=<&z&76>24WCEOp`si!Bs)1ew~4`X)3bzcWAcP5#H8#oy!~ z&UgJ4_3a>=*bnBGI{nAIZ|qpV9^eUY@j0#9=o6`PCwcjTWjTlM)XS}syJ1+%(WBqG zlk@*gCT2zk#>GvH4}l?a*T9aALz|6}m6e^5k;TY>!9WkjH(+d2$|xx*u+rDhPcAOd zO9Z7Kz2y8{FjqGvwJbBmz|cSz7$35HEMhDo8>c>Xh<#99_D%arv{?RxAm=%KuMBuV z(!z|4|5=!ThRcI^$}AEFVhtkU;%^t7zf&_~p}>Pb``UGNK0Ou>0lJ6}q(p(GiIEk^ zVKiv`2h9MafzrYjEHfhe_xJALJ08x^D`K_urvFX9|E0~M z%lM=&^X}oUn`yPPcwLLnTe5!iILHOmyJ`a&7^cRIa}5oe7?qGc$jHjT+{DPw02Jq9YGPz$xVFY({)+_Zc}LjOmT2U=tMiInXNoz< zG(YNJS*2N*S!Yjkyl<8!ubTZM+rwWEUQ$kB5O&wR%yZXz(v-N4t51ZN#64vX7n{#~ z?(pi0x-T3C?tH;7_sf=KGc92B-C?HkZI4ge?CN{fsdbHO`okOKr@wq_C7%-U;2B3# z5wGB`={LT(yWh~2{m;wt@2~?~e&D^EBHPR(c9pzW^l>;bTdK!qqiMBS+Ul3Do}9im z)j;*&7MD3&AFz9Dm1c|5cZs<2O2Kirp`U=1#IIge(S575*zfR9S;gAY`ea>YmGKR> zoOuFo4tsdNPu4$^yNBgr;;QR$Zj-0oV~?FzRJZhH9_tOBzf8=G42+Aj4KfYnfnh7F z%mR$g29cRZD>6^p8kZfKxyI$`2EKngzuZ0!P6x7lEMhDoQy1CHKX|?`gLhZWDhGS^ z@Q8a|p$2>){rrrK|5;d=nOHs;h=ceFECL1$20UzB32h#XslXIxz=Rwf!1M-;4n~I6 zdlzbdSQW_1WjDWEMP()<@W)XM*Q-}>~*+Zv|+87dkITEUNe1W$)n8hl-CX9b@WaU$o8S2q zM}A>a7tx$D^UQ-^UM-TEw&I-s--o*3_J|E4LI4DLs{5_nL>jNSZejk+yp+tM)Z`N9ARh&1M`Hsy zab80M14AIRFg7qSh!W>DHZU|YhH(wzNVG}MKnG+Kv#@GdVoqj?LUNFgXK`_9YLSAg zE3(5BKrS`1Flb^_LiQXZD+6;ABR>OBoQtW6k&)p*5$nzAGGF(dn!SE{biMxl#@0Tr z&wgpS+w`sq$*WIyk3O+%kzMrtV@vICbWO59VU%}7Q`NX|!z`w3r^wwp>#BoZOiRwY zx1eaMNupHV#rRVe=d@Xze{1c#xFPhb$dt%sh4Jx7EH=@-3S;7Y3wq z>K1AKUf8sH(RZ%N0>yh69nx8KrmYrZX`!GB7S~VvGfb zNTh*0Fl=R&S%A^mAmTAOr1nUz!GGOw*Fu&1KCJV-7<9quK$ee1j76lmdS-B1%Eq0U zr{2tBoO?sTqCoPr0Ut;|KO^IR78YhEmJbHvAie^NfB~NY4;xoPn+IbmFvS@#8Z^EI z$;h)bJ~d!?WYBnjL1W8;#>OS}2DK!n2PFdqph>`#CyAEw5Glh@(?A`hhFMqvrbYpj zJk#=v-~!O(x+rW(h(Qqboq(JKf%yxV1Q{7}S8QnzE?DzrqgP-xPy zFQp3>_fCs+{h{BKALnt}k&E|}TT#=4rh*44eDUv#!v4I-|HQO^+rhNA2iGo5<-IDW zC;siUee-njz|!9p7CB}rYW$0O6dKZh*}L(5d{w$igI6o&d)t4Z-LwTmb1Y+I$YuIbr{WfvXhq)*x1 z+06B)I8u@Gz}mYVi?;BsWoDnPWHwc?yJ*73Wh$ydvsU@!&yLzI|MKU>XUtnn-tKT+ pq39^n**xieRjJj>HBT>HN!icZDL(7VgBuU+cQ!9QbYI0F4gi#~mn#4O literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/KeyFailureCerts/parse_fail_explicit_paramaters.cer b/OSX/shared_regressions/si-18-certificate-parse/KeyFailureCerts/parse_fail_explicit_paramaters.cer new file mode 100644 index 0000000000000000000000000000000000000000..f9c53045004cd44d20fc3e02f51bf4a3ffb07e08 GIT binary patch literal 830 zcmXqLVzx49VtTNEnTe5!NhFrxS?ms3-`=~6`n#_7__0ooc~ok^#m1r4=5fxJg_+5q z$dKEBlZ`o)g-w{r#nn*2fDgps;9+-9Ey_*It2E>{;01}W^RW4r=4B>l81fnLfCRXB zSQAT%Qg^<+Z5<_VNNsu5jk5Ev4eu;ubl0rdIW^SsHsact! zft)z6k%57QftjJPfsuiE6p(9(#2pYfH8FY{G%+%>v4cZ~iP50(I};CFfcFzF&u!zV89@nMFGSHO5#%UheaXknCXpGR+FD^e!VxeY)0FjR9UtSXM#6; zvp#2Ir+z8Hn^~0M$Xqjyw&yI9v(hRa3eQ#B-Z;N*0*fO{w)n+Q4|SZ}f9!eoGe~(?+^Tn z@B-K?AgAtm_G|5O@p&zucb+=*Cs{QR=x1gp2A0@W)3v;|UuUX6#hek~UH||9 literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/NameFailureCerts/rdn_short_length.cer b/OSX/shared_regressions/si-18-certificate-parse/NameFailureCerts/rdn_short_length.cer new file mode 100644 index 0000000000000000000000000000000000000000..9c0f93b3eea356df5b1c32b0193f49da4b2e456a GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NhCPP%v-$Yf66 zd*l7juO>{pCT0AO)3NX*&-dyb^GxIV!(Znu;R{n)`t+B4_haV5Zk45$-}1t&gF3dW z$?oXcn|k9)^1TCL&*zALWGwb`RX^}chJ9-9H^Eu%rHouD*{1!!Kc$zQ6%=eW%J{J9 z!g1r28C5>{)fyandU2EG{XXYx^V7*|-#5V<7CN;~Q6cwtHNV*V!M(Y@DE7U; ivqP0~4}IEyC0+aT@Y0Qdl9lq-j)711X3Nc2ivGZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeIzhG4t>yC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NhCPP%v-$Yf66 zd*l7juO>{pCT0AO)3NX*&-dyb^GxIV!(Znu;R{n)`t+B4_haV5Zk45$-}1t&gF3dW z$?oXcn|k9)^1TCL&*zALWGwb`RX^}chJ9-9H^Eu%rHouD*{1!!Kc$zQ6%=eW%J{J9 z!g1r28C5>{)fyandU2EG{XXYx^V7*|-#5V<7CN;~Q6cwtHNV*V!M(Y@DE7U; ivqP0~4}IEyC0+aT@Y0Qdl9lq-j)711X3Nc2ivUn!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXAcRC~R1B0L)<_2!CgxQJ78GRWr7IYg zfKE9N{7DL z_wTWaKVQ#$e(AIWs_QRg9cwNg`(wD&d{_Ri#6C-&e#)#T&C zGT#qpmHzjSOPld**`l9UC%hGwJ5;F=zwF~x%LR_bldtbun)CeA4$d3KQBt|Jb)T0W zIlOh(H@&9(^Pm4lGQCs%iHBK+Iv{FzA$;d2L z0HTtNRE5&w)FOqv{F2P%RE4yn{9J{?(!?BKk_3ucDkK&c=OzK!$e9ON7yvU5BLnASYol+AzFv4#^fx5s$_2~AZ`BKIQ!ID=69uZ;IF2ON*%x>mK(zOGc&U)XX>;n^#X`KEF3 zb!E8inY(hnpJQo}V%W`ToEI}*zX~o^one&QvFFui!6mwL(!ZxZe>vsZJ+97$<{@Iw c4c_Y2oNFm%FOIG#ed3^Sx46Y$e`z-x01m$7aR2}S literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_ekus.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_ekus.cer new file mode 100644 index 0000000000000000000000000000000000000000..7b839ce37ea329835e7fae04637aa179dbff7ef5 GIT binary patch literal 974 zcmXqLVm@Wi#I$JvGZP~d6C;ZOFB_*;n@8JsUPeZ4RtAH{K0`$Vc{b)y7G@ra;9wtx zkfPG!5`}>LoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJe9WIkg+Dj`Z<@*#ntlv zpW9`=_-DHD^1eCW?oZ2n;N=*SyTSjsg;Il0?q_v>%Waq2w^kdU3ZEgUx1pHp`RA?K zi$pRd)7BEb=>h*iiEBw~}uv$LmC(EbP zN3-PY3v|9;n55?>t=F~n!-`2yvL5+&bT4UROix&Um8HNoMnZJk*O$_3#GRSr5-JaG zQFxpDT*p^b?OT82>3{aJm7lKoZ&%mbx7cIKC%ZzHX?54anigNPw<>$mWbuIa(pQOv z%U|qw^|umGb2D)&_20OC{))-MqQ^ql6-6A}trWWDQKe&Gyz#Q#7jv1I85tNCTN_v! z@B`yYR+y3TKMSh?GcaTf_&@^uAORL;CiVscF%VxB#OE zI5Ii(KI>x6+eIa+=bv?(KMPT-FRN`=|0)eeA239;R`$mU+>x4Q1dP2 z%nF%}P2aytWL{2;{Sq~S-%PZg>EZ3F_FuObOm~m=-O1-;`a5@i!-MK{;dK$LUz$Vr z-s}2t|FOjZ?jNTVwjP|%X7P3BdC^_{)xV^}$^s0z`-CRVv)K^MxTtksTmOq$-RnPUq5s)S{BiynL8KE*>t&f`Xh>1<$-> zJwsUoX^=v09+BYG{U|>LkkBO0uRlAXefs5IRfhB0yYf;|3 zbE`hzc>MC$@!qY+ygME|3P}FR@glS*C1vxvJB*tjx(J=NE3ZDJWuT>!B9Oz@CiY|# zuT5vbhXwzXzbmf8 z1C~|y)2c-`3eW4kwyAvCu6J4sk>ZxwgTcU+Nx`Y4Y|5rxAG791+Fw+8`Qq!g&66GH z*Iug)&n}(jnzWgRNs-~$oHINUyL-!2)l?k?tC}wrFL}*nuws$2eAB;0uIFM`002|6 Bt+fCE literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_general_subtrees.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseFailureCerts/zero_length_general_subtrees.cer new file mode 100644 index 0000000000000000000000000000000000000000..5d76d031d2d693738a72af9ddcf4e1618f1bd5b3 GIT binary patch literal 1009 zcmXqLVt#AT#B_B5GZP~d6Qi90FB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pj1Ah{&fx3fPSS&9wH`O^muehWrF*C2ESi!~5P{G;J zpovil*(;2!49rc8{0u;GE~X|%Muroj6Bc^6ZoT;M!}4l1qphF(q8AxVdA-{GkB(0T z|Jqm6emyp;U^}AtmgS{uPUH6-Yq)Orbjj;zimd&UQ}l`V|2Dn0mZYBYTgN|Dt-P1? z>axTs`mTMSia!z7! z5BI1IZJU_%LxQc~jqiP)^+qc$ZcblvLMb5IO+`MH-QiiwyHdrMQO9&SSndJ z!PMl(rM#v`COf!V{2zfzPHnpAOy72!Ez=QF_6)`Ap1=42+8#?;14TGLQ$xn5;63 zgn?Lt$dlUmi!oE%ICNOo?JM1uy8LGBiZpPX%kr^^v4}WUIJuqmTha9Vq2>MWE5#0Q z{dwPJzz5RL&&c?ng$0<3*bKx$d<7N(13m*DHm-y=55`oWxB;U9KS)9tq>$Bs8Aut# zfdu400wD%L3m6RimiQQWk(d;u3?zW2uy6|t7Ni#CW|owsrUaKJl@z6>8X~6vU}6TQ z07iyPK_BhCjBnT7UU4F?uYgI7#GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NE*BJ-qsb!`d&Plg#YdM*yzPKsi zBX8;EB^b*bx_B4 zHQ60KdsA;*NxpX=?D-t=kBr5BuIdMV$*@oD{U$iey_AtFCEK+B_owu-vx0)HMj0PA zT{v!>GNZ~TzgmMsPcLq=yx-@XZGKw0vy_j_?)xTq!$POlDJtatuI3keKe#v77sb98 icy_2#?x9cnucT{#9$vZ;P_k0q+A;9S-fX$~YOw%x3TwCk literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_directory_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_directory_name.cer new file mode 100644 index 0000000000000000000000000000000000000000..e755cecdc0d57cde5516893f1eccc0ac6ba7f8e2 GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NwcIpl$97#Q-5480sZ3&VW>-fQlBopE5ET4u`OoOJuPmXnFs(#>?4ExmHZ-TSjOBuORvQ7Jce@ZVqD=64%l<{HH zh2zF4Gpc;@t2H?E^x`JV`+d&Y=BJfAOZmv`zHfpzEOcs}qC)QPYJRczgL`v*QS5tx iXNM}~9{RNZO1k#v;iVe^B`f8v9Rr{2&6b<577GAKt!#7v literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_dns_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_dns_name.cer new file mode 100644 index 0000000000000000000000000000000000000000..3e60bc97eac6018b8a0a95421522cb53ede410f9 GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NhCPP%v-$Yf66 zd*l7juO>{pCT0AO)3NX*&-dyb^GxIV!(Znu;R{n)`t+B4_haV5Zk45$-}1t&gF3dW z$?oXcn|k9)^1TCL&*zALWGwb`RX^}chJ9-9H^Eu%rHouD*{1!!Kc$zQ6%=eW%J{J9 z!g1r28C5>{)fyandU2EG{XXYx^V7*|-#5V<7CN;~Q6cwtHNV*V!M(Y@DE7U; ivqP0~4}IEyC0+aT@Y0Qdl9lq-j)711X3Nc2iv<87GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NwcIpl$97#Q-5480sZ3&VW>-fQlBopE5ET4u`OoOJuPmXnFs(#>?4ExmHZ-TSjOBuORvQ7Jce@ZVqD=64%l<{HH zh2zF4Gpc;@t2H?E^x`JV`+d&Y=BJfAOZmv`zHfpzEOcs}qC)QPYJRczgL`v*QS5tx iXNM}~9{RNZO1k#v;iVe^B`f8v9Rr{2&6b<577GAL(QI`9 literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_ip_address.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_ip_address.cer new file mode 100644 index 0000000000000000000000000000000000000000..64eff2a1c125d25f638eeca0aa154e050821508a GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NhCPP%v-$Yf66 zd*l7juO>{pCT0AO)3NX*&-dyb^GxIV!(Znu;R{n)`t+B4_haV5Zk45$-}1t&gF3dW z$?oXcn|k9)^1TCL&*zALWGwb`RX^}chJ9-9H^Eu%rHouD*{1!!Kc$zQ6%=eW%J{J9 z!g1r28C5>{)fyandU2EG{XXYx^V7*|-#5V<7CN;~Q6cwtHNV*V!M(Y@DE7U; ivqP0~4}IEyC0+aT@Y0Qdl9lq-j)711X3Nc2iv<8DnQT`8 literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_other_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_other_name.cer new file mode 100644 index 0000000000000000000000000000000000000000..124c48e2311c55921c2818505ac872ecdccab906 GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NwcIpl$97#Q-5480sZ3&VW>-fQlBopE5ET4u`OoOJuPmXnFs(#>?4ExmHZ-TSjOBuORvQ7Jce@ZVqD=64%l<{HH zh2zF4Gpc;@t2H?E^x`JV`+d&Y=BJfAOZmv`zHfpzEOcs}qC)QPYJRczgL`v*QS5tx iXNM}~9{RNZO1k#v;iVe^B`f8v9Rr{2&6b<577GAG9c*v_ literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_registered_id.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_registered_id.cer new file mode 100644 index 0000000000000000000000000000000000000000..44163a71b7f8eb197170a6e8d6b3992b4167a7d8 GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NhCPP%v-$Yf66 zd*l7juO>{pCT0AO)3NX*&-dyb^GxIV!(Znu;R{n)`t+B4_haV5Zk45$-}1t&gF3dW z$?oXcn|k9)^1TCL&*zALWGwb`RX^}chJ9-9H^Eu%rHouD*{1!!Kc$zQ6%=eW%J{J9 z!g1r28C5>{)fyandU2EG{XXYx^V7*|-#5V<7CN;~Q6cwtHNV*V!M(Y@DE7U; ivqP0~4}IEyC0+aT@Y0Qdl9lq-j)711X3Nc2iv<8Ey=+(j literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_rfc822_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_rfc822_name.cer new file mode 100644 index 0000000000000000000000000000000000000000..6eaaa8efb6044b091f48a4883786d1f7b4189035 GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NhCPP%v-$Yf66 zd*l7juO>{pCT0AO)3NX*&-dyb^GxIV!(Znu;R{n)`t+B4_haV5Zk45$-}1t&gF3dW z$?oXcn|k9)^1TCL&*zALWGwb`RX^}chJ9-9H^Eu%rHouD*{1!!Kc$zQ6%=eW%J{J9 z!g1r28C5>{)fyandU2EG{XXYx^V7*|-#5V<7CN;~Q6cwtHNV*V!M(Y@DE7U; ivqP0~4}IEyC0+aT@Y0Qdl9lq-j)711X3Nc2iv<86!E8|g literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_uri_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_uri_name.cer new file mode 100644 index 0000000000000000000000000000000000000000..77a69f7a438e825d514fa4ef3fdfaac1681da662 GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NhCPP%v-$Yf66 zd*l7juO>{pCT0AO)3NX*&-dyb^GxIV!(Znu;R{n)`t+B4_haV5Zk45$-}1t&gF3dW z$?oXcn|k9)^1TCL&*zALWGwb`RX^}chJ9-9H^Eu%rHouD*{1!!Kc$zQ6%=eW%J{J9 z!g1r28C5>{)fyandU2EG{XXYx^V7*|-#5V<7CN;~Q6cwtHNV*V!M(Y@DE7U; ivqP0~4}IEyC0+aT@Y0Qdl9lq-j)711X3Nc2iv<8Cb!=7u literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_x400_name.cer b/OSX/shared_regressions/si-18-certificate-parse/ParseSuccessCerts/general_name_type_x400_name.cer new file mode 100644 index 0000000000000000000000000000000000000000..c84a8d9478069bd458a4401a637c36660d8197c5 GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6CLoXq4(g^*Mr+u6}j#6Sq7go}sUv7jI)RY$=yFImq})<7C0%FQDZoSIx( zlvz@#;F_17nU|Vcl$n=qC~P1IlIGyya!$<2Ov^9I%S<%nHsAyavI#SV1{(?)2!J^3 zJeyC8p>l zf?TARoS#ciS2i&!A%`R*D+6;ABR_*d6C)Q>6C)$Tw$OE-Br@!Yq@X6fd ze3!XAk8)N1%zfQHjUqX!Grq|OrI~aW{Lg%J{LGb&J2tL8kw0O=g=g0b1RbZeKHkOh zTkyvrA-DC)lN}EpUh})aw&bAuvwP<=+@im=Fo_>#D`}p;kZ+TN{@lU;OkYH-Ge-9eSQj%!~|-i^B{; z4ETXjB`eIx_@9NwcIpl$97#Q-5480sZ3&VW>-fQlBopE5ET4u`OoOJuPmXnFs(#>?4ExmHZ-TSjOBuORvQ7Jce@ZVqD=64%l<{HH zh2zF4Gpc;@t2H?E^x`JV`+d&Y=BJfAOZmv`zHfpzEOcs}qC)QPYJRczgL`v*QS5tx iXNM}~9{RNZO1k#v;iVe^B`f8v9Rr{2&6b<577GAJiEMKK literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/AAACertificateServices.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/AAACertificateServices.cer new file mode 100644 index 0000000000000000000000000000000000000000..5c715faed85eae3569262d7f3dd3fa93a62dff60 GIT binary patch literal 1078 zcmXqLVlgskVwPIK%*4pV#K>sC%f_kI=F#?@mywZ`mBFCeklTQhjX9KsO_<5u$xzxr z62#%)5ppj|O)N<*Qt(a8OU_6w1~Lr=4ER8j>^$tji8*QcMJa|-1`;3BO}8;hq+(!9=D%XaqM2>(L9Krh@_kR3etljY8_*?Y$UTeg!qEbyv!1#k$!E6ZWw>z%zdG%s za$rx9->Z+J>%N4{65={swaGZ)(XGzV&q@)W@7+27zPW8t&lLap8J}iMaBERNUbg@7 z8B?9^IQEp(rUM=uR!sbvIKNCGV8z7aXy`MkR z^P}$lH6^~%Gq$=PeX4o!=LCu4Npto!A6Kik>ry>_;O^XKrWpbXbNg@HyL7l^4sYBG z{gX`0j0}v68xI&X?lq7F#dY#EPc0sPf3X5{=a{Ob{zMQ z`qG)eTA#3;)$8-OkB9aj*;&%IO}94t%%#t6clD1w$U1!3gjuI{+TEx_e9O6J9%Sua z&7=Q0#_D{Ic_?T5yAv>AB-zo?y~ literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/ApplePublicServerRSA12-G1.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/ApplePublicServerRSA12-G1.cer new file mode 100644 index 0000000000000000000000000000000000000000..3b7788be8972fcc47824d2165de91f8249d55df9 GIT binary patch literal 1172 zcmXqLVwqsj#9Xm}nTe5!Nr3A~zcQmiisPinhlggp?3FO!W#iOp^Jx3d%gD&h%3x4! z$Zf#M#vIDRCd}mSWGHPQ3F2_@2)P%fCYGcYDflMlC1<1-1DS>b27Dk%b{_WN#GJJJ zq7*|Z0|}4_7muKGer|qBzJjx(f=^~{W=U#_p`w92NRF9D!qL%D!8x_4Br`2D8EB?L zaB5LmW^!t=ft)z6p{0Qt5Q9OKIIod~p^<@^k+G?zsb!QwilMfFCfE>RCC7q-oK%H? z(xjZsWUvW9w*>_Q4R%y8G*Zx2a5pp*HV_26Mwknt*fTF#4<^VV%;lVzlL>TnUS=Ya zpF@KUni!RkLxqu*fw_s1p8+V&#ni;e$gp>xka^sW`IVwGxZhL-&*tY`#$Z>@s3VYb zl0Emmb<#=U7U|_jG$(G|Y9(plvc2zyR`|P%1){Y_YZr$;wG(DgmvhoQ)Nrln`j&?6 z2Xyv6oEUBpGmA5;sk2t}@n zeL1~;`R{2b@96n%uPbVM5@;CNvan}juiPir2g=zd-&{-tf9Z-k&vo84|Em8K<4qod zGn<=^JpcB=+nnv~f%@E+r*9mo{~sp0N#F0Ko%>}G(X2gO*^={pnzqg4PuaV&d+)B} zm-apUF>Rmpo!c|tWt5+JZINMnZWd4Z1ydW|cr!gsHuL^7;;)-6GT68L{<7FI-)>{f z$K5QyLZ0{ht^Ljy{>%C8a;qo3&1cu-1UGj++{I;e`eDC?X30hU$^Z9PEVSA$6Pf&? Yi*L`9>cB-S?%!IT%wQ#Umi5vt08R^ + + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_ca + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedCAIdentities + + NSPinnedCAIdentitiesCount + 1 + NSIncludesSubdomains + + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_leaf + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedLeafIdentitiesCount + 2 + NSPinnedCAIdentities + + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_leaf_and_ca + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedLeafIdentitiesCount + 1 + NSPinnedCAIdentities + + NSPinnedCAIdentitiesCount + 2 + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_without_spki + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedCAIdentities + + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_with_empty_spki + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedLeafIdentitiesCount + 0 + NSPinnedCAIdentities + + + + + PlistDirectory + si-20-sectrust-policies-data + PlistFileName + NSPinnedDomains_with_invalid_spki + ExpectedProperties + + NSPinnedLeafIdentities + + NSPinnedLeafIdentitiesCount + 0 + NSPinnedCAIdentities + + NSPinnedCAIdentitiesCount + 0 + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_ca.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_ca.plist new file mode 100644 index 00000000..edac4c79 --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_ca.plist @@ -0,0 +1,24 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + NSIncludesSubdomains + + NSPinnedCAIdentities + + + SPKI-SHA256-BASE64 + r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E= + + + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf.plist new file mode 100644 index 00000000..4cab23ad --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf.plist @@ -0,0 +1,26 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + NSPinnedLeafIdentities + + + SPKI-SHA256-BASE64 + i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI= + + + SPKI-SHA256-BASE64 + i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI= + + + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf_and_ca.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf_and_ca.plist new file mode 100644 index 00000000..9a8c5551 --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_leaf_and_ca.plist @@ -0,0 +1,33 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + NSPinnedCAIdentities + + + SPKI-SHA256-BASE64 + 5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w= + + + SPKI-SHA256-BASE64 + r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E= + + + NSPinnedLeafIdentities + + + SPKI-SHA256-BASE64 + i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI= + + + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_empty_spki.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_empty_spki.plist new file mode 100644 index 00000000..a974f8be --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_empty_spki.plist @@ -0,0 +1,18 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + NSPinnedLeafIdentities + + + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_invalid_spki.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_invalid_spki.plist new file mode 100644 index 00000000..187c60d7 --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_with_invalid_spki.plist @@ -0,0 +1,21 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + NSPinnedCAIdentities + + r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E= + + NSPinnedLeafIdentities + i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI= + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_without_spki.plist b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_without_spki.plist new file mode 100644 index 00000000..81657f67 --- /dev/null +++ b/OSX/shared_regressions/si-20-sectrust-policies-data/NSPinnedDomains_without_spki.plist @@ -0,0 +1,15 @@ + + + + + NSAppTransportSecurity + + NSPinnedDomains + + example.org + + + + + + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/OCSP_TestCA.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/OCSP_TestCA.cer new file mode 100644 index 0000000000000000000000000000000000000000..9df4ea9715304aa6c8a8d55f69a75bb06bffc6c3 GIT binary patch literal 601 zcmXqLVhS~AV*I;+nTe5!iIZXZbZhaK8A*%=oNVk`Z64=rSr`o(dkwjPeCALVHesgF zU_)U8K@f+7hs!xJCo?U-C@(Y7P{=?4B*@Og>0DZnT2zvmmk(3O#lz)TP>_?V;F*`K zXDDkR4N}O>BNCjNTw0V_QmNpYm!6rInp%{Zmu{$NAPQ@|&o42M6X!KDFfcbXHZm|YFf@-6=QRd#4WZmY=iW#IVQ647F|u)hLzS74 zo!N-2B7j#fvw=QPCZhNeT=Po1EwJdUHME378|^cE+l4I?eCertDirectory si-20-sectrust-policies-data MajorTestName - iPhoneProfileSigning + iPhoneProfileApplicationSigning MinorTestName PositiveTest Policies @@ -2515,7 +2515,7 @@ Properties SecPolicyName - openmarket.ess.apple.com + init.ess.apple.com Leaf @@ -2529,7 +2529,7 @@ ChainLength 3 VerifyDate - 2019-02-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2537,7 +2537,7 @@ MajorTestName Systemwide-Baseline MinorTestName - IDS-IST + IDS-PublicTrust Policies PolicyIdentifier @@ -2545,21 +2545,21 @@ Properties SecPolicyName - static.ess.apple.com + pds-init.ess.apple.com Leaf - ids_ist_static + ids_init_public Intermediates - AppleISTCA2G1 + ApplePublicServerRSA12-G1 Anchors - GeoTrustGlobalCA + AAACertificateServices ExpectedResult 4 ChainLength 3 VerifyDate - 2017-12-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2589,7 +2589,7 @@ ChainLength 3 VerifyDate - 2019-02-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2635,7 +2635,7 @@ Properties SecPolicyName - openmarket.ess.apple.com + init.ess.apple.com SecPolicyPolicyName IDS @@ -2651,11 +2651,13 @@ ChainLength 3 VerifyDate - 2019-02-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory si-20-sectrust-policies-data + BridgeOSDisable + MajorTestName Systemwide-PolicyName MinorTestName @@ -2667,21 +2669,21 @@ Properties SecPolicyName - static.ess.apple.com + pds-init.ess.apple.com SecPolicyPolicyName IDS Leaf - ids_ist_static + ids_init_public Intermediates - AppleISTCA2G1 + ApplePublicServerRSA12-G1 Anchors - GeoTrustGlobalCA + AAACertificateServices ExpectedResult 5 VerifyDate - 2017-02-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2713,7 +2715,7 @@ ChainLength 3 VerifyDate - 2019-02-08T21:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2791,19 +2793,19 @@ Properties SecPolicyName - static.ess.apple.com + init.ess.apple.com Leaf - ids_ist_static + ids_test Intermediates - AppleISTCA2G1 + TestAppleServerAuthentication Anchors - GeoTrustGlobalCA + TestAppleRootCA ExpectedResult 4 VerifyDate - 2017-04-08T20:00:00Z + 2020-09-15T00:00:00Z CertDirectory @@ -2858,6 +2860,38 @@ VerifyDate 2017-02-20T21:00:00Z + + CertDirectory + si-20-sectrust-policies-data + BridgeOSDisable + + MajorTestName + Systemwide-Both + MinorTestName + Precedence + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + identity.ess.apple.com + SecPolicyPolicyName + APN + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + VerifyDate + 2020-09-15T00:00:00Z + CertDirectory si-20-sectrust-policies-data @@ -3588,5 +3622,460 @@ ChainLength 3 + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + iPhoneProfileApplicationSigning + MinorTestName + PositiveTest + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.55 + + Leaf + test_iphone_distribution + Intermediates + TestAppleWWDR-G3 + Anchors + TestAppleRootCA + VerifyDate + 2020-03-01T20:00:00Z + ExpectedResult + 4 + ChainLength + 3 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + OCSP + MinorTestName + PositiveTest + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.66 + + Leaf + ocsp_responder + Anchors + OCSP_TestCA + VerifyDate + 2020-08-01T20:00:00Z + ExpectedResult + 4 + ChainLength + 2 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + OCSP + MinorTestName + NegativeTest-SubCA + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.66 + + Leaf + ocsp_subca + Anchors + OCSP_TestCA + VerifyDate + 2020-08-01T20:00:00Z + ExpectedResult + 5 + ChainLength + 2 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + OCSP + MinorTestName + NegativeTest-MissingEKU + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.66 + + Leaf + ocsp_missing_eku + Anchors + OCSP_TestCA + VerifyDate + 2020-08-01T20:00:00Z + ExpectedResult + 5 + ChainLength + 2 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + OCSP + MinorTestName + NegativeTest-MissingKU + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.66 + + Leaf + ocsp_missing_ku + Anchors + OCSP_TestCA + VerifyDate + 2020-08-01T20:00:00Z + ExpectedResult + 5 + ChainLength + 2 + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckLeafSPKISHA256 + MinorTestName + leaf-good + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + LeafSPKISHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + +GxzfmXKLWfWePjBrbCey6zjhsMU/KtGFQExWAnFJeQ= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 4 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckLeafSPKISHA256 + MinorTestName + leaf-empty + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + LeafSPKISHA256 + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckLeafSPKISHA256 + MinorTestName + leaf-bad + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + LeafSPKISHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + intermediate-good + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + CAspkiSHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + Yc/8PBtv5TPVDELtY0SUFd5zObsSVVzm7WbLz5eIpQM= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 4 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + intermediate-empty + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + CAspkiSHA256 + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + intermediate-bad + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + CAspkiSHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + root-good + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + CAspkiSHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + pmuYhKz98VG4gaGpUvi3y7CEl5+yJNGQ8/ARWg4FVnw= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 4 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + leaf-good-intermediate-good-root-good + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + LeafSPKISHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + +GxzfmXKLWfWePjBrbCey6zjhsMU/KtGFQExWAnFJeQ= + + CAspkiSHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + Yc/8PBtv5TPVDELtY0SUFd5zObsSVVzm7WbLz5eIpQM= + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + pmuYhKz98VG4gaGpUvi3y7CEl5+yJNGQ8/ARWg4FVnw= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 4 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + + + CertDirectory + si-20-sectrust-policies-data + MajorTestName + kSecPolicyCheckCAspkiSHA256 + MinorTestName + leaf-bad-intermediate-good-root-good + Policies + + PolicyIdentifier + 1.2.840.113635.100.1.3 + Properties + + SecPolicyName + init.ess.apple.com + SecPolicyClient + + LeafSPKISHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + + CAspkiSHA256 + + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + Yc/8PBtv5TPVDELtY0SUFd5zObsSVVzm7WbLz5eIpQM= + QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= + pmuYhKz98VG4gaGpUvi3y7CEl5+yJNGQ8/ARWg4FVnw= + + + + Leaf + ids_test + Intermediates + TestAppleServerAuthentication + Anchors + TestAppleRootCA + ExpectedResult + 5 + ChainLength + 3 + VerifyDate + 2020-09-15T00:00:00Z + diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleWWDR-G3.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleWWDR-G3.cer new file mode 100644 index 0000000000000000000000000000000000000000..212690f3930860bc66e4e84d957c10700339e40f GIT binary patch literal 1141 zcmXqLVktCeVvbzE%*4pV#KC;}`nAw`+QtUFY@Awc9&O)w85y}*84S`5xeYkkm_u3E zgqcEv4TTK^K^!g~F2{m`oKywRyktE?H3JopAUBUJM9?|4s3bEjGdZy&Ge1wkv9u&3 zzbLb$(oot!5~PlqM<^tI4D2AM8Vn7Ku(<3$iTqJz{0@5)X>B@N}Sgi#5FSj zgD8ViA{+vBDmM?4yRo5*ffK|wYlubR`9(P?<(Vm|3NEQ-sX6%tsYMDwsX1Ur7AxRz zvq2N15^|6*vNA9?G4eA2#krW87#SIEM4K6vRNhW>6o>%m^G;_;*Y#*y~TuWF~^-YZs#R;^qeOBD}8&LiJ6gsad8u)ATUID4TOLpE-TE) z_@9NtfDK47F)|p)gT$0sBn-qFL?U-+PqC8T^^sxSyMQ2NL0hJlZg51r=BE}-(&Aj-TMy|7M z>Pn^t-F`(D6-O0Q13r*6Kgg>rz#PP8Ai%~2&Ns;^Y)p(SOu(#znv;OZhLJ&S!ST|Y z7ru39o!XFL->~$%uSNoQ$kwNEFa0kwMm4`qJi_SIxpRsC^9#!zzWi1#oq6^mn~ur- z)f`j*9_752+ZocO%h-QXGUdo&`<99J(=E@`*uQ9RObs%RQ&@1fWW($kQ`UYzx~oTewgQ(_nh}VzyG|K zGeA#Y2lOmwf>dBhWh^uN$?(z=hRrDukl^lMDb;K% zYQ|dZuTsTJv5+KDyj+ZhN!7_xH5MA?j|KQ+I3M%Cf^nP$=9`?EEatTH28EbAyGUm- z1BCJNSfyGa7vkoCVe+K1kgZ{0(E>|80LyVc9|ztzzMVArz!S%3OrT4{9f19`3>%e% z@Q^Fy8m^QexI&XAu2`9Xy8>sEgE`ASL8uVMNfV?BjjvpiKyc&K$|MyR=L4UWd@!r# z|COkR7thTNOo7bwuoVRKFcZr zS=n#E;IMykRXf3d82G_;7V}gQ_-mo!^~y)t=bpyo+U7qHR3A?1QeV1}zI5p8i7w~y z4L^9xMuKBMc~kjeQ1i>tL{6C@+K<*|H0;^@ZA>rYRlhDM3nLLa|t?(oDz1zTGzs2T2l&4x6G#_@1QRP261hgMR1lal7E2UHbnWqzdWSC)uN*t>lwWo|j$pW~<74>y`xjj+rw}Y; z#N+9^tp z`r7VEO`rDeyzec$t!Jbf7n z_Ce~V3W;_0nLjyjR^y*8fRdqbHuV(mVdG%O_`ezgE7vp& zl56Wv&X2k|eEh`LuB>}K)7aXzZ?VB32*Etdok4>-=^0H`l3t@be&-JFn|&)lDKk2K z)K@Fu*ddP4P)LTvI*qCDW=D&ca6sa}-53h*e)o2lHClJN)g=d#yH(fOXmi91-uTSC zAi^(f@Le4GrLf#hMmgV~UzHP~tFEzoDcYqEK2$tzzkaQF<=Rr6;Q7@W zd))6t;#c6Is)E%hE z_a5WbGVP5icFLB-o|~Q7&PSTKee;u7m(iR3IdaL#LPlC|Jzel&`r{l6uY;}GX9-WDI5ovrvbhrw0!9QUeBO5VVuE2VLDZLj}ZP*1MtBk8{e0BSwIgekF-R z4~wE;Ny{9hGdzALe4+%1kkB2xJ?%O6@B4{1_fqffx`j{5p zJHu~_6an9V*fcjvDk|yDcvwI|6d&D&Fw?!I0$%+<-!0l~9N2%7yQKMxI^M3QBU~$- zFPi-h_5MJATzshk;t?U1`tK_Ym422jps5vlf+d3z)`JR>rPuPy!x&EVp`i-Veux~g z5UGRXt@r=x+#u_8l;DZqG$kll>By6WEhMnq(nbjnV_yOT0RRD`f&o1+f&n>`K>{!e zW(EUQ9T5ayFkO?a0vD5e0y6~?X>MtBlePkR6m$ju+rCQ4J5+bBPGGXpM{v$H+mk~B zH-D>xA_f$akWc@IpY>_}hZLFwc@ZlVcmE)Ez zX={x7%vT^am@$Je^J3`GtG?s=Xtcc${M}1h2T_qJrf-Bo*sk(A(xSAst1=|x{a21t z-BW#T$+> z8>Hj%zCosDp2qbD=$jKX2318jh-FVq5#R#X=))UL%`sV3kfUlqF|Cq@{!_)cUIL>6 DoWw6x delta 671 zcmV;Q0$}}%3Hk^ZFoFbjFoFYKpaTK{0s;sm9~^@8B|@~37l$x0I50RcH!v|UH8VF_ z7Y#8vFgY+bFflMSGdEf=S1}$i90mhb1Op5eaB^>EX>4VY%VvMt?#@pNG4*O}*x30V zO@%lYLPfgrj26P|DTIi^!bQt@_J4_GJ(%t1A*icN;&psmCIG}tf#m;h(ir^D#TiRl;@q$2&X+YbmcokRF@EM+^zy2b`!9KA!$5=Me^>9gOOkbJY`O zQ4Kw7XER#kXbfQm4QFf6HxanVi%N?zL|FUg@r`SBLva;4X?GP96N_;S|sWrPp5 zBSB5$-N0M7_#E;dwO!ErxqS^Z#9=~?)a^{9gPe`J<4Hva^G>`{LGxJFJ zI|m0S1f>=i!|e$cghB85o!wniv=un3`Hf0l9`qT!Y4`babz# zfjY#!3Rv80rQn-cTnzMF|nO9fh>s6$0EieVw@k6EIX-R_SJ)T z?aWo}Yrjm6AlS1*G^$(Ib?rqPmxs@eRccJ*N U$-ECCN1_?I8(y_vjB2(60CAhc0RR91 literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_missing_ku.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/ocsp_missing_ku.cer new file mode 100644 index 0000000000000000000000000000000000000000..edadfed51a8c6aeae2826a6b8b19b7550b7d08b6 GIT binary patch literal 669 zcmXqLVw!2t#ALsKnTe5!Nm%vs|J`LSE?tKXeLKecK3H-eqmls^8;4e#$2nUTW+sEi zUPEpJPB!LH7B*p~&|pJh13?gngNMsGF()%EzbG#=(NM@h03^uH!|7aFkXlrdnU@b! z$i>6uSWu9Ys^FQItY;`|APrK;%_9<=np|3xSyHLsnwOrLmzr9XnU`*;Xdn-gX6BLb zcMc9v2udw3$j?hjEm8 z8dL40vu{lHKVkn^*SOH}o7AGsf_90SH_yu}#LsZwaQXJPE#V7<^O7PH;@19>l5(B5 zEOYkaQiEax9-uR1g&7(DvoIMj81R93{2(4M1{s-vRs;E}EIgoy)n;R4Wo2jPG>`=e z^0A1qh|JWzKc8izu433B%gj9?0t^kySKS6jgsd`)gn?LtNaWUyd7ZP@)JY2KlxEn@ zXB7=$6+=!W%pME|u1tyy2boecMcr69&A(ed%U>E99LxLh%jakI-%=(m?)On(dcdTh lbx2iep(j^W`U&TPrI8ss>6uSWu9Ys^FQItY;`|APrK;%_9<=np|3xSyHLsnwOrLmzr9XnU`*;Xdn-gX6BLb zcMc9v2udw3$j?hjEm8 zfg;4cQdrz;r4R-Tp%jBi17S9HaCkB?LIakWk)7FzfyMXF+wdE&G><)1Z4X>koE6XD zlj8Isc-^~s_TGE6tADE)2hVpho_R#d_yp&fzJQX0cC(!3<-7S6n>_hgRrk;#adD|Z zu>lXz1+v17jQ?4f3>XafKs6uSWu9Ys^FQItY;`|APrK;%_9<=np|3xSyHLsnwOrLmzr9XnU`*;Xdn-gX6BLb zcMc9v2udw3$j?hjEm8 zfg;4cQdrz;r4U@2<)i>XpKG^8re_4HT zg+ZACKhOoT!i!m9fO9GYX(=8M|;#&ni0UcSU091XI{ED{D{4I+_SH|BNDUQ;J2tW%m{JD*iF zgjEbVi7wr{Tq`Si5wflIFGB j!WUnE9C~|VD^uvB>;LvkRR}u2y0xtDVebE)+bdiFdOXN5 literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/test_iPh0ne_distribution.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/test_iPh0ne_distribution.cer new file mode 100644 index 0000000000000000000000000000000000000000..1196715317fc1d169b6ab1ce2b85758ce9ad73d9 GIT binary patch literal 1494 zcmZ`(dr(wW9Nu&H;j%1{v&usP53rc5>~iidB&;EU45+9e$jJCeFL$r))n#|P_bv;L z8mtpDW}-tS7UF1RiRd)2N`tAGuN=`-G9=1jN&+3t%+%17?OYMknfl|*obR09_j{e+ zcaTTki9E7HJEa65h?ml8b?$2G*YMs4F{^ikXLO?gg`ci!X4PK-0Qk!#$VK`iKZUeV zrqB?D1*8Uz6@f~vN_RSK44h@B4I>u*Y9iZ2W}*zyLaLrNY_ZV6*(`3>!oW8B8;y9BF)V})`Q84_Sb$VeKEWYSd9xClcNhU7DdDr?CJ zC{&^HtC_Un{k!oN0Mx2i=cnXnC7bdRi^wEo8crgf&9ge}I5x`*99!%XqnhDp?oba4 zTsDES!vzd4j8y0Uf-i_7hf5CmKicyhLLLzPd=G(KBK3eE2|ia59snck8(<@O0mjOI5LRmwcyOlL}ofcrUI0Nt1cskF967MF)6yGXuJ~OIayfdQB(V zj}_jk9%bg29$yEpAHJ}>Y;OCtu)FGCHYJ9ZHBMiy9P&;#9@M}! zVF7im1N~=L?iswVd-!^uHm_bN^1T=Vv z6yzb2kQ%o(LIZ$LMj#2AD54lyC=pEG$$m`c&2#0ixLd9gL4`vaZvHLB*E>raBrFn7KZa7^C%Hi z8J-axH1GT`o_LN-`e8aE@l!%EQ7H3(5DYYU1wB&@ZIJ^EC8+YmNC1LBm96SZFCKc9 zveOK7*r8x$c_`*NJo^kRE{Bx896BjZz&oCIl`uS{Xqs{2;S@P5FozMB9f}2E#S~-t z@%Yw4aTX{rTnQ%FEs%EDE$pzkFv-O;@h=2&IxtrZhAl_qV^KgSN6`X{Lt&o+Q^ME< z-hh%vivYp#VwZT_U$@)+TvPw`!cZgfP4J;$u|u)q!>W;L#EVplBE<7RS+H!}D=W8L zdBfH<`KNWiw|QV8*%P);jsnH&Adx1M5@RZmMxlE88_^a8kUbp}{3pHmMPYdXNpoRc z-)w}s(P+EnzNqKw9^&_V3dhB*x%hmVo8vZgaPLOWY@2qnzJ~j4!_UfS{Y_e1-Mqc)z0#cQqDL8r`(}fG E0O)ZG>i_@% literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-20-sectrust-policies-data/test_iphone_distribution.cer b/OSX/shared_regressions/si-20-sectrust-policies-data/test_iphone_distribution.cer new file mode 100644 index 0000000000000000000000000000000000000000..1196715317fc1d169b6ab1ce2b85758ce9ad73d9 GIT binary patch literal 1494 zcmZ`(dr(wW9Nu&H;j%1{v&usP53rc5>~iidB&;EU45+9e$jJCeFL$r))n#|P_bv;L z8mtpDW}-tS7UF1RiRd)2N`tAGuN=`-G9=1jN&+3t%+%17?OYMknfl|*obR09_j{e+ zcaTTki9E7HJEa65h?ml8b?$2G*YMs4F{^ikXLO?gg`ci!X4PK-0Qk!#$VK`iKZUeV zrqB?D1*8Uz6@f~vN_RSK44h@B4I>u*Y9iZ2W}*zyLaLrNY_ZV6*(`3>!oW8B8;y9BF)V})`Q84_Sb$VeKEWYSd9xClcNhU7DdDr?CJ zC{&^HtC_Un{k!oN0Mx2i=cnXnC7bdRi^wEo8crgf&9ge}I5x`*99!%XqnhDp?oba4 zTsDES!vzd4j8y0Uf-i_7hf5CmKicyhLLLzPd=G(KBK3eE2|ia59snck8(<@O0mjOI5LRmwcyOlL}ofcrUI0Nt1cskF967MF)6yGXuJ~OIayfdQB(V zj}_jk9%bg29$yEpAHJ}>Y;OCtu)FGCHYJ9ZHBMiy9P&;#9@M}! zVF7im1N~=L?iswVd-!^uHm_bN^1T=Vv z6yzb2kQ%o(LIZ$LMj#2AD54lyC=pEG$$m`c&2#0ixLd9gL4`vaZvHLB*E>raBrFn7KZa7^C%Hi z8J-axH1GT`o_LN-`e8aE@l!%EQ7H3(5DYYU1wB&@ZIJ^EC8+YmNC1LBm96SZFCKc9 zveOK7*r8x$c_`*NJo^kRE{Bx896BjZz&oCIl`uS{Xqs{2;S@P5FozMB9f}2E#S~-t z@%Yw4aTX{rTnQ%FEs%EDE$pzkFv-O;@h=2&IxtrZhAl_qV^KgSN6`X{Lt&o+Q^ME< z-hh%vivYp#VwZT_U$@)+TvPw`!cZgfP4J;$u|u)q!>W;L#EVplBE<7RS+H!}D=W8L zdBfH<`KNWiw|QV8*%P);jsnH&Adx1M5@RZmMxlE88_^a8kUbp}{3pHmMPYdXNpoRc z-)w}s(P+EnzNqKw9^&_V3dhB*x%hmVo8vZgaPLOWY@2qnzJ~j4!_UfS{Y_e1-Mqc)z0#cQqDL8r`(}fG E0O)ZG>i_@% literal 0 HcmV?d00001 diff --git a/OSX/shared_regressions/si-44-seckey-aks.m b/OSX/shared_regressions/si-44-seckey-aks.m index e276aeb7..cd8a2a46 100644 --- a/OSX/shared_regressions/si-44-seckey-aks.m +++ b/OSX/shared_regressions/si-44-seckey-aks.m @@ -8,17 +8,13 @@ #import #import #import -#if !TARGET_OS_OSX #import "MobileGestalt.h" -#else -#import -#endif #import "shared_regressions.h" -static id generateKey(id keyType, CFStringRef protection, BOOL noACL) { +static id generateKey(id keyType, CFStringRef protection, BOOL withACL) { id accessControl; - if (noACL) { + if (!withACL) { accessControl = CFBridgingRelease(SecAccessControlCreate(kCFAllocatorDefault, NULL)); SecAccessControlSetProtection((__bridge SecAccessControlRef)accessControl, protection, NULL); } else { @@ -41,9 +37,9 @@ static void secKeySepTest(BOOL testPKA) { } else { keyTypes = @[(id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeyTypeSecureEnclaveAttestation]; } - BOOL noACL = YES; + BOOL withACL = NO; for (id keyType in keyTypes) { - id privateKey = generateKey((id)keyType, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, (noACL = !noACL)); + id privateKey = generateKey((id)keyType, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, (withACL = !withACL)); ok(privateKey, "failed to create key '%@'", keyType); id publicKey = (__bridge_transfer id)SecKeyCopyPublicKey((SecKeyRef)privateKey); @@ -92,16 +88,13 @@ static void secKeySepTest(BOOL testPKA) { } } -static void attestationTest(CFStringRef protection, BOOL noACL) { +static void attestationTest(CFStringRef protection, BOOL withACL) { NSError *error; - id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom, protection, noACL); - id uik = generateKey((id)kSecAttrKeyTypeSecureEnclaveAttestation, protection, noACL); + id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom, protection, withACL); + id uik = generateKey((id)kSecAttrKeyTypeSecureEnclaveAttestation, protection, withACL); id sik = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeSIK, (void *)&error)); ok(sik != nil, "get SIK key: %@", error); - id pubSIK = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sik)); - ok(pubSIK != nil, "get SIK pubkey"); - error = nil; NSData *attSIKPlain = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)uik, (void *)&error)); ok(attSIKPlain != nil, "SIK attesting UIK, no nonce: %@", error); @@ -120,70 +113,82 @@ static void attestationTest(CFStringRef protection, BOOL noACL) { ok(SecKeySetParameter((__bridge SecKeyRef)uik, kSecKeyParameterSETokenAttestationNonce, (__bridge CFPropertyListRef)nonce, (void *)&error), "Set nonce to UIK: %@", error); NSData *attUIKNonce = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)uik, (__bridge SecKeyRef)privKey, (void *)&error)); ok(attUIKNonce != nil, "SIK attesting UIK, with nonce: %@", error); +} + +static void sysKeyAttestationTest(CFStringRef protection, BOOL withACL, const char *name, SecKeyAttestationKeyType committed, SecKeyAttestationKeyType proposed, BOOL canAttest) { + NSError *error; + id privKey = generateKey((id)kSecAttrKeyTypeECSECPrimeRandom, protection, withACL); + id sik = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeSIK, (void *)&error)); + ok(sik != nil, "get SIK key: %@", error); + + id pubSIK = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sik)); + ok(pubSIK != nil, "get SIK pubkey"); + + id sysKeyC = CFBridgingRelease(SecKeyCopyAttestationKey(committed, (void *)&error)); + if (sysKeyC == nil) { + diag("skipping attestation test, platform does not support key %s-committed", name); + return; + } error = nil; - id sysUikC = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeUIKCommitted, (void *)&error)); - if (sysUikC == nil) { - // Platform does not support system UIK, so just fake test rounds to avoid testplan counting failures. - for (int i = 0; i < 19; i++) { - ok(true); - } - } else { - ok(sysUikC != nil, "get UIK-committed key, error: %@", error); - error = nil; - id sysUikP = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeUIKProposed, (void *)&error)); - ok(sysUikP != nil, "get UIK-proposed key: %@", error); + id sysKeyP = CFBridgingRelease(SecKeyCopyAttestationKey(proposed, (void *)&error)); + ok(sysKeyP != nil, "unable to get proposed key, but successfully got committed key"); + if (canAttest) { error = nil; - NSData *attUIKC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKC != nil, "Sys-UIK-committed attesting privKey: %@", error); + NSData *attSysKeyC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyC, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyC != nil, "%s-committed attesting privKey: %@", name, error); error = nil; - NSData *attUIKP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKP != nil, "Sys-UIK-proposed attesting privKey: %@", error); + NSData *attSysKeyP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyP, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyP != nil, "%s-proposed attesting privKey: %@", name, error); + } - id pubUIKP = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikP)); - ok(pubUIKP != nil, "Sys-UIK-proposed copy public key"); - id pubUIKC = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikC)); - ok(pubUIKC != nil, "Sys-UIK-proposed copy public key"); + id pubSysKeyP = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysKeyP)); + ok(pubSysKeyP != nil, "%s-proposed copy public key", name); + id pubSysKeyC = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysKeyC)); + ok(pubSysKeyC != nil, "%s-committed copy public key", name); - BOOL res = SecKeyControlLifetime((__bridge SecKeyRef)sysUikC, kSecKeyControlLifetimeTypeBump, (void *)&error); - ok(res, "bumping sys-uik: %@", error); + BOOL res = SecKeyControlLifetime((__bridge SecKeyRef)sysKeyC, kSecKeyControlLifetimeTypeBump, (void *)&error); + ok(res, "bumping %s: %@", name, error); + if (canAttest) { error = nil; - NSData *attUIKCN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKCN != nil, "Sys-UIK-committed attesting privKey: %@", error); + NSData *attSysKeyCN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyC, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyCN != nil, "%s-committed attesting privKey: %@", name, error); error = nil; - NSData *attUIKPN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKPN != nil, "Sys-UIK-proposed attesting privKey: %@", error); + NSData *attSysKeyPN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyP, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyPN != nil, "%s-proposed attesting privKey: %@", name, error); + } - id pubUIKPN = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikP)); - ok(pubUIKPN != nil, "Sys-UIK-proposed copy public key"); - ok(![pubUIKPN isEqual:pubUIKC], "Sys-UIK proposed and committed differ after bump"); + id pubSysKeyPN = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysKeyP)); + ok(pubSysKeyPN != nil, "%s-proposed copy public key", name); + ok(![pubSysKeyPN isEqual:pubSysKeyC], "%s proposed and committed differ after bump", name); - res = SecKeyControlLifetime((__bridge SecKeyRef)sysUikP, kSecKeyControlLifetimeTypeCommit, (void *)&error); - ok(res, "committing sys-uik: %@", error); + res = SecKeyControlLifetime((__bridge SecKeyRef)sysKeyP, kSecKeyControlLifetimeTypeCommit, (void *)&error); + ok(res, "committing %s: %@", name, error); + if (canAttest) { error = nil; - NSData *attUIKCNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKCNN != nil, "Sys-UIK-committed attesting privKey: %@", error); + NSData *attSysKeyCNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyC, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyCNN != nil, "%s-committed attesting privKey: %@", name, error); error = nil; - NSData *attUIKPNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error)); - ok(attUIKPNN != nil, "Sys-UIK-proposed attesting privKey: %@", error); + NSData *attSysKeyPNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyP, (__bridge SecKeyRef)privKey, (void *)&error)); + ok(attSysKeyPNN != nil, "%s-proposed attesting privKey: %@", name, error); + } - id pubUIKCN = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysUikC)); - ok(pubUIKCN != nil, "Sys-UIK-committed copy public key"); - ok([pubUIKPN isEqual:pubUIKCN], "Sys-UIK proposed and committed same after commit"); + id pubSysKeyCN = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)sysKeyC)); + ok(pubSysKeyCN != nil, "%s-committed copy public key", name); + ok([pubSysKeyPN isEqual:pubSysKeyCN], "%s proposed and committed same after commit", name); - // Attest system-UIK with SIK - NSData *attSIKUIKP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysUikP, (void *)&error)); - ok(attSIKUIKP != nil, "SIK attesting Sys-UIK-proposed, error: %@", error); + // Attest system key with SIK + NSData *attSIKSysKeyP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysKeyP, (void *)&error)); + ok(attSIKSysKeyP != nil, "SIK attesting %s-proposed, error: %@", name, error); - NSData *attSIKUIKC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysUikC, (void *)&error)); - ok(attSIKUIKC != nil, "SIK attesting Sys-UIK-committed, error: %@", error); - } + NSData *attSIKSysKeyC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysKeyC, (void *)&error)); + ok(attSIKSysKeyC != nil, "SIK attesting %s-committed, error: %@", name, error); } static void keyFromBlobTest(void) { @@ -494,35 +499,44 @@ static void secAccessControlDescriptionTest(void) { int si_44_seckey_aks(int argc, char *const *argv) { @autoreleasepool { - BOOL testPKA = YES; -#if !TARGET_OS_OSX - NSNumber *hasPKA = (__bridge_transfer id)MGCopyAnswer(kMGQHasPKA, NULL); - if(![hasPKA isKindOfClass:NSNumber.class] || ![hasPKA boolValue]) { - testPKA = NO; - } -#else - if (remote_device_copy_unique_of_type(REMOTE_DEVICE_TYPE_EOS) == nil && remote_device_copy_unique_of_type(REMOTE_DEVICE_TYPE_BRIDGE_COPROC) == nil) { + NSNumber *hasSEP = CFBridgingRelease(MGCopyAnswer(kMGQHasSEP, NULL)); + if (!hasSEP.boolValue) { // macOS without SEP cannot run attestations at all. plan_tests(1); ok(true); return 0; } - testPKA = NO; -#endif - plan_tests(testPKA ? 119 : 104); + NSNumber *hasPKA = CFBridgingRelease(MGCopyAnswer(kMGQHasPKA, NULL)); + plan_tests(hasPKA.boolValue ? 207 : 113); secAccessControlDescriptionTest(); - secKeySepTest(testPKA); - attestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, NO); - attestationTest(kSecAttrAccessibleUntilReboot, YES); + secKeySepTest(hasPKA.boolValue); + + attestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, YES); + attestationTest(kSecAttrAccessibleUntilReboot, NO); + + sysKeyAttestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, YES, "SysUIK", kSecKeyAttestationKeyTypeUIKCommitted, kSecKeyAttestationKeyTypeUIKProposed, YES); + sysKeyAttestationTest(kSecAttrAccessibleUntilReboot, NO, "SysUIK", kSecKeyAttestationKeyTypeUIKCommitted, kSecKeyAttestationKeyTypeUIKProposed, YES); + + // OIK is too weird to be usable directly, just skip is testing for now. +#if 0 + sysKeyAttestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, YES, "OIK", kSecKeyAttestationKeyTypeOIKCommitted, kSecKeyAttestationKeyTypeOIKProposed, NO); + sysKeyAttestationTest(kSecAttrAccessibleUntilReboot, NO, "OIK", kSecKeyAttestationKeyTypeOIKCommitted, kSecKeyAttestationKeyTypeOIKProposed, NO); +#endif + + sysKeyAttestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, YES, "DAK", kSecKeyAttestationKeyTypeDAKCommitted, kSecKeyAttestationKeyTypeDAKProposed, YES); + sysKeyAttestationTest(kSecAttrAccessibleUntilReboot, NO, "DAK", kSecKeyAttestationKeyTypeDAKCommitted, kSecKeyAttestationKeyTypeDAKProposed, YES); + keyFromBlobTest(); keychainTest(); - // 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); + if (hasPKA.boolValue) { + // 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); + } return 0; } diff --git a/OSX/shared_regressions/si-44-seckey-proxy.m b/OSX/shared_regressions/si-44-seckey-proxy.m index c0aa33aa..648dfeae 100644 --- a/OSX/shared_regressions/si-44-seckey-proxy.m +++ b/OSX/shared_regressions/si-44-seckey-proxy.m @@ -54,11 +54,12 @@ static void test_key_proxy_connect() { // Create new proxy and invalidate it (idempotent, so we try invalidate multiple times). keyProxy = [[SecKeyProxy alloc] initWithKey:(SecKeyRef)serverKey]; + endpoint = keyProxy.endpoint; [keyProxy invalidate]; [keyProxy invalidate]; - secondKey = [SecKeyProxy createKeyFromEndpoint:keyProxy.endpoint error:&error]; + secondKey = [SecKeyProxy createKeyFromEndpoint:endpoint error:&error]; is(secondKey, NULL, "connection to invalidated proxy should be refused."); - + // Invalidate connected proxy, make sure that remote key does not work as expected. keyProxy = [[SecKeyProxy alloc] initWithKey:(SecKeyRef)serverKey]; secondKey = [SecKeyProxy createKeyFromEndpoint:keyProxy.endpoint error:&error]; diff --git a/OSX/shared_regressions/si-88-sectrust-valid.m b/OSX/shared_regressions/si-88-sectrust-valid.m deleted file mode 100644 index 28b593aa..00000000 --- a/OSX/shared_regressions/si-88-sectrust-valid.m +++ /dev/null @@ -1,308 +0,0 @@ -/* - * si-88-sectrust-valid.m - * Security - * - * Copyright (c) 2017-2019 Apple Inc. All Rights Reserved. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "shared_regressions.h" - -enum { - kBasicPolicy = 0, - kSSLServerPolicy = 1, -}; - -/* number of tests in the test_valid_trust function */ -#define TVT_COUNT 8 - -static void test_valid_trust(SecCertificateRef leaf, SecCertificateRef ca, SecCertificateRef subca, - CFArrayRef anchors, CFDateRef date, CFIndex policyID, - SecTrustResultType expected, const char *test_name) -{ - CFArrayRef policies=NULL; - SecPolicyRef policy=NULL; - SecTrustRef trust=NULL; - SecTrustResultType trustResult; - CFMutableArrayRef certs=NULL; - - printf("Starting %s\n", test_name); - isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array"); - if (certs) { - if (leaf) { - CFArrayAppendValue(certs, leaf); - } - if (ca) { - CFArrayAppendValue(certs, ca); - } - if (subca) { - CFArrayAppendValue(certs, subca); - } - } - - if (policyID == kSSLServerPolicy) { - isnt(policy = SecPolicyCreateSSL(true, NULL), NULL, "create ssl policy"); - } else { - isnt(policy = SecPolicyCreateBasicX509(), NULL, "create basic policy"); - } - isnt(policies = CFArrayCreate(kCFAllocatorDefault, (const void **)&policy, 1, &kCFTypeArrayCallBacks), NULL, "create policies"); - ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust"); - - assert(trust); // silence analyzer - ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); - ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - ok(trustResult == expected, "trustResult %d expected (got %d)", - (int)expected, (int)trustResult); - - CFReleaseSafe(certs); - CFReleaseSafe(policy); - CFReleaseSafe(policies); - CFReleaseSafe(trust); -} - -#import -SecCertificateRef SecCertificateCreateWithPEM(CFAllocatorRef allocator, CFDataRef pem_certificate); - -static SecCertificateRef SecCertificateCreateFromResource(NSString *name) -{ - NSString *resources = @"si-88-sectrust-valid-data"; - NSString *extension = @"pem"; - - NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:extension subdirectory:resources]; - if (!url) { - printf("No URL for resource \"%s.pem\"\n", [name UTF8String]); - return NULL; - } - - NSData *certData = [NSData dataWithContentsOfURL:url]; - if (!certData) { - printf("No cert data for resource \"%s.pem\"\n", [name UTF8String]); - return NULL; - } - - return SecCertificateCreateWithPEM(kCFAllocatorDefault, (__bridge CFDataRef)certData); -} - -/* number of tests in date_constraints_tests function, plus calls to test_valid_trust */ -#define DC_COUNT (12+(TVT_COUNT*6)) - -static void date_constraints_tests() -{ - SecCertificateRef ca_na=NULL, ca_nb=NULL, root=NULL; - SecCertificateRef leaf_na_ok1=NULL, leaf_na_ok2=NULL; - SecCertificateRef leaf_nb_ok1=NULL, leaf_nb_ok2=NULL, leaf_nb_revoked1=NULL; - - isnt(ca_na = SecCertificateCreateFromResource(@"ca-na"), NULL, "create ca-na cert"); - isnt(ca_nb = SecCertificateCreateFromResource(@"ca-nb"), NULL, "create ca-nb cert"); - isnt(root = SecCertificateCreateFromResource(@"root"), NULL, "create root cert"); - isnt(leaf_na_ok1 = SecCertificateCreateFromResource(@"leaf-na-ok1"), NULL, "create leaf-na-ok1 cert"); - isnt(leaf_na_ok2 = SecCertificateCreateFromResource(@"leaf-na-ok2"), NULL, "create leaf-na-ok2 cert"); - isnt(leaf_nb_ok1 = SecCertificateCreateFromResource(@"leaf-nb-ok1"), NULL, "create leaf-nb-ok1 cert"); - isnt(leaf_nb_ok2 = SecCertificateCreateFromResource(@"leaf-nb-ok2"), NULL, "create leaf-nb-ok2 cert"); - isnt(leaf_nb_revoked1 = SecCertificateCreateFromResource(@"leaf-nb-revoked1"), NULL, "create leaf-nb-revoked1 cert"); - - CFMutableArrayRef anchors=NULL; - isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array"); - if (anchors && root) { - CFArrayAppendValue(anchors, root); - } - CFCalendarRef cal = NULL; - CFAbsoluteTime at; - CFDateRef date_20180102 = NULL; // a date when our test certs would all be valid, in the absence of Valid db info - - isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar"); - ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2018, 1, 2), "create verify absolute time 20180102"); - isnt(date_20180102 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20180102"); - - /* Case 0: leaf_na_ok1 (not revoked) */ - /* -- OK: cert issued 2017-10-20, before the CA not-after date of 2017-10-21 */ - /* test cert has no SCT, but is expected to be OK since we now only apply the CT restriction for SSL. */ - test_valid_trust(leaf_na_ok1, ca_na, NULL, anchors, date_20180102, - kBasicPolicy, kSecTrustResultUnspecified, - "leaf_na_ok1 basic"); - - /* Case 1: leaf_na_ok1 (not revoked) */ - /* -- BAD: since a not-after date now requires CT (for SSL) and the test cert has no SCT, this is fatal. */ - test_valid_trust(leaf_na_ok1, ca_na, NULL, anchors, date_20180102, - kSSLServerPolicy, kSecTrustResultFatalTrustFailure, - "leaf_na_ok1 ssl"); - - /* Case 2: leaf_na_ok2 (revoked) */ - /* -- BAD: cert issued 2017-10-26, after the CA not-after date of 2017-10-21 */ - test_valid_trust(leaf_na_ok2, ca_na, NULL, anchors, date_20180102, - kBasicPolicy, kSecTrustResultFatalTrustFailure, - "leaf_na_ok2 basic"); - - /* Case 3: leaf_nb_ok1 (revoked) */ - /* -- BAD: cert issued 2017-10-20, before the CA not-before date of 2017-10-22 */ - test_valid_trust(leaf_nb_ok1, ca_nb, NULL, anchors, date_20180102, - kBasicPolicy, kSecTrustResultFatalTrustFailure, - "leaf_nb_ok1 basic"); - - /* Case 4: leaf_nb_ok2 (not revoked) */ - /* -- OK: cert issued 2017-10-26, after the CA not-before date of 2017-10-22 */ - test_valid_trust(leaf_nb_ok2, ca_nb, NULL, anchors, date_20180102, - kBasicPolicy, kSecTrustResultUnspecified, - "leaf_nb_ok2 basic"); - - /* Case 5: leaf_nb_revoked1 (revoked) */ - /* -- BAD: cert issued 2017-10-20, before the CA not-before date of 2017-10-22 */ - test_valid_trust(leaf_nb_revoked1, ca_nb, NULL, anchors, date_20180102, - kBasicPolicy, kSecTrustResultFatalTrustFailure, - "leaf_nb_revoked1 basic"); - - CFReleaseSafe(ca_na); - CFReleaseSafe(ca_nb); - CFReleaseSafe(leaf_na_ok1); - CFReleaseSafe(leaf_na_ok2); - CFReleaseSafe(leaf_nb_ok1); - CFReleaseSafe(leaf_nb_ok2); - CFReleaseSafe(leaf_nb_revoked1); - CFReleaseSafe(root); - CFReleaseSafe(anchors); - CFReleaseSafe(cal); - CFReleaseSafe(date_20180102); -} - -/* number of tests in known_intermediate_tests function, plus calls to test_valid_trust */ -#define KI_COUNT (10+(TVT_COUNT*3)) - -static void known_intermediate_tests() -{ - SecCertificateRef ca_ki=NULL, root=NULL; - SecCertificateRef leaf_ki_ok1=NULL, leaf_ki_revoked1=NULL; - SecCertificateRef leaf_unknown=NULL, ca_unknown=NULL; - - isnt(ca_ki = SecCertificateCreateFromResource(@"ca-ki"), NULL, "create ca-ki cert"); - isnt(root = SecCertificateCreateFromResource(@"root"), NULL, "create root cert"); - isnt(leaf_ki_ok1 = SecCertificateCreateFromResource(@"leaf-ki-ok1"), NULL, "create leaf-ki-ok1 cert"); - isnt(leaf_ki_revoked1 = SecCertificateCreateFromResource(@"leaf-ki-revoked1"), NULL, "create leaf-ki-revoked1 cert"); - isnt(ca_unknown = SecCertificateCreateFromResource(@"ca-unknown"), NULL, "create ca-unknown cert"); - isnt(leaf_unknown = SecCertificateCreateFromResource(@"leaf-unknown"), NULL, "create leaf-unknown cert"); - - CFMutableArrayRef anchors=NULL; - isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array"); - if (anchors && root) { - CFArrayAppendValue(anchors, root); - } - CFCalendarRef cal = NULL; - CFAbsoluteTime at; - CFDateRef date_20180310 = NULL; // a date when our test certs would all be valid, in the absence of Valid db info - - isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar"); - ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2018, 3, 10), "create verify absolute time 20180310"); - isnt(date_20180310 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20180310"); - - /* Case 1: leaf_ki_ok1 */ - /* -- OK: cert issued by a known intermediate */ - test_valid_trust(leaf_ki_ok1, ca_ki, NULL, anchors, date_20180310, - kBasicPolicy, kSecTrustResultUnspecified, - "leaf_ki_ok1"); - - /* Case 2: leaf_ki_revoked1 */ - /* -- BAD: CA specifies known-only+complete serial blocklist; this cert is on the blocklist. */ - test_valid_trust(leaf_ki_revoked1, ca_ki, NULL, anchors, date_20180310, - kBasicPolicy, kSecTrustResultFatalTrustFailure, - "leaf_ki_revoked1"); - - /* Case 3: leaf_unknown */ - /* -- BAD: ca_unknown issued from ca_ki, but is not a known intermediate. - * ca_ki has a path len of 0 which would normally result in kSecTrustResultRecoverableTrustFailure; - * however, since known-intermediates is asserted for ca_ki (non-overridable), we expect a fatal failure. */ - test_valid_trust(leaf_unknown, ca_unknown, ca_ki, anchors, date_20180310, - kBasicPolicy, kSecTrustResultFatalTrustFailure, - "leaf_unknown test"); - - CFReleaseSafe(ca_ki); - CFReleaseSafe(leaf_ki_ok1); - CFReleaseSafe(leaf_ki_revoked1); - CFReleaseSafe(ca_unknown); - CFReleaseSafe(leaf_unknown); - CFReleaseSafe(root); - CFReleaseSafe(anchors); - CFReleaseSafe(cal); - CFReleaseSafe(date_20180310); -} - -static int ping_host(char *host_name) -{ - struct sockaddr_in pin; - struct hostent *nlp_host; - int sd = 0; - int port = 80; - int retries = 5; // we try 5 times, then give up - - while ((nlp_host=gethostbyname(host_name))==0 && retries--) { - printf("Resolve Error! (%s) %d\n", host_name, h_errno); - sleep(1); - } - if (nlp_host==0) { - return 0; - } - - bzero(&pin,sizeof(pin)); - pin.sin_family=AF_INET; - pin.sin_addr.s_addr=htonl(INADDR_ANY); - pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr; - pin.sin_port=htons(port); - - sd=socket(AF_INET,SOCK_STREAM,0); - - if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1) { - printf("connect error! (%s) %d\n", host_name, errno); - close(sd); - return 0; - } - close(sd); - return 1; -} - -static int preflight_network() -{ - char *hosts[] = { - "EVSecure-ocsp.verisign.com", - "EVIntl-ocsp.verisign.com", - "EVIntl-aia.verisign.com", - "ocsp.comodoca.com", - "crt.comodoca.com", - "ocsp.entrust.net", - "ocsp.digicert.com", - }; - - for (unsigned host_cnt = 0; host_cnt < sizeof(hosts)/sizeof(hosts[0]); host_cnt ++) { - if (!ping_host(hosts[host_cnt])) { - printf("Accessing specific server (%s) failed, check the network!\n", hosts[host_cnt]); - return 0; - } - } - return 1; -} - -int si_88_sectrust_valid(int argc, char *const *argv) -{ - plan_tests(DC_COUNT+KI_COUNT); - - if (!preflight_network()) { - return 0; - } - - date_constraints_tests(); - known_intermediate_tests(); - - return 0; -} diff --git a/OSX/utilities/Regressions/su-10-cfstring-der.c b/OSX/utilities/Regressions/su-10-cfstring-der.c index 98176101..3a9031e1 100644 --- a/OSX/utilities/Regressions/su-10-cfstring-der.c +++ b/OSX/utilities/Regressions/su-10-cfstring-der.c @@ -63,7 +63,7 @@ static void one_test(const struct test_case * thisCase) CFStringRef decoded = NULL; - const uint8_t* decode_end = der_decode_string(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_string(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end); @@ -77,7 +77,7 @@ static void one_test(const struct test_case * thisCase) CFTypeRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end); diff --git a/OSX/utilities/Regressions/su-11-cfdata-der.c b/OSX/utilities/Regressions/su-11-cfdata-der.c index ceeeddf9..fb50b629 100644 --- a/OSX/utilities/Regressions/su-11-cfdata-der.c +++ b/OSX/utilities/Regressions/su-11-cfdata-der.c @@ -120,14 +120,14 @@ static void one_test(const struct test_case * thisCase) #endif CFDataRef decoded = NULL; - const uint8_t* decode_end = der_decode_data(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_data(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end); ok((decoded != NULL) && CFEqual(decoded, start)); CFTypeRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end); diff --git a/OSX/utilities/Regressions/su-12-cfboolean-der.c b/OSX/utilities/Regressions/su-12-cfboolean-der.c index ed6fe783..5a4ae67a 100644 --- a/OSX/utilities/Regressions/su-12-cfboolean-der.c +++ b/OSX/utilities/Regressions/su-12-cfboolean-der.c @@ -61,14 +61,14 @@ static void one_test(CFBooleanRef value, size_t der_size, const uint8_t *expecte #endif CFBooleanRef decoded = NULL; - const uint8_t* decode_end = der_decode_boolean(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_boolean(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end); ok((decoded != NULL) && CFEqual(decoded, value)); CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end); diff --git a/OSX/utilities/Regressions/su-13-cfnumber-der.c b/OSX/utilities/Regressions/su-13-cfnumber-der.c index 8eb5d038..6b6b1738 100644 --- a/OSX/utilities/Regressions/su-13-cfnumber-der.c +++ b/OSX/utilities/Regressions/su-13-cfnumber-der.c @@ -82,7 +82,7 @@ static void one_test(const struct test_case * thisCase) CFNumberRef decoded = NULL; - const uint8_t* decode_end = der_decode_number(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_number(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); @@ -90,7 +90,7 @@ static void one_test(const struct test_case * thisCase) CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); diff --git a/OSX/utilities/Regressions/su-14-cfarray-der.c b/OSX/utilities/Regressions/su-14-cfarray-der.c index 5627a9db..14076282 100644 --- a/OSX/utilities/Regressions/su-14-cfarray-der.c +++ b/OSX/utilities/Regressions/su-14-cfarray-der.c @@ -83,7 +83,7 @@ static void one_test(const struct test_case * thisCase) CFArrayRef decoded = NULL; - const uint8_t* decode_end = der_decode_array(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_array(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); @@ -91,7 +91,7 @@ static void one_test(const struct test_case * thisCase) CFTypeRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); diff --git a/OSX/utilities/Regressions/su-15-cfdictionary-der.c b/OSX/utilities/Regressions/su-15-cfdictionary-der.c index 945bf3fe..9f9c3515 100644 --- a/OSX/utilities/Regressions/su-15-cfdictionary-der.c +++ b/OSX/utilities/Regressions/su-15-cfdictionary-der.c @@ -83,7 +83,7 @@ static void test_dictionary(CFDictionaryRef testValue, size_t expected_size, con CFDictionaryRef decoded = NULL; - const uint8_t* decode_end = der_decode_dictionary(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_dictionary(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); @@ -91,7 +91,7 @@ static void test_dictionary(CFDictionaryRef testValue, size_t expected_size, con CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); diff --git a/OSX/utilities/Regressions/su-16-cfdate-der.c b/OSX/utilities/Regressions/su-16-cfdate-der.c index df3d05fc..8b781a73 100644 --- a/OSX/utilities/Regressions/su-16-cfdate-der.c +++ b/OSX/utilities/Regressions/su-16-cfdate-der.c @@ -114,6 +114,7 @@ static bool ok_date_equals(int testnumber, CFDateRef decoded, CFDateRef expected } } +#if 0 static CFCalendarRef sZuluCalendar = NULL; static CFCalendarRef SecCFCalendarGetZulu() { @@ -170,10 +171,12 @@ static bool parallelizeZulu(bool useSharedZuluCalendar, void(^action)(CFCalendar dispatch_release(dgroup); return !stop; } +#endif // We expect this to fail until this is fixed: // CFCalendarDecomposeAbsoluteTime is not thread safe // +#if 0 static void testWithUnguardedZuluCalendar() { const bool useSharedZuluCalendar = true; __block bool success = true; @@ -217,6 +220,7 @@ static void testDoWithZulu() { ok(success,"unexpected result from CFCalendarDecomposeAbsoluteTime"); } +#endif #define kTestsPerTestCase 12 static void one_test(const struct test_case * thisCase, int testnumber) @@ -246,7 +250,7 @@ static void one_test(const struct test_case * thisCase, int testnumber) CFReleaseNull(error); CFDateRef decoded = NULL; - const uint8_t* decode_end = der_decode_date(NULL, kCFPropertyListMutableContainers, + const uint8_t* decode_end = der_decode_date(NULL, &decoded, &error, encoded, buffer_end); ok(error == NULL, "[%d] der_decode_date failed: %@", testnumber, error); CFReleaseNull(error); @@ -256,7 +260,7 @@ static void one_test(const struct test_case * thisCase, int testnumber) CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainers, + decode_end = der_decode_plist(NULL, &decoded_type, &error, encoded, buffer_end); ok(error == NULL, "[%d] der_decode_plist failed: %@", testnumber, error); CFReleaseNull(error); diff --git a/OSX/utilities/Regressions/su-17-cfset-der.c b/OSX/utilities/Regressions/su-17-cfset-der.c index eff6f588..845b5b15 100644 --- a/OSX/utilities/Regressions/su-17-cfset-der.c +++ b/OSX/utilities/Regressions/su-17-cfset-der.c @@ -86,7 +86,7 @@ static void test_set(CFSetRef testValue, size_t expected_size, const uint8_t* ex CFSetRef decoded = NULL; - const uint8_t* decode_end = der_decode_set(NULL, kCFPropertyListMutableContainersAndLeaves, + const uint8_t* decode_end = der_decode_set(NULL, &decoded, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); @@ -94,7 +94,7 @@ static void test_set(CFSetRef testValue, size_t expected_size, const uint8_t* ex CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + decode_end = der_decode_plist(NULL, &decoded_type, NULL, encoded, buffer_end); ok(decode_end == buffer_end, "didn't decode whole buffer"); diff --git a/OSX/utilities/Regressions/su-40-secdb.c b/OSX/utilities/Regressions/su-40-secdb.c index 5c3c4d13..90d2c0c9 100644 --- a/OSX/utilities/Regressions/su-40-secdb.c +++ b/OSX/utilities/Regressions/su-40-secdb.c @@ -24,6 +24,7 @@ #include #include +#include #include @@ -71,25 +72,25 @@ static void count_connections(SecDbRef db) { dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_async(group, queue, ^{ - cmp_ok(count_func(db, "writers", &max_conn_count, SecDbPerformWrite), <=, kSecDbMaxWriters, "max writers is %d", kSecDbMaxWriters); + cmp_ok(count_func(db, "writers", &max_conn_count, SecDbPerformWrite), <=, kSecDbMaxWriters, "max writers is %zu", kSecDbMaxWriters); TODO: { todo("can't guarantee all threads used"); - is(count_func(db, "writers", &max_conn_count, SecDbPerformWrite), kSecDbMaxWriters, "max writers is %d", kSecDbMaxWriters); + is(count_func(db, "writers", &max_conn_count, SecDbPerformWrite), kSecDbMaxWriters, "max writers is %zu", kSecDbMaxWriters); } }); dispatch_group_async(group, queue, ^{ - cmp_ok(count_func(db, "readers", &max_conn_count, SecDbPerformRead), <=, kSecDbMaxReaders, "max readers is %d", kSecDbMaxReaders); + cmp_ok(count_func(db, "readers", &max_conn_count, SecDbPerformRead), <=, kSecDbMaxReaders, "max readers is %zu", kSecDbMaxReaders); TODO: { todo("can't guarantee all threads used"); - is(count_func(db, "readers", &max_conn_count, SecDbPerformRead), kSecDbMaxReaders, "max readers is %d", kSecDbMaxReaders); + is(count_func(db, "readers", &max_conn_count, SecDbPerformRead), kSecDbMaxReaders, "max readers is %zu", kSecDbMaxReaders); } }); dispatch_group_wait(group, DISPATCH_TIME_FOREVER); dispatch_release(group); - cmp_ok(max_conn_count, <=, kSecDbMaxIdleHandles, "max idle connection count is %d", kSecDbMaxIdleHandles); + cmp_ok(max_conn_count, <=, kSecDbMaxIdleHandles, "max idle connection count is %zu", kSecDbMaxIdleHandles); TODO: { todo("can't guarantee all threads idle"); - is(max_conn_count, kSecDbMaxIdleHandles, "max idle connection count is %d", kSecDbMaxIdleHandles); + is(max_conn_count, kSecDbMaxIdleHandles, "max idle connection count is %zu", kSecDbMaxIdleHandles); } } diff --git a/OSX/utilities/Regressions/su-41-secdb-stress.c b/OSX/utilities/Regressions/su-41-secdb-stress.c index b7f9c5bf..52c8b838 100644 --- a/OSX/utilities/Regressions/su-41-secdb-stress.c +++ b/OSX/utilities/Regressions/su-41-secdb-stress.c @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -31,7 +32,7 @@ #include "utilities_regressions.h" #include -#define kTestCount 3418 +#define kTestCount 3422 // God I love magic numbers // Queue to protect counters and test_ok invocations static dispatch_queue_t count_queue; @@ -187,7 +188,7 @@ static void tests(void) CFReleaseNull(tid); const char *home_var = getenv("HOME"); - CFStringRef dbName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s/Library/Keychains/su-41-sqldb-stress.db"), home_var ? home_var : ""); + CFStringRef dbName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s/Library/Keychains/su-41-secdb-stress.db"), home_var ? home_var : "/var/tmp"); CFStringPerformWithCString(dbName, ^(const char *path) { unlink(path); }); SecDbRef db = SecDbCreate(dbName, 0600, true, true, true, true, kSecDbMaxIdleHandles, @@ -244,14 +245,18 @@ static void tests(void) dispatch_release_null(count_queue); - cmp_ok(max_idle, >=, kSecDbMaxIdleHandles - 1, "max idle at least %d", kSecDbMaxIdleHandles - 1); - cmp_ok(max_writers, >=, kSecDbMaxWriters - 1, "max writers at least %d", kSecDbMaxWriters - 1); - cmp_ok(max_readers, >=, kSecDbMaxReaders - 1, "max readers at least %d", kSecDbMaxReaders - 1); + cmp_ok(SecDbIdleConnectionCount(db), >=, kSecDbMaxIdleHandles - 1, "cur idle at least %lu", kSecDbMaxIdleHandles - 1); + cmp_ok(SecDbIdleConnectionCount(db), <=, kSecDbMaxIdleHandles, "cur idle at most %lu", kSecDbMaxIdleHandles); + cmp_ok(max_idle, <=, kSecDbMaxIdleHandles, "max idle at most %lu", kSecDbMaxIdleHandles - 1); + cmp_ok(max_writers, >=, kSecDbMaxWriters - 1, "max writers at least %lu", kSecDbMaxWriters - 1); + cmp_ok(max_readers, >=, kSecDbMaxReaders - 1, "max readers at least %lu", kSecDbMaxReaders - 1); + cmp_ok(max_writers, <=, kSecDbMaxWriters, "max writers at most %lu", kSecDbMaxWriters); + cmp_ok(max_readers, <=, kSecDbMaxReaders, "max readers at most %lu", kSecDbMaxReaders); TODO: { todo("race conditions make us not always hit the limits reliably."); - is(max_idle, kSecDbMaxIdleHandles, "max idle connection count is %d", kSecDbMaxIdleHandles); - is(max_writers, kSecDbMaxWriters, "max writers is %d", kSecDbMaxWriters); - is(max_readers, kSecDbMaxReaders, "max readers is %d", kSecDbMaxReaders); + is(max_idle, kSecDbMaxIdleHandles, "max idle connection count is %zu", kSecDbMaxIdleHandles); + is(max_writers, kSecDbMaxWriters, "max writers is %zu", kSecDbMaxWriters); + is(max_readers, kSecDbMaxReaders, "max readers is %zu", kSecDbMaxReaders); } CFReleaseSafe(dbName); diff --git a/OSX/utilities/SecADWrapper.c b/OSX/utilities/SecADWrapper.c deleted file mode 100644 index 7d6aba8f..00000000 --- a/OSX/utilities/SecADWrapper.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2016 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@ - */ - -#include "SecADWrapper.h" - -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR -#include - -static typeof(ADClientAddValueForScalarKey) *soft_ADClientAddValueForScalarKey = NULL; -static typeof(ADClientClearScalarKey) *soft_ADClientClearScalarKey = NULL; -static typeof(ADClientSetValueForScalarKey) *soft_ADClientSetValueForScalarKey = NULL; -static typeof(ADClientPushValueForDistributionKey) *soft_ADClientPushValueForDistributionKey = NULL; - -static bool -setup(void) -{ - static dispatch_once_t onceToken; - static CFBundleRef bundle = NULL; - dispatch_once(&onceToken, ^{ - - CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/System/Library/PrivateFrameworks/AggregateDictionary.framework"), kCFURLPOSIXPathStyle, true); - if (url == NULL) - return; - - bundle = CFBundleCreate(kCFAllocatorDefault, url); - CFRelease(url); - if (bundle == NULL) - return; - - soft_ADClientClearScalarKey = CFBundleGetFunctionPointerForName(bundle, CFSTR("ADClientClearScalarKey")); - soft_ADClientSetValueForScalarKey = CFBundleGetFunctionPointerForName(bundle, CFSTR("ADClientSetValueForScalarKey")); - soft_ADClientAddValueForScalarKey = CFBundleGetFunctionPointerForName(bundle, CFSTR("ADClientAddValueForScalarKey")); - soft_ADClientPushValueForDistributionKey = CFBundleGetFunctionPointerForName(bundle, CFSTR("ADClientPushValueForDistributionKey")); - - if (soft_ADClientClearScalarKey == NULL || - soft_ADClientSetValueForScalarKey == NULL || - soft_ADClientAddValueForScalarKey == NULL || - soft_ADClientPushValueForDistributionKey == NULL) - { - CFRelease(bundle); - bundle = NULL; - } - }); - return bundle != NULL; -} -#endif - -void -SecADClearScalarKey(CFStringRef key) -{ -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - if (setup()) - soft_ADClientClearScalarKey(key); -#endif -} - -void -SecADSetValueForScalarKey(CFStringRef key, int64_t value) -{ -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - if (setup()) - soft_ADClientSetValueForScalarKey(key, value); -#endif -} -void -SecADAddValueForScalarKey(CFStringRef key, int64_t value) -{ -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - if (setup()) - soft_ADClientAddValueForScalarKey(key, value); -#endif -} - -void -SecADClientPushValueForDistributionKey(CFStringRef key, int64_t value) -{ -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - if (setup()) - soft_ADClientPushValueForDistributionKey(key, value); -#endif -} - diff --git a/OSX/utilities/SecCFCCWrappers.c b/OSX/utilities/SecCFCCWrappers.c index 588b9de2..dc815dfd 100644 --- a/OSX/utilities/SecCFCCWrappers.c +++ b/OSX/utilities/SecCFCCWrappers.c @@ -24,6 +24,8 @@ #include +#include + CFDataRef CFDataCreateDigestWithBytes(CFAllocatorRef allocator, const struct ccdigest_info *di, size_t len, const void *data, CFErrorRef *error) { CFMutableDataRef digest = CFDataCreateMutable(allocator, di->output_size); diff --git a/OSX/utilities/SecCFError.c b/OSX/utilities/SecCFError.c index 39caa712..fd428b29 100644 --- a/OSX/utilities/SecCFError.c +++ b/OSX/utilities/SecCFError.c @@ -26,7 +26,8 @@ #include #include #include - +#include "keychain/SecureObjectSync/SOSInternal.h" +#include // // OSStatus values we magically know @@ -69,66 +70,26 @@ bool SecCheckErrno(int result, CFErrorRef *error, CFStringRef format, ...) { return false; } -bool SecPOSIXError(int error, CFErrorRef *cferror, CFStringRef format, ...) -{ - if (error == 0) return true; - if (error) { - va_list args; - CFIndex code = error; - CFErrorRef previousError = *cferror; - - *cferror = NULL; - va_start(args, format); - SecCFCreateErrorWithFormatAndArguments(code, kSecErrnoDomain, previousError, cferror, NULL, format, args); - va_end(args); - } - return false; -} - -bool SecCoreCryptoError(int error, CFErrorRef *cferror, CFStringRef format, ...) -{ - if (error == 0) return true; - if (error) { - va_list args; - CFIndex code = error; - CFErrorRef previousError = *cferror; - - *cferror = NULL; - va_start(args, format); - SecCFCreateErrorWithFormatAndArguments(code, kSecCoreCryptoDomain, previousError, cferror, NULL, format, args); - va_end(args); - } - return false; -} +bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...) { + if (status == 0) { + return true; + } + CFErrorRef localError = NULL; + va_list args; + CFIndex code = status; + va_start(args, format); + SecCFCreateErrorWithFormatAndArguments(code, kSecErrorDomain, error ? *error : NULL, &localError, NULL, format, args); + va_end(args); -bool SecNotifyError(uint32_t result, CFErrorRef *error, CFStringRef format, ...) { - if (result == NOTIFY_STATUS_OK) return true; if (error) { - va_list args; - CFIndex code = result; - CFErrorRef previousError = *error; - - *error = NULL; - va_start(args, format); - SecCFCreateErrorWithFormatAndArguments(code, kSecNotifyDomain, previousError, error, NULL, format, args); - va_end(args); + *error = localError; // Existing *error is consumed by SecCFCreateErrorWithFormatAndArguments + } else { + // This happens a bunch in our codebase, so this log can only really exist in debug builds + secdebug("secerror", "Error, but no out-parameter for error: %@", localError); + CFReleaseNull(localError); } - return false; -} - -bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...) { - if (status == 0) return true; - if (error) { - va_list args; - CFIndex code = status; - CFErrorRef previousError = *error; - *error = NULL; - va_start(args, format); - SecCFCreateErrorWithFormatAndArguments(code, kSecErrorDomain, previousError, error, NULL, format, args); - va_end(args); - } return false; } @@ -175,6 +136,57 @@ bool SecCFCreateErrorWithFormat(CFIndex errorCode, CFStringRef domain, CFErrorRe return result; } +static bool SecCFErrorIsEqual(CFIndex errorCode, CFStringRef domain, CFStringRef description, CFErrorRef previousError) +{ + bool isEqual = false; + bool equalDescriptions = false; + + if (previousError == NULL) { + return false; + } + + CFDictionaryRef previousUserInfo = CFErrorCopyUserInfo(previousError); + CFStringRef previousDescription = CFDictionaryGetValue(previousUserInfo, kCFErrorDescriptionKey); + if (previousDescription) { + equalDescriptions = CFStringCompare(description, previousDescription, 0) == kCFCompareEqualTo ? true : false; + } + + CFReleaseNull(previousUserInfo); + bool equalCodes = errorCode == CFErrorGetCode(previousError); + + CFErrorDomain previousDomain = CFErrorGetDomain(previousError); + bool equalDomains = CFStringCompare(domain, previousDomain, 0) == kCFCompareEqualTo ? true : false; + + isEqual = equalCodes && equalDomains && equalDescriptions; + return isEqual; +} + +#define CAP_LIMIT 200 +static bool SecCFErrorShouldCapNestedError(CFErrorRef previousError, long *newCount) +{ + bool shouldCap = false; + + if (previousError) { + CFDictionaryRef userInfo = CFErrorCopyUserInfo(previousError); + if (userInfo && CFDictionaryContainsKey(userInfo, kSOSCountKey) == true) { + CFNumberRef previousCount = CFDictionaryGetValue(userInfo, kSOSCountKey); + if (previousCount) { + long previousLong = 0; + CFNumberGetValue(previousCount, kCFNumberLongType, &previousLong); + if (SecErrorIsNestedErrorCappingEnabled() && previousLong >= CAP_LIMIT) { + shouldCap = true; + } else { + *newCount = previousLong+1; + } + } + } + CFReleaseNull(userInfo); + } else { + *newCount = 0; + } + return shouldCap; +} + // Also consumes whatever newError points to bool SecCFCreateErrorWithFormatAndArguments(CFIndex errorCode, CFStringRef domain, CF_CONSUMED CFErrorRef previousError, CFErrorRef *newError, @@ -182,35 +194,57 @@ bool SecCFCreateErrorWithFormatAndArguments(CFIndex errorCode, CFStringRef domai { if (newError && !(*newError)) { CFStringRef formattedString = CFStringCreateWithFormatAndArguments(NULL, formatoptions, format, args); - - const void* keys[2] = { kCFErrorDescriptionKey, kCFErrorUnderlyingErrorKey}; - const void* values[2] = { formattedString, previousError }; - const CFIndex numEntriesToUse = (previousError != NULL) ? 2 : 1; - // Prepare to release whatever we replaced, as long as they didn't tell us to do so via previousError - // In a sane world, this function wouldn't have a previousError argument, since it should always release what it's replacing, - // but changing all callsites is a huge change - CFErrorRef replacing = ((*newError) == previousError) ? NULL : *newError; + long newDepthCount = 0; + CFNumberRef newCount = NULL; + + if (SecCFErrorIsEqual(errorCode, domain, formattedString, previousError) == true) { + secdebug("error_thee_well", "SecCFCreateErrorWithFormatAndArguments previous Error: %@ is equal to the new incoming error: domain: %@, error code: %ld, description: %@", previousError, domain, (long)errorCode, formattedString); + *newError = CFRetainSafe(previousError); + CFReleaseNull(previousError); + CFReleaseNull(formattedString); + return false; + } else if (SecCFErrorShouldCapNestedError(previousError, &newDepthCount) == true) { + secdebug("error_thee_well", "SecCFCreateErrorWithFormatAndArguments reached nested error limit, returning previous error: %@", previousError); + *newError = CFRetainSafe(previousError); + CFReleaseNull(previousError); + CFReleaseNull(formattedString); + return false; + } else { + newCount = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongType, &newDepthCount); + } - *newError = CFErrorCreateWithUserInfoKeysAndValues(kCFAllocatorDefault, domain, errorCode, - keys, values, numEntriesToUse); + CFMutableDictionaryRef newUserInfo = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFReleaseNull(formattedString); - if (previousError) - secdebug("error_thee_well", "encapsulated %@ with new error: %@", previousError, *newError); + if (previousError) { + CFDictionaryAddValue(newUserInfo, kCFErrorUnderlyingErrorKey, previousError); + } + if (newCount) { + CFDictionaryAddValue(newUserInfo, kSOSCountKey, newCount); + } + if (formattedString) { + CFDictionaryAddValue(newUserInfo, kCFErrorDescriptionKey, formattedString); + } + + *newError = CFErrorCreate(kCFAllocatorDefault, domain, errorCode, newUserInfo); - CFReleaseNull(replacing); + if (previousError) { + secdebug("error_thee_well", "encapsulated %@ with new error: %@", previousError, *newError); + } + CFReleaseNull(newCount); + CFReleaseNull(formattedString); + CFReleaseNull(newUserInfo); CFReleaseNull(previousError); } else { if (previousError && newError && (previousError != *newError)) { secdebug("error_thee_well", "dropping %@", previousError); - CFRelease(previousError); + CFReleaseNull(previousError); } } - if (newError) + if (newError) { secdebug("error_thee_well", "SecError: %@", *newError); - + } return false; } diff --git a/OSX/utilities/SecCFError.h b/OSX/utilities/SecCFError.h index 3d6121ee..853e150a 100644 --- a/OSX/utilities/SecCFError.h +++ b/OSX/utilities/SecCFError.h @@ -47,21 +47,6 @@ bool SecCheckErrno(int result, CFErrorRef *error, CFStringRef format, ...) bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...) CF_FORMAT_FUNCTION(3, 4); -// Direct checking of POSIX errors. -bool SecPOSIXError(int error, CFErrorRef *cferror, CFStringRef format, ...) - CF_FORMAT_FUNCTION(3, 4); - -// CoreCrypto error -#define kSecCoreCryptoDomain CFSTR("kSecCoreCryptoDomain") -bool SecCoreCryptoError(int error, CFErrorRef *cferror, CFStringRef format, ...) - CF_FORMAT_FUNCTION(3, 4); - -// Notification -#define kSecNotifyDomain CFSTR("kSecNotifyDomain") -bool SecNotifyError(uint32_t result, CFErrorRef *error, CFStringRef format, ...) - CF_FORMAT_FUNCTION(3, 4); - - // requirement error, typically parameters bool SecRequirementError(bool requirement, CFErrorRef *error, CFStringRef format, ...) CF_FORMAT_FUNCTION(3, 4); @@ -95,7 +80,9 @@ static inline bool asArrayOptional(CFTypeRef cfType, CFArrayRef *array, CFErrorR if (array) *array = (CFArrayRef)cfType; return true; } - SecError(-50, error, CFSTR("object %@ is not an array"), cfType); + if(error) { + SecError(-50, error, CFSTR("object %@ is not an array"), cfType); + } return false; } @@ -104,16 +91,9 @@ static inline bool asDataOptional(CFTypeRef cfType, CFDataRef *data, CFErrorRef if (data) *data = (CFDataRef)cfType; return true; } - SecError(-50, error, CFSTR("object %@ is not an data"), cfType); - return false; -} - -static inline bool asSetOptional(CFTypeRef cfType, CFSetRef *set, CFErrorRef *error) { - if (!cfType || CFGetTypeID(cfType) == CFSetGetTypeID()) { - if (set) *set = (CFSetRef)cfType; - return true; + if(error) { + SecError(-50, error, CFSTR("object %@ is not an data"), cfType); } - SecError(-50, error, CFSTR("object %@ is not a set"), cfType); return false; } @@ -121,63 +101,23 @@ static inline bool asSetOptional(CFTypeRef cfType, CFSetRef *set, CFErrorRef *er // MARK: Required value type casting // -// -// MARK: Required value type casting -// - -static inline CFArrayRef copyIfArray(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFArrayGetTypeID()) - return (CFArrayRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not an array"), cfType); - return NULL; -} - -static inline CFBooleanRef copyIfBoolean(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFBooleanGetTypeID()) - return (CFBooleanRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not an boolean"), cfType); - return NULL; -} - static inline CFDataRef copyIfData(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDataGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFDataGetTypeID()) { return (CFDataRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a data"), cfType); - return NULL; -} - -static inline CFDateRef copyIfDate(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDateGetTypeID()) - return (CFDateRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a date"), cfType); - return NULL; -} - -static inline CFDictionaryRef copyIfDictionary(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDictionaryGetTypeID()) - return (CFDictionaryRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a dictionary"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a data"), cfType); + } return NULL; } static inline CFSetRef copyIfSet(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFSetGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFSetGetTypeID()) { return (CFSetRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a set"), cfType); - return NULL; -} - -static inline CFStringRef copyIfString(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFStringGetTypeID()) - return (CFStringRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a string"), cfType); - return NULL; -} - -static inline CFUUIDRef copyIfUUID(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFUUIDGetTypeID()) - return (CFUUIDRef)CFRetainSafe(cfType); - SecError(-50, error, CFSTR("object %@ is not a UUID"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a set"), cfType); + } return NULL; } @@ -185,58 +125,72 @@ static inline CFUUIDRef copyIfUUID(CFTypeRef cfType, CFErrorRef *error) { // MARK: Analyzer confusing asXxx casting // static inline CFArrayRef asArray(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFArrayGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFArrayGetTypeID()) { return (CFArrayRef)cfType; - SecError(-50, error, CFSTR("object %@ is not an array"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not an array"), cfType); + } return NULL; } static inline CFBooleanRef asBoolean(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFBooleanGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFBooleanGetTypeID()) { return (CFBooleanRef)cfType; - SecError(-50, error, CFSTR("object %@ is not an boolean"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not an boolean"), cfType); + } return NULL; } static inline CFDataRef asData(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDataGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFDataGetTypeID()) { return (CFDataRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a data"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a data"), cfType); + } return NULL; } static inline CFDateRef asDate(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDateGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFDateGetTypeID()) { return (CFDateRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a date"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a date"), cfType); + } return NULL; } static inline CFDictionaryRef asDictionary(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFDictionaryGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFDictionaryGetTypeID()) { return (CFDictionaryRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a dictionary"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a dictionary"), cfType); + } return NULL; } static inline CFSetRef asSet(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFSetGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFSetGetTypeID()) { return (CFSetRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a set"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a set"), cfType); + } return NULL; } static inline CFStringRef asString(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFStringGetTypeID()) + if (cfType && CFGetTypeID(cfType) == CFStringGetTypeID()) { return (CFStringRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a string"), cfType); - return NULL; -} - -static inline CFUUIDRef asUUID(CFTypeRef cfType, CFErrorRef *error) { - if (cfType && CFGetTypeID(cfType) == CFUUIDGetTypeID()) - return (CFUUIDRef)cfType; - SecError(-50, error, CFSTR("object %@ is not a UUID"), cfType); + } + if(error) { + SecError(-50, error, CFSTR("object %@ is not a string"), cfType); + } return NULL; } diff --git a/OSX/utilities/SecCFWrappers.h b/OSX/utilities/SecCFWrappers.h index 1cfb109b..979adda6 100644 --- a/OSX/utilities/SecCFWrappers.h +++ b/OSX/utilities/SecCFWrappers.h @@ -34,7 +34,7 @@ #include -#include +#include "utilities/simulatecrash_assert.h" #include #include #include @@ -225,12 +225,12 @@ static inline bool isNull(CFTypeRef cfType) { // Usage: void foo(CFTypeRef value) { CFDataRef data = CFCast(CFData, value); } #define CFCast(type, value) \ - ((value != NULL) && CFGetTypeID(value) == type ## GetTypeID() ? (type ## Ref)(value) : NULL) + ({ __typeof__(value) _v = (value); (_v != NULL) && CFGetTypeID(_v) == type ## GetTypeID() ? (type ## Ref)_v : NULL; }) -#define CFCastWithError(type, value, error) \ - ((value != NULL) && CFGetTypeID(value) == type ## GetTypeID() ? \ - (type ## Ref)(value) : \ - (SecError(errSecParam, error, CFSTR("Unexpected type")), NULL)) +#define CFCastWithError(type, value, error) \ + ({ __typeof__(value) _v = (value); (_v != NULL) && CFGetTypeID(_v) == type ## GetTypeID() ? \ + (type ## Ref)_v : \ + (SecError(errSecParam, error, CFSTR("Unexpected type")), NULL); }) // // MARK CFEqual Helpers @@ -369,7 +369,9 @@ static inline const uint8_t* CFDataGetPastEndPtr(CFDataRef theData) { return CFDataGetBytePtr(theData) + CFDataGetLength(theData); } -static inline CFComparisonResult CFDataCompare(CFDataRef left, CFDataRef right) +// This function compare DER data object, which take into account the length +// of the data objects when doing the comparsion which item is "before" or "after" +static inline CFComparisonResult CFDataCompareDERData(CFDataRef left, CFDataRef right) { const size_t left_size = CFDataGetLength(left); const size_t right_size = CFDataGetLength(right); @@ -385,6 +387,10 @@ static inline CFComparisonResult CFDataCompare(CFDataRef left, CFDataRef right) return kCFCompareEqualTo; } +static inline __deprecated_msg("please use CFEqual or CFDataCompareDERData") CFComparisonResult CFDataCompare(CFDataRef left, CFDataRef right) { + return CFDataCompareDERData(left, right); +} + static inline CFDataRef CFDataCreateWithHash(CFAllocatorRef allocator, const struct ccdigest_info *di, const uint8_t *buffer, const uint8_t length) { CFMutableDataRef result = CFDataCreateMutableWithScratch(allocator, di->output_size); @@ -530,13 +536,13 @@ static inline CFStringRef CFStringCreateTruncatedCopy(CFStringRef s, CFIndex len // static inline -const void *SecCFRetainForCollection(CFAllocatorRef allocator, const void *value) +const void *SecCFRetainForCollection(CFAllocatorRef __unused allocator, const void *value) { return CFRetain(value); } static inline -void SecCFReleaseForCollection(CFAllocatorRef allocator, const void *value) +void SecCFReleaseForCollection(CFAllocatorRef __unused allocator, const void *value) { CFRelease(value); } @@ -1015,7 +1021,8 @@ static inline CFDateRef CFDateCreateForGregorianMoment(CFAllocatorRef allocator, return CFDateCreate(allocator, CFAbsoluteTimeForGregorianMoment(tz, year, month, day, hour, minute, second)); } -static inline CFDateRef CFDateCreateForGregorianDay(CFAllocatorRef allocator, CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second) +static inline CFDateRef CFDateCreateForGregorianDay(CFAllocatorRef allocator, CFTimeZoneRef tz, int year, int month, int day, + int __unused hour, int __unused minute, int __unused second) { return CFDateCreate(allocator, CFAbsoluteTimeForGregorianDay(tz, year, month, day)); } diff --git a/OSX/utilities/SecCoreAnalytics.h b/OSX/utilities/SecCoreAnalytics.h index 244ffd28..2f8dc662 100644 --- a/OSX/utilities/SecCoreAnalytics.h +++ b/OSX/utilities/SecCoreAnalytics.h @@ -21,12 +21,18 @@ * @APPLE_LICENSE_HEADER_END@ */ -#import +#include + +void SecCoreAnalyticsSendValue(CFStringRef _Nonnull eventName, int64_t value); #if __OBJC__ +#import + NS_ASSUME_NONNULL_BEGIN +extern NSString* const SecCoreAnalyticsValue; + @interface SecCoreAnalytics : NSObject + (void)sendEvent:(NSString*) eventName event:(NSDictionary *)event; diff --git a/OSX/utilities/SecCoreAnalytics.m b/OSX/utilities/SecCoreAnalytics.m index 3e41cf17..e58cea45 100644 --- a/OSX/utilities/SecCoreAnalytics.m +++ b/OSX/utilities/SecCoreAnalytics.m @@ -26,9 +26,20 @@ #import #import +NSString* const SecCoreAnalyticsValue = @"value"; + + +void SecCoreAnalyticsSendValue(CFStringRef _Nonnull eventName, int64_t value) +{ + [SecCoreAnalytics sendEvent:(__bridge NSString*)eventName + event:@{ + SecCoreAnalyticsValue: [NSNumber numberWithLong:value], + }]; +} + @implementation SecCoreAnalytics -SOFT_LINK_FRAMEWORK_SAFE(PrivateFrameworks, CoreAnalytics); +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CoreAnalytics); SOFT_LINK_FUNCTION(CoreAnalytics, AnalyticsSendEvent, soft_AnalyticsSendEvent, \ void, (NSString* eventName, NSDictionary* eventPayload),(eventName, eventPayload)); diff --git a/OSX/utilities/SecDb.c b/OSX/utilities/SecDb.c index f09ef95f..422b871b 100644 --- a/OSX/utilities/SecDb.c +++ b/OSX/utilities/SecDb.c @@ -23,6 +23,7 @@ #include "SecDb.h" +#include "SecDbInternal.h" #include "debugging.h" #include @@ -87,9 +88,13 @@ struct __OpaqueSecDb { CFStringRef db_path; dispatch_queue_t queue; dispatch_queue_t commitQueue; - CFMutableArrayRef connections; - dispatch_semaphore_t write_semaphore; - dispatch_semaphore_t read_semaphore; + + CFMutableArrayRef idleWriteConnections; // up to kSecDbMaxWriters of them (currently 1, requires locking change for >1) + CFMutableArrayRef idleReadConnections; // up to kSecDbMaxReaders of them + pthread_mutex_t writeMutex; + // TODO: Replace after we have rdar://problem/60961964 + dispatch_semaphore_t readSemaphore; + bool didFirstOpen; bool (^opened)(SecDbRef db, SecDbConnectionRef dbconn, bool didCreate, bool *callMeAgainForNextConnection, CFErrorRef *error); bool callOpenedHandlerForNextConnection; @@ -200,7 +205,7 @@ static CFStringRef SecDbCopyFormatDescription(CFTypeRef value, CFDictionaryRef formatOptions) { SecDbRef db = (SecDbRef)value; - return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), db->db_path, db->connections); + return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), db->db_path, db->idleReadConnections); } @@ -208,8 +213,13 @@ static void SecDbDestroy(CFTypeRef value) { SecDbRef db = (SecDbRef)value; - CFReleaseNull(db->connections); + CFReleaseNull(db->db_path); + dispatch_sync(db->queue, ^{ + CFReleaseNull(db->idleWriteConnections); + CFReleaseNull(db->idleReadConnections); + }); + if (db->queue) { dispatch_release(db->queue); db->queue = NULL; @@ -218,14 +228,14 @@ SecDbDestroy(CFTypeRef value) dispatch_release(db->commitQueue); db->commitQueue = NULL; } - if (db->read_semaphore) { - dispatch_release(db->read_semaphore); - db->read_semaphore = NULL; - } - if (db->write_semaphore) { - dispatch_release(db->write_semaphore); - db->write_semaphore = NULL; + + pthread_mutex_destroy(&(db->writeMutex)); + + if (db->readSemaphore) { + dispatch_release(db->readSemaphore); + db->readSemaphore = NULL; } + if (db->opened) { Block_release(db->opened); db->opened = NULL; @@ -252,9 +262,12 @@ SecDbCreate(CFStringRef dbName, mode_t mode, bool readWrite, bool allowRepair, b db->commitQueue = dispatch_queue_create(cqNameStr, DISPATCH_QUEUE_CONCURRENT); }); CFReleaseNull(commitQueueStr); - db->read_semaphore = dispatch_semaphore_create(kSecDbMaxReaders); - db->write_semaphore = dispatch_semaphore_create(kSecDbMaxWriters); - db->connections = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + db->readSemaphore = dispatch_semaphore_create(kSecDbMaxReaders); + if (pthread_mutex_init(&(db->writeMutex), NULL) != 0) { + seccritical("SecDb: SecDbCreate failed to init the write mutex, this will end badly"); + } + db->idleWriteConnections = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + db->idleReadConnections = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); db->opened = opened ? Block_copy(opened) : NULL; if (getenv("__OSINSTALL_ENVIRONMENT") != NULL) { // TODO: Move this code out of this layer @@ -280,13 +293,15 @@ CFIndex SecDbIdleConnectionCount(SecDbRef db) { __block CFIndex count = 0; dispatch_sync(db->queue, ^{ - count = CFArrayGetCount(db->connections); + count = CFArrayGetCount(db->idleReadConnections); + count += CFArrayGetCount(db->idleWriteConnections); }); return count; } void SecDbAddNotifyPhaseBlock(SecDbRef db, SecDBNotifyBlock notifyPhase) { +#if !TARGET_OS_BRIDGE // SecDbNotifyPhase seems to mostly be called on the db's commitQueue, and not the db's queue. Therefore, protect the array with that queue. dispatch_sync(db->commitQueue, ^{ SecDBNotifyBlock block = Block_copy(notifyPhase); /* Force the block off the stack */ @@ -296,9 +311,11 @@ void SecDbAddNotifyPhaseBlock(SecDbRef db, SecDBNotifyBlock notifyPhase) CFArrayAppendValue(db->notifyPhase, block); Block_release(block); }); +#endif } static void SecDbNotifyPhase(SecDbConnectionRef dbconn, SecDbTransactionPhase phase) { +#if !TARGET_OS_BRIDGE if (CFArrayGetCount(dbconn->changes)) { CFArrayRef changes = dbconn->changes; dbconn->changes = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); @@ -310,6 +327,7 @@ static void SecDbNotifyPhase(SecDbConnectionRef dbconn, SecDbTransactionPhase ph } CFReleaseSafe(changes); } +#endif } static void SecDbOnNotify(SecDbConnectionRef dbconn, void (^perform)(void)) { @@ -784,10 +802,6 @@ bool SecDbCheckpoint(SecDbConnectionRef dbconn, CFErrorRef *error) return SecDbConnectionCheckCode(dbconn, sqlite3_wal_checkpoint(dbconn->handle, NULL), error, CFSTR("wal_checkpoint")); } -static bool SecDbFileControl(SecDbConnectionRef dbconn, int op, void *arg, CFErrorRef *error) { - return SecDbConnectionCheckCode(dbconn, sqlite3_file_control(dbconn->handle, NULL, op, arg), error, CFSTR("file_control")); -} - static sqlite3 *_SecDbOpenV2(const char *path, int flags, int useWAL, @@ -986,19 +1000,24 @@ SecDbProfileMask(void) static int SecDbTraceV2(unsigned mask, void *ctx, void *p, void *x) { SecDbConnectionRef dbconn __unused = ctx; + +#if SECDB_DEBUGGING const char *trace = "unknown"; + char *tofree = NULL; if (mask == SQLITE_TRACE_PROFILE) trace = sqlite3_sql(p); else if (mask == SQLITE_TRACE_STMT) { trace = sqlite3_sql(p); } else if (mask == SQLITE_TRACE_ROW) { - trace = sqlite3_expanded_sql(p); + trace = tofree = sqlite3_expanded_sql(p); } -#if SECDB_DEBUGGING secinfo("#SecDB", "#SecDB %{public}s", trace); + + sqlite3_free(tofree); #endif + return 0; } @@ -1089,21 +1108,36 @@ static void SecDbConectionSetReadOnly(SecDbConnectionRef dbconn, bool readOnly) dbconn->readOnly = readOnly; } -/* Read only connections go to the end of the queue, writeable connections - go to the start of the queue. */ SecDbConnectionRef SecDbConnectionAcquire(SecDbRef db, bool readOnly, CFErrorRef *error) { SecDbConnectionRef dbconn = NULL; SecDbConnectionAcquireRefMigrationSafe(db, readOnly, &dbconn, error); return dbconn; } +static void SecDbConnectionConsumeResource(SecDbRef db, bool readOnly) { + if (readOnly) { + dispatch_semaphore_wait(db->readSemaphore, DISPATCH_TIME_FOREVER); + } else { + pthread_mutex_lock(&(db->writeMutex)); + } +} + +static void SecDbConnectionMakeResourceAvailable(SecDbRef db, bool readOnly) { + if (readOnly) { + dispatch_semaphore_signal(db->readSemaphore); + } else { + pthread_mutex_unlock(&(db->writeMutex)); + } +} + bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbConnectionRef* dbconnRef, CFErrorRef *error) { CFRetain(db); #if SECDB_DEBUGGING secinfo("dbconn", "acquire %s connection", readOnly ? "ro" : "rw"); #endif - dispatch_semaphore_wait(readOnly ? db->read_semaphore : db->write_semaphore, DISPATCH_TIME_FOREVER); + SecDbConnectionConsumeResource(db, readOnly); + __block SecDbConnectionRef dbconn = NULL; __block bool ok = true; __block bool ranOpenedHandler = false; @@ -1140,29 +1174,23 @@ bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbCon if (ok) { db->didFirstOpen = ok = SecDbDidCreateFirstConnection(dbconn, didCreate, error); ranOpenedHandler = true; - } - if (!ok) + SecDbConectionSetReadOnly(dbconn, readOnly); // first connection always created "rw", so set to real value + } else { CFReleaseNull(dbconn); + } } else { /* Try to get one from the cache */ - CFIndex count = CFArrayGetCount(db->connections); - while (count && !dbconn) { - CFIndex ix = readOnly ? count - 1 : 0; - if (assignDbConn((SecDbConnectionRef)CFArrayGetValueAtIndex(db->connections, ix))) + CFMutableArrayRef cache = readOnly ? db->idleReadConnections : db->idleWriteConnections; + if (CFArrayGetCount(cache) && !dbconn) { + if (assignDbConn((SecDbConnectionRef)CFArrayGetValueAtIndex(cache, 0))) { CFRetainSafe(dbconn); - else - secerror("got NULL dbconn at index: %" PRIdCFIndex " skipping", ix); - CFArrayRemoveValueAtIndex(db->connections, ix); + } + CFArrayRemoveValueAtIndex(cache, 0); } } }); - if (dbconn) { - /* Make sure the connection we found has the right access */ - if (SecDbConnectionIsReadOnly(dbconn) != readOnly) { - SecDbConectionSetReadOnly(dbconn, readOnly); - } - } else if (ok) { + if (ok && !dbconn) { /* Nothing found in cache, create a new connection */ bool created = false; if (assignDbConn(SecDbConnectionCreate(db, readOnly, error)) && !SecDbOpenHandle(dbconn, &created, error)) { @@ -1170,7 +1198,6 @@ bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbCon } } - if (dbconn && !ranOpenedHandler && dbconn->db->opened) { dispatch_sync(db->queue, ^{ if (dbconn->db->callOpenedHandlerForNextConnection) { @@ -1189,8 +1216,8 @@ bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbCon } if (!dbconn) { - // If acquire fails we need to signal the semaphore again. - dispatch_semaphore_signal(readOnly ? db->read_semaphore : db->write_semaphore); + // Caller doesn't get (to use) a connection so the backing synchronization primitive is available again + SecDbConnectionMakeResourceAvailable(db, readOnly); CFRelease(db); } @@ -1199,33 +1226,38 @@ bool SecDbConnectionAcquireRefMigrationSafe(SecDbRef db, bool readOnly, SecDbCon void SecDbConnectionRelease(SecDbConnectionRef dbconn) { if (!dbconn) { - secerror("called with NULL dbconn"); + secerror("SecDbConnectionRelease called with NULL dbconn"); return; } SecDbRef db = dbconn->db; #if SECDB_DEBUGGING secinfo("dbconn", "release %@", dbconn); #endif + + bool readOnly = SecDbConnectionIsReadOnly(dbconn); dispatch_sync(db->queue, ^{ - bool readOnly = SecDbConnectionIsReadOnly(dbconn); if (dbconn->hasIOFailure) { // Something wrong on the file layer (e.g. revoked file descriptor for networked home) - // so we don't trust our existing connections anymore. - CFArrayRemoveAllValues(db->connections); + secwarning("SecDbConnectionRelease: IO failure reported in connection, throwing away currently idle caches"); + // Any other checked-out connections are beyond our grasp. If they did not have IO failures they'll come back, + // otherwise this branch gets taken more than once and gradually those connections die off + CFArrayRemoveAllValues(db->idleWriteConnections); + CFArrayRemoveAllValues(db->idleReadConnections); } else { - CFIndex count = CFArrayGetCount(db->connections); - // Add back possible writable dbconn to the pool. - CFArrayInsertValueAtIndex(db->connections, readOnly ? count : 0, dbconn); - // Remove the last (probably read-only) dbconn from the pool. - if (count >= db->maxIdleHandles) { - CFArrayRemoveValueAtIndex(db->connections, count); + CFMutableArrayRef cache = readOnly ? db->idleReadConnections : db->idleWriteConnections; + CFIndex count = CFArrayGetCount(cache); + if ((unsigned long)count < (readOnly ? kSecDbMaxReaders : kSecDbMaxWriters)) { + CFArrayAppendValue(cache, dbconn); + } else { + secerror("dbconn: did not expect to run out of room in the %s cache when releasing connection", readOnly ? "ro" : "rw"); } } - // Signal after we have put the connection back in the pool of connections - dispatch_semaphore_signal(readOnly ? db->read_semaphore : db->write_semaphore); - CFRelease(dbconn); - CFRelease(db); }); + + // Signal after we have put the connection back in the pool of connections + SecDbConnectionMakeResourceAvailable(db, readOnly); + CFRelease(dbconn); + CFRelease(db); } void SecDbReleaseAllConnections(SecDbRef db) { @@ -1235,29 +1267,31 @@ void SecDbReleaseAllConnections(SecDbRef db) { return; } dispatch_sync(db->queue, ^{ - CFArrayRemoveAllValues(db->connections); - dispatch_semaphore_signal(db->write_semaphore); - dispatch_semaphore_signal(db->read_semaphore); + CFArrayRemoveAllValues(db->idleReadConnections); + CFArrayRemoveAllValues(db->idleWriteConnections); + }); +} + +static void onQueueSecDbForceCloseForCache(CFMutableArrayRef cache) { + CFArrayForEach(cache, ^(const void* ptr) { + SecDbConnectionRef connection = (SecDbConnectionRef)ptr; + + // this pointer is claimed to be nonretained + connection->db = NULL; + + if(connection->handle) { + sqlite3_close(connection->handle); + connection->handle = NULL; + } }); + CFArrayRemoveAllValues(cache); } // Please make sure you want to do this. Any use of the outstanding connections to this DB will cause a crash. void SecDbForceClose(SecDbRef db) { dispatch_sync(db->queue, ^{ - CFArrayForEach(db->connections, ^(const void* p) { - SecDbConnectionRef connection = (SecDbConnectionRef)p; - - // this pointer is claimed to be nonretained - connection->db = NULL; - - if(connection->handle) { - sqlite3_close(connection->handle); - connection->handle = NULL; - } - }); - CFArrayRemoveAllValues(db->connections); - dispatch_semaphore_signal(db->write_semaphore); - dispatch_semaphore_signal(db->read_semaphore); + onQueueSecDbForceCloseForCache(db->idleReadConnections); + onQueueSecDbForceCloseForCache(db->idleWriteConnections); }); } diff --git a/OSX/utilities/SecDb.h b/OSX/utilities/SecDb.h index 06ea04e4..9316e3e8 100644 --- a/OSX/utilities/SecDb.h +++ b/OSX/utilities/SecDb.h @@ -36,14 +36,6 @@ typedef struct __OpaqueSecDbConnection *SecDbConnectionRef; typedef struct __OpaqueSecDbStatement *SecDbStatementRef; struct SOSDigestVector; -// MARK: Configuration values, not used by clients directly. -// TODO: Move this section to a private header -enum { - kSecDbMaxReaders = 4, - kSecDbMaxWriters = 1, - kSecDbMaxIdleHandles = 3, -}; - // MARK: SecDbTransactionType enum { kSecDbNoneTransactionType = 0, diff --git a/OSX/utilities/SecDbInternal.h b/OSX/utilities/SecDbInternal.h new file mode 100644 index 00000000..15a5ef20 --- /dev/null +++ b/OSX/utilities/SecDbInternal.h @@ -0,0 +1,14 @@ +#ifndef SecDbInternal_h +#define SecDbInternal_h + +#include "SecDb.h" + +static const size_t kSecDbMaxReaders = 5; + +// Do not increase this without changing lock types in SecDb +static const size_t kSecDbMaxWriters = 1; + +// maxreaders + maxwriters +static const size_t kSecDbMaxIdleHandles = 6; + +#endif /* SecDbInternal_h */ diff --git a/OSX/utilities/SecFileLocations.c b/OSX/utilities/SecFileLocations.c index ffe3923b..3606eef8 100644 --- a/OSX/utilities/SecFileLocations.c +++ b/OSX/utilities/SecFileLocations.c @@ -262,7 +262,16 @@ CFURLRef SecCopyURLForFileInManagedPreferencesDirectory(CFStringRef fileName) CFURLRef SecCopyURLForFileInRevocationInfoDirectory(CFStringRef fileName) { +#if TARGET_OS_OSX + return SecCopyURLForFileInBaseDirectory(true, CFSTR("private/var/protected/trustd/"), fileName); +#else return SecCopyURLForFileInBaseDirectory(true, CFSTR("Library/Keychains/crls/"), fileName); +#endif +} + +CFURLRef SecCopyURLForFileInProtectedDirectory(CFStringRef fileName) +{ + return SecCopyURLForFileInBaseDirectory(true, CFSTR("private/var/protected/"), fileName); } static void WithPathInDirectory(CFURLRef fileURL, void(^operation)(const char *utf8String)) @@ -292,6 +301,11 @@ void WithPathInUserCacheDirectory(CFStringRef fileName, void(^operation)(const c WithPathInDirectory(SecCopyURLForFileInUserCacheDirectory(fileName), operation); } +void WithPathInProtectedDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)) +{ + WithPathInDirectory(SecCopyURLForFileInProtectedDirectory(fileName), operation); +} + void SetCustomHomeURL(CFURLRef url) { sCustomHomeURL = CFRetainSafe(url); diff --git a/OSX/utilities/SecFileLocations.h b/OSX/utilities/SecFileLocations.h index 09dcd233..dc59d9f2 100644 --- a/OSX/utilities/SecFileLocations.h +++ b/OSX/utilities/SecFileLocations.h @@ -40,10 +40,12 @@ CFURLRef SecCopyURLForFileInUserCacheDirectory(CFStringRef fileName) CF_RETURNS_ CFURLRef SecCopyURLForFileInPreferencesDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; CFURLRef SecCopyURLForFileInManagedPreferencesDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; CFURLRef SecCopyURLForFileInRevocationInfoDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; +CFURLRef SecCopyURLForFileInProtectedDirectory(CFStringRef fileName) CF_RETURNS_RETAINED; void WithPathInKeychainDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); void WithPathInRevocationInfoDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); void WithPathInUserCacheDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); +void WithPathInProtectedDirectory(CFStringRef fileName, void(^operation)(const char *utf8String)); void SetCustomHomePath(const char* path); void SetCustomHomeURLString(CFStringRef path); diff --git a/OSX/utilities/SecXPCError.c b/OSX/utilities/SecXPCError.c index 47e9266f..83b6f6b8 100644 --- a/OSX/utilities/SecXPCError.c +++ b/OSX/utilities/SecXPCError.c @@ -56,7 +56,7 @@ CFErrorRef SecCreateCFErrorWithXPCObject(xpc_object_t xpc_error) const uint8_t *der = xpc_dictionary_get_data(xpc_error, kUserInfoKey, &size); if (der) { const uint8_t *der_end = der + size; - der = der_decode_plist(kCFAllocatorDefault, kCFPropertyListImmutable, + der = der_decode_plist(kCFAllocatorDefault, &user_info, NULL, der, der_end); if (der != der_end) CFReleaseNull(user_info); diff --git a/OSX/utilities/SecXPCHelper.h b/OSX/utilities/SecXPCHelper.h index 4b926795..019b49a1 100644 --- a/OSX/utilities/SecXPCHelper.h +++ b/OSX/utilities/SecXPCHelper.h @@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN * Some NSError objects contain non-NSSecureCoding-compliant userInfo. * When in doubt, use cleanseErrorForXPC: before encodedDataFromError: */ -+ (NSError *)errorFromEncodedData:(NSData *)data; ++ (NSError * _Nullable)errorFromEncodedData:(NSData *)data; + (NSData *)encodedDataFromError:(NSError *)error; @end diff --git a/OSX/utilities/SecXPCHelper.m b/OSX/utilities/SecXPCHelper.m index 5980d182..73e3cf32 100644 --- a/OSX/utilities/SecXPCHelper.m +++ b/OSX/utilities/SecXPCHelper.m @@ -35,6 +35,32 @@ return errorClasses; } ++ (NSSet *)safeCKErrorPrimitiveClasses +{ + static NSMutableSet *errorClasses = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + errorClasses = [NSMutableSet set]; + char *classes[] = { + "CKArchivedAnchoredPackage", + "CKAsset", + "CKPackage", + "CKRecordID", + "CKReference", + "CLLocation", + }; + + for (unsigned n = 0; n < sizeof(classes) / sizeof(classes[0]); n++) { + Class class = objc_getClass(classes[n]); + if (class) { + [errorClasses addObject:class]; + } + } + }); + + return errorClasses; +} + + (NSSet *)safeErrorCollectionClasses { static NSMutableSet *errorClasses = nil; @@ -47,6 +73,7 @@ "NSError", "NSOrderedSet", "NSSet", + "NSURLError", }; for (unsigned n = 0; n < sizeof(classes) / sizeof(classes[0]); n++) { @@ -69,6 +96,9 @@ for (Class class in [SecXPCHelper safeErrorPrimitiveClasses]) { [errorClasses addObject:class]; } + for (Class class in [SecXPCHelper safeCKErrorPrimitiveClasses]) { + [errorClasses addObject:class]; + } for (Class class in [SecXPCHelper safeErrorCollectionClasses]) { [errorClasses addObject:class]; } @@ -155,7 +185,7 @@ static NSString *kArchiveKeyError = @"error"; -+ (NSError *)errorFromEncodedData:(NSData *)data ++ (NSError * _Nullable)errorFromEncodedData:(NSData *)data { NSKeyedUnarchiver *unarchiver = nil; NSError *error = nil; diff --git a/OSX/utilities/debugging.c b/OSX/utilities/debugging.c index 14695726..b0bd2ce1 100644 --- a/OSX/utilities/debugging.c +++ b/OSX/utilities/debugging.c @@ -215,13 +215,6 @@ static int string_to_log_level(CFStringRef string) { return -1; } -static void CFSetAppendValues(CFSetRef set, CFMutableArrayRef appendTo) -{ - CFSetForEach(set, ^(const void *value) { - CFArrayAppendValue(appendTo, value); - }); -} - static CFMutableArrayRef CFSetOfCFObjectsCopyValues(CFSetRef setOfCFs) { CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); @@ -401,18 +394,6 @@ void __security_debug_init(void) { } - - -static char *copyScopeStr(CFStringRef scope, char *alternative) { - char *scopeStr = NULL; - if(scope) { - scopeStr = CFStringToCString(scope); - } else { - scopeStr = strdup("noScope"); - } - return scopeStr; -} - os_log_t secLogObjForCFScope(CFStringRef scope) { diff --git a/OSX/utilities/debugging.h b/OSX/utilities/debugging.h index 52769f19..caa2b9c2 100644 --- a/OSX/utilities/debugging.h +++ b/OSX/utilities/debugging.h @@ -144,6 +144,9 @@ void __security_stackshotreport(CFStringRef reason, uint32_t code); #define __sec_exception_code_SQLiteBusy __sec_exception_code(10) #define __sec_exception_code_CorruptDb(rc) __sec_exception_code(11|((rc)<<8)) #define __sec_exception_code_Watchdog __sec_exception_code(12) +#define __sec_exception_code_BadStash __sec_exception_code(13) +#define __sec_exception_code_UnexpectedState __sec_exception_code(14) +#define __sec_exception_code_RateLimit __sec_exception_code(15) /* For testing only, turns off/on simulated crashes, when turning on, returns number of simulated crashes which were not reported since last turned off. */ diff --git a/OSX/utilities/der_array.c b/OSX/utilities/der_array.c index 95eaf95e..77885476 100644 --- a/OSX/utilities/der_array.c +++ b/OSX/utilities/der_array.c @@ -32,21 +32,26 @@ #include -const uint8_t* der_decode_array(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_array(CFAllocatorRef allocator, CFArrayRef* array, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } CFMutableArrayRef result = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); const uint8_t *elements_end; const uint8_t *current_element = ccder_decode_sequence_tl(&elements_end, der, der_end); + if (!current_element) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("tag/length decode failed"), NULL, error); + } while (current_element != NULL && current_element < elements_end) { CFPropertyListRef element = NULL; - current_element = der_decode_plist(allocator, mutability, &element, error, current_element, elements_end); + current_element = der_decode_plist(allocator, &element, error, current_element, elements_end); if (current_element) { CFArrayAppendValue(result, element); CFReleaseNull(element); @@ -86,6 +91,7 @@ uint8_t* der_encode_array(CFArrayRef array, CFErrorRef *error, { der_end = der_encode_plist(CFArrayGetValueAtIndex(array, position), error, der, der_end); } - - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, der_end); + + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, der_end), + error); } diff --git a/OSX/utilities/der_boolean.c b/OSX/utilities/der_boolean.c index 986c3132..0ab42b49 100644 --- a/OSX/utilities/der_boolean.c +++ b/OSX/utilities/der_boolean.c @@ -32,12 +32,14 @@ #include -const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFBooleanRef* boolean, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); @@ -64,7 +66,8 @@ uint8_t* der_encode_boolean(CFBooleanRef boolean, CFErrorRef *error, { uint8_t value = CFBooleanGetValue(boolean); - return ccder_encode_tl(CCDER_BOOLEAN, 1, der, - ccder_encode_body(1, &value, der, der_end)); + return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_BOOLEAN, 1, der, + ccder_encode_body(1, &value, der, der_end)), + error); } diff --git a/OSX/utilities/der_data.c b/OSX/utilities/der_data.c index b29ddfe0..83bdcec6 100644 --- a/OSX/utilities/der_data.c +++ b/OSX/utilities/der_data.c @@ -32,40 +32,14 @@ #include -const uint8_t* der_decode_data_mutable(CFAllocatorRef allocator, CFOptionFlags mutability, - CFMutableDataRef* data, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - size_t payload_size = 0; - const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end); - - if (NULL == payload || (ssize_t) (der_end - payload) < (ssize_t) payload_size) { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding"), NULL, error); - return NULL; - } - - *data = CFDataCreateMutable(allocator, 0); - - if (NULL == *data) { - SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Failed to create data"), NULL, error); - return NULL; - } - - CFDataAppendBytes(*data, payload, payload_size); - - return payload + payload_size; -} - - -const uint8_t* der_decode_data(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_data(CFAllocatorRef allocator, CFDataRef* data, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end); @@ -97,7 +71,8 @@ uint8_t* der_encode_data(CFDataRef data, CFErrorRef *error, { const CFIndex data_length = CFDataGetLength(data); - return ccder_encode_tl(CCDER_OCTET_STRING, data_length, der, - ccder_encode_body(data_length, CFDataGetBytePtr(data), der, der_end)); + return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_OCTET_STRING, data_length, der, + ccder_encode_body(data_length, CFDataGetBytePtr(data), der, der_end)), + error); } diff --git a/OSX/utilities/der_date.c b/OSX/utilities/der_date.c index 0bdde9cc..d930f660 100644 --- a/OSX/utilities/der_date.c +++ b/OSX/utilities/der_date.c @@ -39,13 +39,26 @@ /* Cumulative number of days in the year for months up to month i. */ static int mdays[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; +static bool validateDateComponents(int year, int month, int day, int hour, int minute, int second, int *is_leap_year, CFErrorRef* error) +{ + int leapyear = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) ? 1 : 0; + if (is_leap_year) { + *is_leap_year = leapyear; + } + if (month < 1 || month > 12 || day < 1 || day > 31 || hour >= 24 || minute >= 60 || second > 61 + || (month == 2 && day > mdays[month] - mdays[month - 1] + leapyear) + || (month != 2 && day > mdays[month] - mdays[month - 1])) + { + SecError(kSecDERErrorUnknownEncoding, error, CFSTR("Invalid date: %i, %i, %i, %i, %i, %i, %i"), year, month, day, hour, minute, second, leapyear); + return false; + } + + return true; +} + static CFAbsoluteTime SecGregorianDateGetAbsoluteTime(int year, int month, int day, int hour, int minute, int second, CFTimeInterval timeZoneOffset, CFErrorRef *error) { - int is_leap_year = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) ? 1 : 0; - if (month < 1 || month > 12 || day < 1 || day > 31 || hour >= 24 || minute >= 60 || second >= 60.0 - || (month == 2 && day > mdays[month] - mdays[month - 1] + is_leap_year) - || (month != 2 && day > mdays[month] - mdays[month - 1])) { - /* Invalid date. */ - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Invalid date."), 0, error); + int is_leap_year = 0; + if (!validateDateComponents(year, month, day, hour, minute, second, &is_leap_year, error)) { return NULL_TIME; } @@ -72,8 +85,10 @@ static bool SecAbsoluteTimeGetGregorianDate(CFTimeInterval at, int *year, int *m SecCFCalendarDoWithZuluCalendar(^(CFCalendarRef zuluCalendar) { result = CFCalendarDecomposeAbsoluteTime(zuluCalendar, at, "yMdHms", year, month, day, hour, minute, second); }); - if (!result) + if (!result) { SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Failed to encode date."), 0, error); + } + return result; } @@ -144,9 +159,11 @@ static const uint8_t *der_decode_decimal_fraction(double *fraction, CFErrorRef * value += (ch - '0'); } } - if (der >= der_end) + if (der >= der_end) { + SecCFDERCreateError(kSecDERErrorOverflow, + CFSTR("overflow"), 0, error); der = NULL; - else if (last == '0') { + } else if (last == '0') { SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("fraction ends in 0"), 0, error); der = NULL; @@ -205,14 +222,6 @@ static const uint8_t* der_decode_commontime_body(CFAbsoluteTime *at, CFErrorRef CFTimeInterval timeZoneOffset = der_decode_timezone_offset(&der, der_end, error); -#if 0 - secinfo("dateparse", - "date %.*s year: %04d%02d%02d%02d%02d%02d%+05g", - length, bytes, g.year, g.month, - g.day, g.hour, g.minute, g.second, - timeZoneOffset / 60); -#endif - if (der) { if (der != der_end) { SecCFDERCreateError(kSecDERErrorUnknownEncoding, @@ -257,12 +266,14 @@ const uint8_t* der_decode_universaltime_body(CFAbsoluteTime *at, CFErrorRef *err return der_decode_commontime_body(at, error, year, der, der_end); } -const uint8_t* der_decode_date(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_date(CFAllocatorRef allocator, CFDateRef* date, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } der = ccder_decode_constructed_tl(CCDER_GENERALIZED_TIME, &der_end, der, der_end); CFAbsoluteTime at = 0; @@ -373,13 +384,38 @@ static uint8_t *ccder_encode_nanoseconds(CFAbsoluteTime at, const uint8_t *der, return der_end; } -/* Encode generalized zulu time YYYYMMDDhhmmss[.ssss]Z */ uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) +{ + return der_encode_generalizedtime_body_repair(at, error, false, der, der_end); +} + +/* Encode generalized zulu time YYYYMMDDhhmmss[.ssss]Z */ +uint8_t* der_encode_generalizedtime_body_repair(CFAbsoluteTime at, CFErrorRef *error, bool repair, + const uint8_t *der, uint8_t *der_end) { int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; - if (!SecAbsoluteTimeGetGregorianDate(at, &year, &month, &day, &hour, &minute, &second, error)) + if (!SecAbsoluteTimeGetGregorianDate(at, &year, &month, &day, &hour, &minute, &second, error)) { + secerror("der: unable to encode date: %@", error ? *error : NULL); return NULL; + } + + // Without repair flag, do not let validation change result so we do not change existing behavior + CFErrorRef localError = NULL; + if (!validateDateComponents(year, month, day, hour, minute, second, 0, &localError)) { + CFStringRef desc = CFErrorCopyDescription(localError); + __security_simulatecrash(desc, __sec_exception_code_CorruptItem); + CFReleaseNull(desc); + secerror("der: invalid date: %@; %s", localError, repair ? "setting default value" : "continuing"); + CFReleaseNull(localError); + if (repair) { + year = 2001; + month = 1; + day = 1; + // I don't think this is required but I don't want any funny business with exactly midnight in any timezone + minute = 1; + } + } uint8_t * result = ccder_encode_decimal_quad(year, der, ccder_encode_decimal_pair(month, der, @@ -387,17 +423,18 @@ uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, ccder_encode_decimal_pair(hour, der, ccder_encode_decimal_pair(minute, der, ccder_encode_decimal_pair(second, der, - ccder_encode_nanoseconds(at, der, + ccder_encode_nanoseconds(at, der, // Uses original "at" even after repair because DER length calculations depend on its exact value ccder_encode_byte('Z', der, der_end)))))))); - return result; + return SecCCDEREncodeHandleResult(result, error); } uint8_t* der_encode_generalizedtime(CFAbsoluteTime at, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { - return ccder_encode_constructed_tl(CCDER_GENERALIZED_TIME, der_end, der, - der_encode_generalizedtime_body(at, error, der, der_end)); + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_GENERALIZED_TIME, der_end, der, + der_encode_generalizedtime_body(at, error, der, der_end)), + error); } @@ -407,3 +444,11 @@ uint8_t* der_encode_date(CFDateRef date, CFErrorRef *error, return der_encode_generalizedtime(CFDateGetAbsoluteTime(date), error, der, der_end); } + +uint8_t* der_encode_date_repair(CFDateRef date, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end) +{ + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_GENERALIZED_TIME, der_end, der, + der_encode_generalizedtime_body_repair(CFDateGetAbsoluteTime(date), error, repair, der, der_end)), + error); +} diff --git a/OSX/utilities/der_date.h b/OSX/utilities/der_date.h index 327ea7de..a92871b6 100644 --- a/OSX/utilities/der_date.h +++ b/OSX/utilities/der_date.h @@ -39,5 +39,7 @@ uint8_t* der_encode_generalizedtime(CFAbsoluteTime at, CFErrorRef *error, size_t der_sizeof_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error); uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); +uint8_t* der_encode_generalizedtime_body_repair(CFAbsoluteTime at, CFErrorRef *error, bool repair, + const uint8_t *der, uint8_t *der_end); #endif /* _UTILITIES_DER_DATE_H_ */ diff --git a/OSX/utilities/der_dictionary.c b/OSX/utilities/der_dictionary.c index bb002953..6c080d03 100644 --- a/OSX/utilities/der_dictionary.c +++ b/OSX/utilities/der_dictionary.c @@ -32,7 +32,7 @@ #include #include -static const uint8_t* der_decode_key_value(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_key_value(CFAllocatorRef allocator, CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { @@ -48,8 +48,8 @@ static const uint8_t* der_decode_key_value(CFAllocatorRef allocator, CFOptionFla CFTypeRef valueObject = NULL; - payload = der_decode_plist(allocator, mutability, &keyObject, error, payload, payload_end); - payload = der_decode_plist(allocator, mutability, &valueObject, error, payload, payload_end); + payload = der_decode_plist(allocator, &keyObject, error, payload, payload_end); + payload = der_decode_plist(allocator, &valueObject, error, payload, payload_end); if (payload != NULL) { *key = keyObject; @@ -61,12 +61,14 @@ static const uint8_t* der_decode_key_value(CFAllocatorRef allocator, CFOptionFla return payload; } -const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFDictionaryRef* dictionary, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } const uint8_t *payload_end = 0; const uint8_t *payload = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SET, &payload_end, der, der_end); @@ -89,7 +91,7 @@ const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFOptionFlags mut CFTypeRef key = NULL; CFTypeRef value = NULL; - payload = der_decode_key_value(allocator, mutability, &key, &value, error, payload, payload_end); + payload = der_decode_key_value(allocator, &key, &value, error, payload, payload_end); if (payload) { CFDictionaryAddValue(dict, key, value); @@ -120,10 +122,12 @@ struct size_context { static size_t der_sizeof_key_value(CFTypeRef key, CFTypeRef value, CFErrorRef *error) { size_t key_size = der_sizeof_plist(key, error); if (key_size == 0) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return 0; } size_t value_size = der_sizeof_plist(value, error); if (value_size == 0) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return 0; } return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, key_size + value_size); @@ -163,9 +167,10 @@ size_t der_sizeof_dictionary(CFDictionaryRef dict, CFErrorRef *error) static uint8_t* der_encode_key_value(CFPropertyListRef key, CFPropertyListRef value, CFErrorRef *error, const uint8_t* der, uint8_t *der_end) { - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - der_encode_plist(key, error, der, - der_encode_plist(value, error, der, der_end))); + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + der_encode_plist(key, error, der, + der_encode_plist(value, error, der, der_end))), + error); } struct encode_context { @@ -206,9 +211,9 @@ static void add_sequence_to_array(const void *key_void, const void *value_void, } } -static CFComparisonResult cfdata_compare_contents(const void *val1, const void *val2, void *context __unused) +static CFComparisonResult cfdata_compare_der_contents(const void *val1, const void *val2, void *context __unused) { - return CFDataCompare((CFDataRef) val1, (CFDataRef) val2); + return CFDataCompareDERData((CFDataRef) val1, (CFDataRef) val2); } @@ -227,7 +232,7 @@ uint8_t* der_encode_dictionary(CFDictionaryRef dictionary, CFErrorRef *error, CFRange allOfThem = CFRangeMake(0, CFArrayGetCount(elements)); - CFArraySortValues(elements, allOfThem, cfdata_compare_contents, NULL); + CFArraySortValues(elements, allOfThem, cfdata_compare_der_contents, NULL); uint8_t* original_der_end = der_end; @@ -239,6 +244,7 @@ uint8_t* der_encode_dictionary(CFDictionaryRef dictionary, CFErrorRef *error, CFReleaseNull(elements); - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SET, original_der_end, der, der_end); + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SET, original_der_end, der, der_end), + error); } diff --git a/OSX/utilities/der_null.c b/OSX/utilities/der_null.c index b462a031..de3c0bf6 100644 --- a/OSX/utilities/der_null.c +++ b/OSX/utilities/der_null.c @@ -32,12 +32,14 @@ #include -const uint8_t* der_decode_null(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_null(CFAllocatorRef allocator, CFNullRef* nul, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_NULL, &payload_size, der, der_end); @@ -62,5 +64,6 @@ size_t der_sizeof_null(CFNullRef data __unused, CFErrorRef *error) uint8_t* der_encode_null(CFNullRef boolean __unused, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { - return ccder_encode_tl(CCDER_NULL, 0, der, der_end); + return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_NULL, 0, der, der_end), + error); } diff --git a/OSX/utilities/der_number.c b/OSX/utilities/der_number.c index 29560a71..c47ce8a2 100644 --- a/OSX/utilities/der_number.c +++ b/OSX/utilities/der_number.c @@ -33,12 +33,14 @@ #include -const uint8_t* der_decode_number(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_number(CFAllocatorRef allocator, CFNumberRef* number, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_INTEGER, &payload_size, der, der_end); @@ -50,7 +52,6 @@ const uint8_t* der_decode_number(CFAllocatorRef allocator, CFOptionFlags mutabil if (payload_size > sizeof(long long)) { SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Number too large"), NULL, error); return NULL; - } long long value = 0; @@ -107,8 +108,10 @@ static inline size_t bytes_when_encoded(long long value) size_t der_sizeof_number(CFNumberRef data, CFErrorRef *error) { long long value; - if (!CFNumberGetValue(data, kCFNumberLongLongType, &value)) + if (!CFNumberGetValue(data, kCFNumberLongLongType, &value)) { + SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Unable to get number from data"), NULL, error); return 0; + } return ccder_sizeof(CCDER_INTEGER, bytes_when_encoded(value)); } @@ -117,13 +120,17 @@ uint8_t* der_encode_number(CFNumberRef number, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { long long value; - if (!CFNumberGetValue(number, kCFNumberLongLongType, &value)) + if (!CFNumberGetValue(number, kCFNumberLongLongType, &value)) { + SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Unable to get number from data"), NULL, error); return NULL; + } size_t first_byte_to_include = bytes_when_encoded(value); - if (!der_end || (ssize_t) (der_end - der) < (ssize_t) first_byte_to_include) + if (!der_end || (ssize_t) (der_end - der) < (ssize_t) first_byte_to_include) { + SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Unknown size"), NULL, error); return NULL; + } // Put the bytes we should include on the end. for(size_t bytes_included = 0; bytes_included < first_byte_to_include; ++bytes_included) @@ -133,6 +140,7 @@ uint8_t* der_encode_number(CFNumberRef number, CFErrorRef *error, value >>= 8; } - return ccder_encode_tl(CCDER_INTEGER, first_byte_to_include, der, der_end); + return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_INTEGER, first_byte_to_include, der, der_end), + error); } diff --git a/OSX/utilities/der_plist.c b/OSX/utilities/der_plist.c index e053c3f4..0a0f3476 100644 --- a/OSX/utilities/der_plist.c +++ b/OSX/utilities/der_plist.c @@ -31,6 +31,8 @@ #include #include +#include "utilities/simulatecrash_assert.h" + // // der..CFPropertyList // @@ -48,35 +50,40 @@ // // -const uint8_t* der_decode_plist(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_plist(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) -{ if (NULL == der) - return NULL; +{ + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); + return NULL; + } ccder_tag tag; - if (NULL == ccder_decode_tag(&tag, der, der_end)) + if (NULL == ccder_decode_tag(&tag, der, der_end)) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("invalid tag"), NULL, error); return NULL; + } switch (tag) { case CCDER_NULL: - return der_decode_null(allocator, mutability, (CFNullRef*)pl, error, der, der_end); + return der_decode_null(allocator, (CFNullRef*)pl, error, der, der_end); case CCDER_BOOLEAN: - return der_decode_boolean(allocator, mutability, (CFBooleanRef*)pl, error, der, der_end); + return der_decode_boolean(allocator, (CFBooleanRef*)pl, error, der, der_end); case CCDER_OCTET_STRING: - return der_decode_data(allocator, mutability, (CFDataRef*)pl, error, der, der_end); + return der_decode_data(allocator, (CFDataRef*)pl, error, der, der_end); case CCDER_GENERALIZED_TIME: - return der_decode_date(allocator, mutability, (CFDateRef*)pl, error, der, der_end); + return der_decode_date(allocator, (CFDateRef*)pl, error, der, der_end); case CCDER_CONSTRUCTED_SEQUENCE: - return der_decode_array(allocator, mutability, (CFArrayRef*)pl, error, der, der_end); + return der_decode_array(allocator, (CFArrayRef*)pl, error, der, der_end); case CCDER_UTF8_STRING: - return der_decode_string(allocator, mutability, (CFStringRef*)pl, error, der, der_end); + return der_decode_string(allocator, (CFStringRef*)pl, error, der, der_end); case CCDER_INTEGER: - return der_decode_number(allocator, mutability, (CFNumberRef*)pl, error, der, der_end); + return der_decode_number(allocator, (CFNumberRef*)pl, error, der, der_end); case CCDER_CONSTRUCTED_SET: - return der_decode_dictionary(allocator, mutability, (CFDictionaryRef*)pl, error, der, der_end); + return der_decode_dictionary(allocator, (CFDictionaryRef*)pl, error, der, der_end); case CCDER_CONSTRUCTED_CFSET: - return der_decode_set(allocator, mutability, (CFSetRef*)pl, error, der, der_end); + return der_decode_set(allocator, (CFSetRef*)pl, error, der, der_end); default: SecCFDERCreateError(kSecDERErrorUnsupportedDERType, CFSTR("Unsupported DER Type"), NULL, error); return NULL; @@ -109,17 +116,22 @@ size_t der_sizeof_plist(CFPropertyListRef pl, CFErrorRef *error) return der_sizeof_string((CFStringRef) pl, error); else if (CFNumberGetTypeID() == dataType) return der_sizeof_number((CFNumberRef) pl, error); - if (CFNullGetTypeID() == dataType) - return der_sizeof_null((CFNullRef) pl, error); - else { + else if (CFNullGetTypeID() == dataType) + return der_sizeof_null((CFNullRef) pl, error); + else { SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("Unsupported CFType"), NULL, error); return 0; } } - uint8_t* der_encode_plist(CFPropertyListRef pl, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) +{ + return der_encode_plist_repair(pl, error, false, der, der_end); +} + +uint8_t* der_encode_plist_repair(CFPropertyListRef pl, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end) { if (!pl) { SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("Null CFType"), NULL, error); @@ -135,7 +147,7 @@ uint8_t* der_encode_plist(CFPropertyListRef pl, CFErrorRef *error, else if (CFDataGetTypeID() == dataType) return der_encode_data((CFDataRef) pl, error, der, der_end); else if (CFDateGetTypeID() == dataType) - return der_encode_date((CFDateRef) pl, error, der, der_end); + return der_encode_date_repair((CFDateRef) pl, error, repair, der, der_end); else if (CFDictionaryGetTypeID() == dataType) return der_encode_dictionary((CFDictionaryRef) pl, error, der, der_end); else if (CFSetGetTypeID() == dataType) @@ -144,8 +156,8 @@ uint8_t* der_encode_plist(CFPropertyListRef pl, CFErrorRef *error, return der_encode_string((CFStringRef) pl, error, der, der_end); else if (CFNumberGetTypeID() == dataType) return der_encode_number((CFNumberRef) pl, error, der, der_end); - else if (CFNullGetTypeID() == dataType) - return der_encode_null((CFNullRef) pl, error, der, der_end); + else if (CFNullGetTypeID() == dataType) + return der_encode_null((CFNullRef) pl, error, der, der_end); else { SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("Unsupported CFType"), NULL, error); return NULL; @@ -174,7 +186,7 @@ CFPropertyListRef CFPropertyListCreateWithDERData(CFAllocatorRef allocator, CFDa CFPropertyListRef plist = NULL; const uint8_t *der = CFDataGetBytePtr(data); const uint8_t *der_end = der + CFDataGetLength(data); - der = der_decode_plist(0, kCFPropertyListMutableContainers, &plist, error, der, der_end); + der = der_decode_plist(0, &plist, error, der, der_end); if (der && der != der_end) { SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("trailing garbage after plist item"), NULL, error); CFReleaseNull(plist); diff --git a/OSX/utilities/der_plist.h b/OSX/utilities/der_plist.h index 36629478..109e082f 100644 --- a/OSX/utilities/der_plist.h +++ b/OSX/utilities/der_plist.h @@ -40,6 +40,9 @@ static const CFIndex kSecDERErrorUnsupportedDERType = -2; static const CFIndex kSecDERErrorAllocationFailure = -3; static const CFIndex kSecDERErrorUnsupportedNumberType = -4; static const CFIndex kSecDERErrorUnsupportedCFObject = -5; +static const CFIndex kSecDERErrorNullInput = -6; +static const CFIndex kSecDERErrorCCDEREncode = -7; +static const CFIndex kSecDERErrorOverflow = -8; extern CFStringRef sSecDERErrorDomain; @@ -55,7 +58,11 @@ size_t der_sizeof_plist(CFPropertyListRef pl, CFErrorRef *error); uint8_t* der_encode_plist(CFPropertyListRef pl, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_plist(CFAllocatorRef pl, CFOptionFlags mutability, +// When allowed to repair, if certain objects (right now only Dates) do not validate, set them to recognizable defaults +uint8_t* der_encode_plist_repair(CFPropertyListRef pl, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end); + +const uint8_t* der_decode_plist(CFAllocatorRef pl, CFPropertyListRef* cf, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); diff --git a/OSX/utilities/der_plist_internal.c b/OSX/utilities/der_plist_internal.c index 017834f1..5b1041b4 100644 --- a/OSX/utilities/der_plist_internal.c +++ b/OSX/utilities/der_plist_internal.c @@ -25,6 +25,15 @@ #include "utilities/der_plist_internal.h" #include "utilities/SecCFError.h" #include "utilities/SecCFRelease.h" +#include "utilities/der_plist.h" #include CFStringRef sSecDERErrorDomain = CFSTR("com.apple.security.cfder.error"); + +uint8_t * SecCCDEREncodeHandleResult(uint8_t *der, CFErrorRef *newError) +{ + if (!der) { + SecCFDERCreateError(kSecDERErrorCCDEREncode, CFSTR("ccder failed to encode"), NULL, newError); + } + return der; +} diff --git a/OSX/utilities/der_plist_internal.h b/OSX/utilities/der_plist_internal.h index 6b334d8e..e604f089 100644 --- a/OSX/utilities/der_plist_internal.h +++ b/OSX/utilities/der_plist_internal.h @@ -32,6 +32,8 @@ #define SecCFDERCreateError(errorCode, descriptionString, previousError, newError) \ SecCFCreateErrorWithFormat(errorCode, sSecDERErrorDomain, previousError, newError, NULL, descriptionString) +uint8_t * SecCCDEREncodeHandleResult(uint8_t *der, CFErrorRef *newError); + // CFArray <-> DER size_t der_sizeof_array(CFArrayRef array, CFErrorRef *error); @@ -39,7 +41,7 @@ size_t der_sizeof_array(CFArrayRef array, CFErrorRef *error); uint8_t* der_encode_array(CFArrayRef array, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_array(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_array(CFAllocatorRef allocator, CFArrayRef* array, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -49,7 +51,7 @@ size_t der_sizeof_null(CFNullRef nul, CFErrorRef *error); uint8_t* der_encode_null(CFNullRef nul, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_null(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_null(CFAllocatorRef allocator, CFNullRef *nul, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -60,7 +62,7 @@ size_t der_sizeof_boolean(CFBooleanRef boolean, CFErrorRef *error); uint8_t* der_encode_boolean(CFBooleanRef boolean, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFBooleanRef* boolean, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -70,22 +72,20 @@ size_t der_sizeof_data(CFDataRef data, CFErrorRef *error); uint8_t* der_encode_data(CFDataRef data, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_data(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_data(CFAllocatorRef allocator, CFDataRef* data, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); -const uint8_t* der_decode_data_mutable(CFAllocatorRef allocator, CFOptionFlags mutability, - CFMutableDataRef* data, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end); - - // CFDate <-> DER size_t der_sizeof_date(CFDateRef date, CFErrorRef *error); uint8_t* der_encode_date(CFDateRef date, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_date(CFAllocatorRef allocator, CFOptionFlags mutability, +uint8_t* der_encode_date_repair(CFDateRef date, CFErrorRef *error, + bool repair, const uint8_t *der, uint8_t *der_end); + +const uint8_t* der_decode_date(CFAllocatorRef allocator, CFDateRef* date, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -96,7 +96,7 @@ size_t der_sizeof_dictionary(CFDictionaryRef dictionary, CFErrorRef *error); uint8_t* der_encode_dictionary(CFDictionaryRef dictionary, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFDictionaryRef* dictionary, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -107,7 +107,7 @@ size_t der_sizeof_number(CFNumberRef number, CFErrorRef *error); uint8_t* der_encode_number(CFNumberRef number, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_number(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_number(CFAllocatorRef allocator, CFNumberRef* number, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -117,7 +117,7 @@ size_t der_sizeof_string(CFStringRef string, CFErrorRef *error); uint8_t* der_encode_string(CFStringRef string, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_string(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_string(CFAllocatorRef allocator, CFStringRef* string, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); @@ -127,7 +127,7 @@ size_t der_sizeof_set(CFSetRef dict, CFErrorRef *error); uint8_t* der_encode_set(CFSetRef set, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); -const uint8_t* der_decode_set(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_set(CFAllocatorRef allocator, CFSetRef* set, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); diff --git a/OSX/utilities/der_set.c b/OSX/utilities/der_set.c index 8bf2a895..4a3377f8 100644 --- a/OSX/utilities/der_set.c +++ b/OSX/utilities/der_set.c @@ -33,12 +33,14 @@ #include #include -const uint8_t* der_decode_set(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_set(CFAllocatorRef allocator, CFSetRef* set, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } const uint8_t *payload_end = 0; const uint8_t *payload = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_CFSET, &payload_end, der, der_end); @@ -60,7 +62,7 @@ const uint8_t* der_decode_set(CFAllocatorRef allocator, CFOptionFlags mutability while (payload != NULL && payload < payload_end) { CFTypeRef value = NULL; - payload = der_decode_plist(allocator, mutability, &value, error, payload, payload_end); + payload = der_decode_plist(allocator, &value, error, payload, payload_end); if (payload) { CFSetAddValue(theSet, value); @@ -148,9 +150,9 @@ static void add_sequence_to_array(const void *value_void, void *context_void) } } -static CFComparisonResult cfdata_compare_contents(const void *val1, const void *val2, void *context __unused) +static CFComparisonResult cfdata_compare_der_contents(const void *val1, const void *val2, void *context __unused) { - return CFDataCompare((CFDataRef) val1, (CFDataRef) val2); + return CFDataCompareDERData((CFDataRef) val1, (CFDataRef) val2); } @@ -169,7 +171,7 @@ uint8_t* der_encode_set(CFSetRef set, CFErrorRef *error, CFRange allOfThem = CFRangeMake(0, CFArrayGetCount(elements)); - CFArraySortValues(elements, allOfThem, cfdata_compare_contents, NULL); + CFArraySortValues(elements, allOfThem, cfdata_compare_der_contents, NULL); uint8_t* original_der_end = der_end; @@ -181,6 +183,7 @@ uint8_t* der_encode_set(CFSetRef set, CFErrorRef *error, CFReleaseNull(elements); - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_CFSET, original_der_end, der, der_end); + return SecCCDEREncodeHandleResult(ccder_encode_constructed_tl(CCDER_CONSTRUCTED_CFSET, original_der_end, der, der_end), + error); } diff --git a/OSX/utilities/der_set.h b/OSX/utilities/der_set.h index d02dfd01..bd8329bb 100644 --- a/OSX/utilities/der_set.h +++ b/OSX/utilities/der_set.h @@ -14,7 +14,7 @@ #include // If you provide a set in *set, we will add elements to it and return the union. -const uint8_t* der_decode_set(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_set(CFAllocatorRef allocator, CFSetRef* set, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end); diff --git a/OSX/utilities/der_string.c b/OSX/utilities/der_string.c index 2f0c5dc0..972a1206 100644 --- a/OSX/utilities/der_string.c +++ b/OSX/utilities/der_string.c @@ -32,12 +32,14 @@ #include -const uint8_t* der_decode_string(CFAllocatorRef allocator, CFOptionFlags mutability, +const uint8_t* der_decode_string(CFAllocatorRef allocator, CFStringRef* string, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - if (NULL == der) + if (NULL == der) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } size_t payload_size = 0; const uint8_t *payload = ccder_decode_tl(CCDER_UTF8_STRING, &payload_size, der, der_end); @@ -73,9 +75,10 @@ size_t der_sizeof_string(CFStringRef str, CFErrorRef *error) uint8_t* der_encode_string(CFStringRef string, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { - // Obey the NULL allowed rules. - if (!der_end) + if (NULL == der_end) { + SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error); return NULL; + } const CFIndex str_length = CFStringGetLength(string); @@ -88,7 +91,8 @@ uint8_t* der_encode_string(CFStringRef string, CFErrorRef *error, return NULL; } - return ccder_encode_tl(CCDER_UTF8_STRING, bytes_used, der, - ccder_encode_body(bytes_used, buffer, der, der_end)); + return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_UTF8_STRING, bytes_used, der, + ccder_encode_body(bytes_used, buffer, der, der_end)), + error); } diff --git a/OSX/utilities/entitlements.c b/OSX/utilities/entitlements.c new file mode 100644 index 00000000..bffbe6fb --- /dev/null +++ b/OSX/utilities/entitlements.c @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2020 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@ +*/ + +#include "entitlements.h" + +/// Moves the entitlement value from the original entitlement into the target entitlement. +static void transferEntitlement(CFMutableDictionaryRef entitlements, CFStringRef originalEntitlement, CFStringRef targetEntitlement) +{ + CFTypeRef value = (CFStringRef)CFDictionaryGetValue(entitlements, originalEntitlement); + CFDictionaryAddValue(entitlements, targetEntitlement, value); +} + +/// Determines if an entitlement needs fixup, which means it has a value for the original entitlement and no value for the +/// target entitlement. +static bool entitlementNeedsFixup(CFDictionaryRef entitlements, CFStringRef originalEntitlement, CFStringRef targetEntitlement) +{ + // Entitlements only need fixup on macOS running on Apple Silicon, so just always fall through to the default case otherwise. +#if TARGET_OS_OSX && TARGET_CPU_ARM64 + CFTypeRef originalValue = (CFStringRef)CFDictionaryGetValue(entitlements, originalEntitlement); + CFTypeRef newValue = (CFStringRef)CFDictionaryGetValue(entitlements, targetEntitlement); + if (originalValue != NULL && newValue == NULL) { + return true; + } +#endif + return false; +} + +bool needsCatalystEntitlementFixup(CFDictionaryRef entitlements) +{ + return entitlementNeedsFixup(entitlements, CFSTR("application-identifier"), CFSTR("com.apple.application-identifier")) || + entitlementNeedsFixup(entitlements, CFSTR("aps-environment"), CFSTR("com.apple.developer.aps-environment")); +} + +bool updateCatalystEntitlements(CFMutableDictionaryRef entitlements) +{ + bool updated = false; + if (entitlementNeedsFixup(entitlements, CFSTR("application-identifier"), CFSTR("com.apple.application-identifier"))) { + transferEntitlement(entitlements, CFSTR("application-identifier"), CFSTR("com.apple.application-identifier")); + updated = true; + } + if (entitlementNeedsFixup(entitlements, CFSTR("aps-environment"), CFSTR("com.apple.developer.aps-environment"))) { + transferEntitlement(entitlements, CFSTR("aps-environment"), CFSTR("com.apple.developer.aps-environment")); + updated = true; + } + return updated; +} diff --git a/OSX/utilities/entitlements.h b/OSX/utilities/entitlements.h new file mode 100644 index 00000000..427f0bc6 --- /dev/null +++ b/OSX/utilities/entitlements.h @@ -0,0 +1,41 @@ +/* +* Copyright (c) 2020 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@ +*/ + +#ifndef _utilities_entitlements_h +#define _utilities_entitlements_h + +#include +#include + +__BEGIN_DECLS + +/// Checks an entitlement dictionary to determine if any Catalyst-related entitlements need to be updated. +bool needsCatalystEntitlementFixup(CFDictionaryRef entitlements); + +/// Modifies an entitlements dictionary to add the necessary Catalyst-related entitlements based on pre-existing entitlements. +/// Returns whether the entitlements were modified. +bool updateCatalystEntitlements(CFMutableDictionaryRef entitlements); + +__END_DECLS + +#endif /* _utilities_entitlements_h */ diff --git a/OSX/utilities/simulate_crash.m b/OSX/utilities/simulate_crash.m index 197dfe35..0a41470c 100644 --- a/OSX/utilities/simulate_crash.m +++ b/OSX/utilities/simulate_crash.m @@ -11,7 +11,7 @@ #import #import -SOFT_LINK_FRAMEWORK_SAFE(PrivateFrameworks, CrashReporterSupport); +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CrashReporterSupport); SOFT_LINK_FUNCTION(CrashReporterSupport, SimulateCrash, soft_SimulateCrash, \ BOOL, (pid_t pid, mach_exception_data_type_t exceptionCode, NSString *description), diff --git a/keychain/SigninMetrics/SFSignInAnalytics+Internal.h b/OSX/utilities/simulatecrash_assert.h similarity index 60% rename from keychain/SigninMetrics/SFSignInAnalytics+Internal.h rename to OSX/utilities/simulatecrash_assert.h index 9801140a..33d13b37 100644 --- a/keychain/SigninMetrics/SFSignInAnalytics+Internal.h +++ b/OSX/utilities/simulatecrash_assert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,22 +21,19 @@ * @APPLE_LICENSE_HEADER_END@ */ -#if __OBJC2__ -#ifndef SFSignInAnalytics_Internal_h -#define SFSignInAnalytics_Internal_h +#ifndef _SECURITY_UTILITIES_SIMULATECRASH_ASSERT_H_ +#define _SECURITY_UTILITIES_SIMULATECRASH_ASSERT_H_ -#import "SFSignInAnalytics.h" +#if !defined(NDEBUG) || !defined(__OBJC__) + #include +#else // NDEBUG && __OBJC__ + #include "debugging.h" + #undef assert + #define assert(expr) { \ + if (!(expr)) { \ + __security_simulatecrash(CFSTR("Execution has encountered an unexpected state"), __sec_exception_code_UnexpectedState); \ + } \ + } +#endif // NDEBUG && __OBJC__ -@interface SFSignInAnalytics (Internal) -@property (readonly) NSString *signin_uuid; -@property (readonly) NSString *my_uuid; --(instancetype) initChildWithSignInUUID:(NSString*)signin_uuid andCategory:(NSString*)category andEventName:(NSString*)eventName; -@end - -@interface SFSIALoggerObject : SFAnalytics -+ (instancetype)logger; -- (instancetype)init NS_UNAVAILABLE; -@end - -#endif /* SFSignInAnalytics+Internal_h */ -#endif +#endif /* _SECURITY_UTILITIES_SIMULATECRASH_ASSERT_H_ */ diff --git a/RegressionTests/Security.plist b/RegressionTests/Security.plist index e08137ea..4bcfade3 100644 --- a/RegressionTests/Security.plist +++ b/RegressionTests/Security.plist @@ -1,5 +1,5 @@ - + Project @@ -46,6 +46,8 @@ Disabled BATS_UTD_Disabled_keychainnetworkextensionsharing_1 + MayRunConcurrently + TestName @@ -56,6 +58,8 @@ Disabled BATS_UTD_Disabled_keychainnetworkextensionsharing_2 + MayRunConcurrently + TestName @@ -66,6 +70,8 @@ Disabled BATS_UTD_Disabled_keychainnetworkextensionsharing_3 + MayRunConcurrently + TestName @@ -119,29 +125,33 @@ TestName - KeychainSecd_macOS + KeychainSecd ShowSubtestResults Command - BATS_XCTEST_CMD - /AppleInternal/XCTests/com.apple.security/secdxctests_mac.xctest + /AppleInternal/CoreOS/tests/Security/KeychainEntitledTestRunner + -t + secdxctests Disabled - BATS_UTD_Disabled_KeychainSecd_macOS + BATS_UTD_Disabled_KeychainSecdXCTests TestName - KeychainSecd_iOS + SecDbBackupTests + WorkingDirectory + /AppleInternal/XCTests/com.apple.security/ ShowSubtestResults Command - BATS_XCTEST_CMD - /AppleInternal/XCTests/com.apple.security/secdxctests_ios.xctest + /AppleInternal/CoreOS/tests/Security/KeychainEntitledTestRunner + -t + SecDbBackupTests Disabled - BATS_UTD_Disabled_KeychainSecd_iOS + BATS_UTD_Disabled_KeychainSecDbBackupTests TestName @@ -156,6 +166,18 @@ Disabled BATS_UTD_Disabled_SecurityUtiltitesTests + + TestName + SecCodeAPITest + Command + + /AppleInternal/CoreOS/tests/Security/secseccodeapitest + + Disabled + BATS_UTD_Disabled_SecCodeAPITest + ShowSubtestResults + + diff --git a/RegressionTests/bats_utd_plist.h b/RegressionTests/bats_utd_plist.h index e8549e96..78aa0fef 100644 --- a/RegressionTests/bats_utd_plist.h +++ b/RegressionTests/bats_utd_plist.h @@ -45,6 +45,9 @@ #define BATS_UTD_Disabled_keychainnetworkextensionsharing_3 _TRUE_ #define BATS_UTD_Disabled_keystorectl_get_lock_state _FALSE_ #define BATS_UTD_Disabled_security_sysdiagnose _TRUE_ +#define BATS_UTD_Disabled_KeychainSecdXCTests _TRUE_ +#define BATS_UTD_Disabled_KeychainSecDbBackupTests _TRUE_ +#define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ #elif TARGET_OS_OSX /* For MacOS, we disable the iOS only tests. */ @@ -61,6 +64,45 @@ #define BATS_UTD_Disabled_keychainnetworkextensionsharing_3 _FALSE_ #define BATS_UTD_Disabled_keystorectl_get_lock_state _FALSE_ #define BATS_UTD_Disabled_security_sysdiagnose _FALSE_ +#define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecDbBackupTests _FALSE_ +#define BATS_UTD_Disabled_SecCodeAPITest _FALSE_ + +#elif TARGET_OS_WATCH +#define BATS_UTD_Disabled_AuthorizationTest _TRUE_ +#define BATS_UTD_Disabled_EduModeTest _FALSE_ +#define BATS_UTD_Disabled_KCPairingTest _FALSE_ +#define BATS_UTD_Disabled_KeychainAnalyticsTests _FALSE_ +#define BATS_UTD_Disabled_KeychainMockAKSTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecd_iOS _FALSE_ +#define BATS_UTD_Disabled_KeychainSecd_macOS _TRUE_ +#define BATS_UTD_Disabled_SecurityUtiltitesTests _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_1 _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_2 _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_3 _FALSE_ +#define BATS_UTD_Disabled_keystorectl_get_lock_state _FALSE_ +#define BATS_UTD_Disabled_security_sysdiagnose _FALSE_ +#define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecDbBackupTests _TRUE_ +#define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ + +#elif TARGET_OS_TV +#define BATS_UTD_Disabled_AuthorizationTest _TRUE_ +#define BATS_UTD_Disabled_EduModeTest _FALSE_ +#define BATS_UTD_Disabled_KCPairingTest _FALSE_ +#define BATS_UTD_Disabled_KeychainAnalyticsTests _FALSE_ +#define BATS_UTD_Disabled_KeychainMockAKSTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecd_iOS _FALSE_ +#define BATS_UTD_Disabled_KeychainSecd_macOS _TRUE_ +#define BATS_UTD_Disabled_SecurityUtiltitesTests _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_1 _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_2 _FALSE_ +#define BATS_UTD_Disabled_keychainnetworkextensionsharing_3 _FALSE_ +#define BATS_UTD_Disabled_keystorectl_get_lock_state _FALSE_ +#define BATS_UTD_Disabled_security_sysdiagnose _FALSE_ +#define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecDbBackupTests _TRUE_ +#define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ #else /* By default, assume iOS platforms. We disable the MacOS only tests. */ @@ -77,5 +119,8 @@ #define BATS_UTD_Disabled_keychainnetworkextensionsharing_3 _FALSE_ #define BATS_UTD_Disabled_keystorectl_get_lock_state _FALSE_ #define BATS_UTD_Disabled_security_sysdiagnose _FALSE_ +#define BATS_UTD_Disabled_KeychainSecdXCTests _FALSE_ +#define BATS_UTD_Disabled_KeychainSecDbBackupTests _FALSE_ +#define BATS_UTD_Disabled_SecCodeAPITest _TRUE_ #endif diff --git a/RegressionTests/secitemnotifications/secitemnotifications.m b/RegressionTests/secitemnotifications/secitemnotifications.m index 14986bd6..94e961a3 100644 --- a/RegressionTests/secitemnotifications/secitemnotifications.m +++ b/RegressionTests/secitemnotifications/secitemnotifications.m @@ -1,6 +1,25 @@ -// -// Copyright 2016 Apple. All rights reserved. -// +/* + * Copyright (c) 2016,2020 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@ + */ /* * This is to fool os services to not provide the Keychain manager @@ -14,6 +33,7 @@ #include #include #include +#import int main(int argc, const char ** argv) @@ -32,8 +52,9 @@ main(int argc, const char ** argv) (id)kSecAttrAccessible : (id)kSecAttrAccessibleAfterFirstUnlock, }; status = SecItemDelete((__bridge CFDictionaryRef)query); - if (status != errSecSuccess && status != errSecItemNotFound) + if (status != errSecSuccess && status != errSecItemNotFound) { errx(1, "cleanup item: %d", (int)status); + } notify_register_dispatch("com.apple.security.view-change.PCS", &token, queue, ^(int __unused token2) { printf("got notification\n"); @@ -45,13 +66,22 @@ main(int argc, const char ** argv) */ status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); - if (status != errSecSuccess) + if (status != errSecSuccess) { errx(1, "add item: %d", (int)status); + } sleep(3); - if (!got_notification) +// Bridge explicitly disables notify phase, no PCS, octagon or sos on this platform +#if !TARGET_OS_BRIDGE + if (!got_notification) { errx(1, "failed to get notification on add"); + } +#else + if (got_notification) { + errx(1, "received unexpected notification on add"); + } +#endif got_notification = false; /* @@ -59,13 +89,21 @@ main(int argc, const char ** argv) */ status = SecItemDelete((__bridge CFDictionaryRef)query); - if (status != errSecSuccess) + if (status != errSecSuccess) { errx(1, "cleanup2 item: %d", (int)status); + } sleep(3); - if (!got_notification) +#if !TARGET_OS_BRIDGE + if (!got_notification) { errx(1, "failed to get notification on delete"); + } +#else + if (got_notification) { + errx(1, "received unexpected notification on delete"); + } +#endif return 0; } diff --git a/RegressionTests/secitemstresstest/secitemstresstest.m b/RegressionTests/secitemstresstest/secitemstresstest.m index 122a78bd..dea0cee5 100644 --- a/RegressionTests/secitemstresstest/secitemstresstest.m +++ b/RegressionTests/secitemstresstest/secitemstresstest.m @@ -43,8 +43,9 @@ Cleanup(void) (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue, }; status = SecItemDelete((__bridge CFDictionaryRef)query); - if (status != errSecSuccess || status == errSecItemNotFound) + if (status != errSecSuccess) { printf("cleanup ag1: %d\n", (int)status); + } query = @{ (id)kSecClass : (id)kSecClassGenericPassword, @@ -52,8 +53,9 @@ Cleanup(void) (id)kSecUseDataProtectionKeychain : (id)kCFBooleanTrue, }; status = SecItemDelete((__bridge CFDictionaryRef)query); - if (status != errSecSuccess || status != errSecItemNotFound) + if (status != errSecSuccess) { printf("cleanup ag2: %d\n", (int)status); + } } static void diff --git a/RegressionTests/secseccodeapitest.c b/RegressionTests/secseccodeapitest.c new file mode 100644 index 00000000..660abf75 --- /dev/null +++ b/RegressionTests/secseccodeapitest.c @@ -0,0 +1,253 @@ +// +// secseccodeapitest.c +// secseccodeapitest +// + +#include "authd_private.h" + +#include +#include +#include +#include +#include + +#define BEGIN() \ +({ \ + fprintf(stdout, "[BEGIN] %s\n", __FUNCTION__); \ +}) + +#define INFO(fmt, ...) \ +({ \ + fprintf(stdout, fmt "\n", ##__VA_ARGS__); \ +}) + +#define PASS(fmt, ...) \ +({ \ + fprintf(stdout, "[PASS] %s " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ +}) + +#define FAIL(fmt, ...) \ +({ \ + fprintf(stdout, "[FAIL] %s " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \ +}) + +#define SAFE_RELEASE(x) \ +({ \ + if (x) { \ + CFRelease(x); \ + x = NULL; \ + } \ +}) + +enum xpcConnectionStates { + kXPCConnectionStateNotCancelled = 0, + kXPCConnectionStateCancelled, + kXPCConnectionStateOkayToExit, + kXPCConnectionStateServerNotAvailable, +}; + +static int +_validatePathFromSecCode(SecCodeRef processRef, const char *path) +{ + int ret = -1; + OSStatus status; + SecStaticCodeRef staticProcessRef = NULL; + CFURLRef pathURL = NULL; + CFStringRef pathString = NULL; + + /* Get the StaticCodeRef for this SecCodeRef */ + status = SecCodeCopyStaticCode(processRef, kSecCSDefaultFlags, &staticProcessRef); + require_noerr_action(status, exit, ret = -1); + + INFO("Successfully created a SecStaticCodeRef"); + + /* Copy the path of requested service */ + status = SecCodeCopyPath(staticProcessRef, kSecCSDefaultFlags, &pathURL); + require_noerr_action(status, exit, ret = -1); + + INFO("Successfully created a CFURLRef"); + + /* Get the CFStringRef from the CFURLRef */ + pathString = CFURLGetString(pathURL); + require_action(pathString, exit, ret = -1); + + INFO("Successfully created a CFStingRef"); + + if (!strncmp(path, CFStringGetCStringPtr(pathString, kCFStringEncodingUTF8), strlen(path))) { + INFO("Successfully confirmed the location of requested service"); + ret = 0; + } else { + INFO("Location of service incorrect: %s", CFStringGetCStringPtr(pathString, kCFStringEncodingUTF8)); + ret = -1; + } + +exit: + SAFE_RELEASE(pathURL); + SAFE_RELEASE(staticProcessRef); + + return ret; +} + +static int +CheckCreateWithXPCMessage(void) +{ + BEGIN(); + + int ret; + OSStatus status; + xpc_connection_t connection = NULL; + xpc_object_t message = NULL, reply = NULL; + SecCodeRef processRef = NULL; + volatile static int xpcState = kXPCConnectionStateNotCancelled; + + connection = xpc_connection_create(SECURITY_AUTH_NAME, NULL); + if (NULL == connection) { + FAIL("Unable to create an XPC connection with %s", SECURITY_AUTH_NAME); + return -1; + } + + INFO("XPC Connection with %s created", SECURITY_AUTH_NAME); + + xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { + if (xpc_get_type(event) == XPC_TYPE_ERROR && event == XPC_ERROR_CONNECTION_INVALID) { + if (OSAtomicCompareAndSwapInt(kXPCConnectionStateCancelled, kXPCConnectionStateOkayToExit, &xpcState)) { + INFO("XPC Connection Cancelled"); + } else { + xpcState = kXPCConnectionStateServerNotAvailable; + FAIL("Authorization server not available"); + } + } + }); + + xpc_connection_resume(connection); + + INFO("XPC Connection resumed"); + + /* Create an empty dictionary */ + message = xpc_dictionary_create(NULL, NULL, 0); + + /* + * Set _type to something invalid. This is done because authd will simply + * return an "invalid type" for this case, which means no state changes in + * the authd daemon. + */ + xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_RIGHT_PROPERTIES+512); + + /* Send object and wait for response */ + reply = xpc_connection_send_message_with_reply_sync(connection, message); + xpc_release(message); + + INFO("XPC Message received"); + + /* Create a SecCode using the XPC Message */ + status = SecCodeCreateWithXPCMessage(reply, kSecCSDefaultFlags, &processRef); + if (status) { + FAIL("Unable to create a SecCodeRef from message reply [%d]", status); + xpc_release(reply); + return -1; + } + xpc_release(reply); + + INFO("Successfully created a SecCodeRef"); + + const char *authdLocation = "file:///System/Library/Frameworks/Security.framework/Versions/A/XPCServices/authd.xpc/"; + if (_validatePathFromSecCode(processRef, authdLocation)) { + FAIL("Unable to verify authd location"); + ret = -1; + } else { + PASS("authd location successfully verified"); + ret = 0; + } + + SAFE_RELEASE(processRef); + + // Potential race condition in getting an actual XPC_TYPE_ERROR vs getting + // a connection cancelled. We are okay with this since this is extremely unlikely... + if (OSAtomicCompareAndSwapInt(kXPCConnectionStateNotCancelled, kXPCConnectionStateCancelled, &xpcState)) { + xpc_connection_cancel(connection); + } + + while (xpcState != kXPCConnectionStateOkayToExit) { + if (xpcState == kXPCConnectionStateServerNotAvailable) { + break; + } + usleep(1000 * 1); + } + + return ret; +} + +static int +CheckCreateWithXPCMessage_invalidXPCObject(void) +{ + BEGIN(); + + OSStatus status; + xpc_object_t invalidObject = NULL; + SecCodeRef processRef = NULL; + + /* Create an NULL object */ + invalidObject = xpc_null_create(); + + INFO("Created a NULL object"); + + /* Try and acquire a SecCodeRef through the NULL object -- should fail with errSecCSInvalidObjectRef */ + status = SecCodeCreateWithXPCMessage(invalidObject, kSecCSDefaultFlags, &processRef); + if (status != errSecCSInvalidObjectRef) { + FAIL("Return code unexpected [%d]", status); + return -1; + } + + PASS("Got expected return code"); + return 0; +} + +static int +CheckCreateWithXPCMessage_NULLConnectionInObject(void) +{ + BEGIN(); + + OSStatus status; + xpc_object_t emptyDictionary = NULL; + SecCodeRef processRef = NULL; + + /* Create an empty dictionary object */ + emptyDictionary = xpc_dictionary_create_empty(); + + INFO("Created an empty dictionary object"); + + /* Try and acquire a SecCodeRef through the empty dictionary -- should fail with errSecCSInvalidObjectRef */ + status = SecCodeCreateWithXPCMessage(emptyDictionary, kSecCSDefaultFlags, &processRef); + if (status != errSecCSInvalidObjectRef) { + FAIL("Return code unexpected [%d]", status); + return -1; + } + + PASS("Got expected return code"); + return 0; +} + +int main(void) +{ + fprintf(stdout, "[TEST] secseccodeapitest\n"); + + int i; + int (*testList[])(void) = { + CheckCreateWithXPCMessage, + CheckCreateWithXPCMessage_invalidXPCObject, + CheckCreateWithXPCMessage_NULLConnectionInObject + }; + const int numberOfTests = sizeof(testList) / sizeof(*testList); + int testResults[numberOfTests] = {0}; + + for (i = 0; i < numberOfTests; i++) { + testResults[i] = testList[i](); + } + + fprintf(stdout, "[SUMMARY]\n"); + for (i = 0; i < numberOfTests; i++) { + fprintf(stdout, "%d. %s\n", i+1, testResults[i] == 0 ? "Passed" : "Failed"); + } + + return 0; +} diff --git a/Security.exp-in b/Security.exp-in index a3efacd0..241e9740 100644 --- a/Security.exp-in +++ b/Security.exp-in @@ -332,7 +332,6 @@ SEC_EXP_CLASS(CKKSControl) SEC_EXP_CLASS(SecuritydXPCClient) #if __OBJC2__ -SEC_EXP_CLASS(SFSignInAnalytics) SEC_EXP_CLASS(SecXPCHelper) SEC_EXP_CLASS(OTClique) SEC_EXP_CLASS(OTConfigurationContext) @@ -365,19 +364,13 @@ _OTProtocolPiggybacking _OTDefaultsDomain _OTDefaultsOctagonEnable _OTTrustStatusChangeNotification - -_OctagonEventAttributeZoneName -_OctagonEventAttributeFailureReason -_OctagonEventAttributeTimeSinceLastPostedFollowUp +_OTEscrowRecordPrefix _SecEscrowRequestHavePrecord _SecEscrowRequestPendingPasscode _SecEscrowRequestPendingCertificate -_OTCKContainerName -_CuttlefishTrustZone _CuttlefishErrorDomain -_TrustedPeersHelperErrorDomain _CuttlefishErrorRetryAfterKey _OctagonPlatformSupportsSOS @@ -392,6 +385,14 @@ _OctagonAuthoritativeTrustIsEnabled _OctagonAuthoritativeTrustSetIsEnabled _OctagonIsSOSFeatureEnabled _OctagonSetSOSFeatureEnabled +_OctagonIsOptimizationEnabled +_OctagonSetOptimizationEnabled +_OctagonSetEscrowRecordFetchEnabled +_OctagonIsEscrowRecordFetchEnabled +_SecKVSOnCloudKitIsEnabled +_SecKVSOnCloudKitSetOverrideIsEnabled +_SecErrorIsNestedErrorCappingEnabled +_SecErrorSetOverrideNestedErrorCappingIsEnabled SEC_EXP_CLASS(OTJoiningConfiguration) SEC_EXP_CLASS(OTControl) @@ -400,6 +401,9 @@ SEC_EXP_CLASS(SecuritydXPCClient) _SecAccessGroupsGetCurrent _SecAccessGroupsSetCurrent _SecSecurityClientGet +_SecSecurityClientRegularToAppClip +_SecSecurityClientAppClipToRegular +_SecSecurityClientSetApplicationIdentifier _securityd_create_message _securityd_message_with_reply_sync _securityd_message_no_error @@ -415,7 +419,6 @@ __SecSetSecuritydTargetUID _SecDERItemCopyOIDDecimalRepresentation _SecDigestCreate -_SecFrameworkCopyResourceURL _SecCopyErrorMessageString _SecFrameworkCopyIPAddressData @@ -536,11 +539,12 @@ _AuthorizationExecuteWithPrivilegesExternalFormInternal _AuthorizationFree _AuthorizationFreeItemSet _AuthorizationMakeExternalForm -_AuthorizationPreauthorizeCredentials _AuthorizationRightGet _AuthorizationRightRemove _AuthorizationRightSet _AuthorizationEnableSmartCard +_AuthorizationCopyPreloginUserDatabase +_AuthorizationCopyRightProperties _SessionCreate _SessionGetInfo _SessionSetDistinguishedUser @@ -913,14 +917,10 @@ _SecDigestGetData _SecFDERecoveryUnwrapCRSKWithPrivKey _SecFDERecoveryWrapCRSKWithPubKey _SecGenericPasswordCreate -_SecIdentityAddPreferenceItem -_SecIdentityCompare -_SecIdentityCopyFromPreferenceItem _SecIdentityCopyPreference _SecIdentityCopyPreferred _SecIdentityCopySystemIdentity _SecIdentityCreateWithCertificate -_SecIdentityFindPreferenceItem _SecIdentitySearchCopyNext _SecIdentitySearchCreate _SecIdentitySearchCreateWithAttributes @@ -929,11 +929,10 @@ _SecIdentitySearchGetTypeID _SecIdentitySetPreference _SecIdentitySetPreferred _SecIdentitySetSystemIdentity -_SecIdentityUpdatePreferenceItem _SecInferLabelFromX509Name _SecItemAdd_ios _SecItemCopyMatching_ios -_SecItemUpdateTokenItems_ios +_SecItemUpdateTokenItemsForAccessGroups _SecKeyGeneratePair_ios @@ -950,7 +949,6 @@ _SecItemUpdate_ios _SecKeychainAddCallback _SecKeychainAddDBToKeychainList _SecKeychainAddGenericPassword -_SecKeychainAddIToolsPassword _SecKeychainAddInternetPassword _SecKeychainAttemptMigrationWithMasterKey _SecKeychainAttributeInfoForItemID @@ -1034,7 +1032,6 @@ _SecKeychainLogout _SecKeychainMDSInstall _SecKeychainMakeFromFullPath _SecKeychainOpen -_SecKeychainOpenWithGuid _SecKeychainRecodeKeychain _SecKeychainRemoveCallback _SecKeychainRemoveDBFromKeychainList @@ -1589,6 +1586,7 @@ _SecCodeCopyHost _SecCodeCopyGuestWithAttributes _SecCodeCreateWithAuditToken _SecCodeCreateWithPID +_SecCodeCreateWithXPCMessage _SecCodeCheckValidity _SecCodeCheckValidityWithErrors _SecCodeCopyPath @@ -1699,6 +1697,7 @@ _kSecCodeInfoDiskRepVersionMin _kSecCodeInfoDiskRepVersionSDK _kSecCodeInfoResourceDirectory _kSecCodeInfoNotarizationDate +_kSecCodeInfoSignatureVersion _kSecGuestAttributeCanonical _kSecGuestAttributeDynamicCode _kSecGuestAttributeDynamicCodeInfoPlist @@ -1819,6 +1818,9 @@ _SecRequirementGetTypeID _SecStaticCodeCheckValidity _SecStaticCodeCreateWithPath _SecStaticCodeGetTypeID +_SecStaticCodeSetCallback +_SecStaticCodeSetValidationConditions +_SecStaticCodeCancelValidation _kSecCFErrorArchitecture _kSecCFErrorGuestAttributes _kSecCFErrorInfoPlist @@ -1830,6 +1832,7 @@ _kSecCFErrorResourceSideband _kSecCodeAttributeArchitecture _kSecCodeAttributeBundleVersion _kSecCodeAttributeSubarchitecture +_kSecCodeDirectoryFlagTable _kSecCodeInfoCMS _kSecCodeInfoCMSDigest _kSecCodeInfoCMSDigestHashType @@ -1856,6 +1859,7 @@ _kSecCodeInfoPlatformIdentifier _kSecCodeInfoRequirementData _kSecCodeInfoRequirements _kSecCodeInfoResourceDirectory +_kSecCodeInfoSignatureVersion _kSecCodeInfoSource _kSecCodeInfoStatus _kSecCodeInfoTimestamp @@ -1872,13 +1876,6 @@ _kSecGuestAttributeSubarchitecture #endif // TARGET_OS_IPHONE -#if TARGET_OS_OSX -//breadcrumb -_SecBreadcrumbCreateFromPassword -_SecBreadcrumbCopyPassword -_SecBreadcrumbCreateNewEncryptedKey -#endif // TARGET_OS_OSX - // // libDER OIDs // @@ -2009,6 +2006,7 @@ _SecTranslocateAppLaunchCheckin _SecTranslocateURLShouldRunTranslocated _SecTranslocateIsTranslocatedURL _SecTranslocateCreateOriginalPathForURL +_SecTranslocateCreateGeneric #endif // TARGET_OS_OSX #if TARGET_OS_OSX @@ -2087,7 +2085,8 @@ _OBJC_CLASS_$_SFAnalyticsMultiSampler _OBJC_CLASS_$_SFAnalyticsSampler _OBJC_CLASS_$_SFAnalyticsSQLiteStore _OBJC_CLASS_$_SecCoreAnalytics -_OBJC_METACLASS_$_SFSignInAnalytics +_SecCoreAnalyticsValue +_SecCoreAnalyticsSendValue _SFAnalyticsMaxEventsToReport _SFSQLiteJournalSuffixes _SFAnalyticsSamplerIntervalOncePerReport @@ -2116,6 +2115,7 @@ _SFAnalyticsAttributeErrorUnderlyingChain _SFAnalyticsAttributeLastUploadTime _SFAnalyticsTopicCloudServices _SFAnalyticsTopicKeySync +_SFAnalyticsTopicNetworking _SFAnalyticsTopicTransparency _SFAnalyticsTopicTrust _SFAnalyticsErrorDomain @@ -2132,6 +2132,8 @@ _CKDKVSPerfCounterSynchronizeFailures _OBJC_CLASS_$_LocalKeychainAnalytics _LKAEventUpgrade +_LKAEventStash +_LKAEventStashLoad #endif // __OBJC2__ _LKAReportKeychainUpgradeOutcome @@ -2167,3 +2169,5 @@ _SecCreateCFErrorWithXPCObject _SecCreateXPCObjectWithCFError _SecItemVerifyBackupIntegrity + +_SecItemDeleteKeychainItemsForAppClip diff --git a/Security.xcodeproj/project.pbxproj b/Security.xcodeproj/project.pbxproj index d469fbf5..6ccf9ee9 100644 --- a/Security.xcodeproj/project.pbxproj +++ b/Security.xcodeproj/project.pbxproj @@ -13,7 +13,9 @@ buildPhases = ( ); dependencies = ( + 6C2045F82424BC4400F9461D /* PBXTargetDependency */, 47C2F1902059CBFC0062DE30 /* PBXTargetDependency */, + DCE27861245B81BD00381FE8 /* PBXTargetDependency */, D469C4E5218BECCE008AC1FC /* PBXTargetDependency */, 0C78CCE51FCC97E7008B4B24 /* PBXTargetDependency */, EB27FF261E40716D00EC9E3A /* PBXTargetDependency */, @@ -52,6 +54,7 @@ EB6A6FBD1B90F9170045DC68 /* PBXTargetDependency */, DC647C46208A85C900D0F9F8 /* PBXTargetDependency */, D4F56BAB217FCAF600FCA6B7 /* PBXTargetDependency */, + 0C65BB4F23C3F3270063D2B7 /* PBXTargetDependency */, ); name = Security_frameworks_ios; productName = kernel; @@ -73,6 +76,7 @@ buildPhases = ( ); dependencies = ( + 5AAE383623D261CF0025CF9E /* PBXTargetDependency */, EB74CC232207E99700F1BBAD /* PBXTargetDependency */, 47C2F18C2059CBEA0062DE30 /* PBXTargetDependency */, 4771D982209A76B100BA9772 /* PBXTargetDependency */, @@ -177,8 +181,9 @@ buildPhases = ( ); dependencies = ( + 0CCC22D223F39A7500E1FCD0 /* PBXTargetDependency */, + 6CF33CA62387156600D1E75D /* PBXTargetDependency */, EB694E87223AB79400F02C1C /* PBXTargetDependency */, - D4E0E9762224DE9100A802E0 /* PBXTargetDependency */, D4E0E9702224DE8200A802E0 /* PBXTargetDependency */, D4E0E9722224DE8200A802E0 /* PBXTargetDependency */, D4E0E9742224DE8200A802E0 /* PBXTargetDependency */, @@ -208,8 +213,9 @@ buildPhases = ( ); dependencies = ( + 0CCC22D423F39A7C00E1FCD0 /* PBXTargetDependency */, + 6CF33CA82387157200D1E75D /* PBXTargetDependency */, EB694E72223AB78E00F02C1C /* PBXTargetDependency */, - D4E0E9AC2224DFEB00A802E0 /* PBXTargetDependency */, D4E0E9A62224DFDD00A802E0 /* PBXTargetDependency */, D4E0E9A82224DFDD00A802E0 /* PBXTargetDependency */, D4E0E9AA2224DFDD00A802E0 /* PBXTargetDependency */, @@ -359,6 +365,7 @@ D4F56B9D217FCA7E00FCA6B7 /* PBXTargetDependency */, D4F56B9F217FCA8600FCA6B7 /* PBXTargetDependency */, D4F56BB72181380600FCA6B7 /* PBXTargetDependency */, + 0C2B36C523C42EC800000718 /* PBXTargetDependency */, ); name = Security_frameworks_tvos; productName = Security_frameworks_tvos; @@ -372,6 +379,7 @@ D4F56BA7217FCAB000FCA6B7 /* PBXTargetDependency */, D4F56BA5217FCAAA00FCA6B7 /* PBXTargetDependency */, D4F56BBB2181387600FCA6B7 /* PBXTargetDependency */, + 0C2B36C323C42EBC00000718 /* PBXTargetDependency */, ); name = Security_frameworks_watchos; productName = Security_frameworks_watchos; @@ -621,6 +629,9 @@ buildPhases = ( ); dependencies = ( + 0CCC22D023F39A6A00E1FCD0 /* PBXTargetDependency */, + 6CC638FE2266AE0A00E5DB0B /* PBXTargetDependency */, + 6CC639002266AE0A00E5DB0B /* PBXTargetDependency */, EB694E8B223AB7A200F02C1C /* PBXTargetDependency */, EB694DD0223A087700F02C1C /* PBXTargetDependency */, EB694DC82239E5F200F02C1C /* PBXTargetDependency */, @@ -639,8 +650,6 @@ D4A763E32224BDF90063B2B9 /* PBXTargetDependency */, D4A763E12224BDED0063B2B9 /* PBXTargetDependency */, D4A763DF2224BDDC0063B2B9 /* PBXTargetDependency */, - D4A763DD2224BDCC0063B2B9 /* PBXTargetDependency */, - D4A763DB2224BDAB0063B2B9 /* PBXTargetDependency */, D4A763D92224BD990063B2B9 /* PBXTargetDependency */, D4A763D52224BD6F0063B2B9 /* PBXTargetDependency */, D4A763D32224BD640063B2B9 /* PBXTargetDependency */, @@ -652,9 +661,10 @@ D477EE7B21ED48C000C9AAFF /* PBXTargetDependency */, D477EE7D21ED48CB00C9AAFF /* PBXTargetDependency */, D477EE7F21ED48D500C9AAFF /* PBXTargetDependency */, - D477EE8321ED48E800C9AAFF /* PBXTargetDependency */, D477EE8121ED48DF00C9AAFF /* PBXTargetDependency */, EBB8521022F793A200424FD0 /* PBXTargetDependency */, + 6C61D3E8242A29BA008AB9BB /* PBXTargetDependency */, + 3E88361D24F08F5400E9F4D6 /* PBXTargetDependency */, ); name = Security_tests_osx; productName = Security_test_macos; @@ -665,13 +675,14 @@ buildPhases = ( ); dependencies = ( + 0CCC22CE23F39A6300E1FCD0 /* PBXTargetDependency */, + 6C2D797522C06CEF00C3CE32 /* PBXTargetDependency */, + 6C2D797322C06CEB00C3CE32 /* PBXTargetDependency */, EB694E89223AB79B00F02C1C /* PBXTargetDependency */, EB694DCE223A086C00F02C1C /* PBXTargetDependency */, EB694DC42239E5A200F02C1C /* PBXTargetDependency */, - D4E0E97A2224DEE600A802E0 /* PBXTargetDependency */, D45D8F882224DC3F00D6C124 /* PBXTargetDependency */, D45D8F862224DBF800D6C124 /* PBXTargetDependency */, - D45D8F842224DBEF00D6C124 /* PBXTargetDependency */, D45D8F822224DBE300D6C124 /* PBXTargetDependency */, D45D8F7E2224DBD900D6C124 /* PBXTargetDependency */, D45D8F7C2224DBC600D6C124 /* PBXTargetDependency */, @@ -692,7 +703,6 @@ EB58A0621E74C8E4009C10D7 /* PBXTargetDependency */, EB10557D1E14DFB60003C309 /* PBXTargetDependency */, BE9C38D31EB11605007E2AE1 /* PBXTargetDependency */, - 47D991D020407F7E0078CAE2 /* PBXTargetDependency */, EBB8521222F793AC00424FD0 /* PBXTargetDependency */, ); name = Security_tests_ios; @@ -708,6 +718,7 @@ DC647C44208A85BE00D0F9F8 /* PBXTargetDependency */, DC58C4431D77C1F8003C25A4 /* PBXTargetDependency */, D4F56BB32181306900FCA6B7 /* PBXTargetDependency */, + 0C65BB4D23C3F31B0063D2B7 /* PBXTargetDependency */, ); name = Security_frameworks_osx; productName = Security_frameworks_macos; @@ -729,6 +740,7 @@ buildPhases = ( ); dependencies = ( + 6C7BE2EA23C3DD9C003BB2CA /* PBXTargetDependency */, 47455B24205B3E2F008FE980 /* PBXTargetDependency */, D41257F71E941E9600781F23 /* PBXTargetDependency */, ); @@ -771,11 +783,11 @@ 091B39732063B67700ECAB6F /* RemoteServiceDiscovery.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 091B396D2063B64A00ECAB6F /* RemoteServiceDiscovery.framework */; }; 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 */; }; - 09BFE35C20A32E0E008511E9 /* KeychainEntitlementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 09BFE35A20A32E0E008511E9 /* KeychainEntitlementsTest.m */; }; + 097CE59F246966A100958AF8 /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; 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 */; }; 0C00FC86217A980100C8BF00 /* OTLocalCuttlefishReset.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C00FC81217A971800C8BF00 /* OTLocalCuttlefishReset.m */; }; + 0C0203E623A857C1005D0A68 /* OTEscrowRecord.proto in Sources */ = {isa = PBXBuildFile; fileRef = 0C0203E023A8564E005D0A68 /* OTEscrowRecord.proto */; }; 0C0582C620D9CA4800D7BD7A /* OTClique.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CDBCD8620AD03FB007F8EA7 /* OTClique.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0C0582CC20D9CA4900D7BD7A /* OTClique.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CDBCD8620AD03FB007F8EA7 /* OTClique.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0C0BDB32175685B000BC1A7E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C0BDB31175685B000BC1A7E /* main.m */; }; @@ -786,13 +798,18 @@ 0C0BDB931756A8C900BC1A7E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; 0C0C4F86216FB73C00C14C61 /* EscrowKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0C4F83216FB55600C14C61 /* EscrowKeys.swift */; }; 0C0C4F87216FB73F00C14C61 /* BottledPeer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0C4F84216FB56B00C14C61 /* BottledPeer.swift */; }; + 0C0CB73923AD714D0020C6BF /* Container_EscrowRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */; }; + 0C0CB73A23AD715A0020C6BF /* Container_EscrowRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */; }; + 0C0CB73B23AD71650020C6BF /* Container_EscrowRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */; }; 0C0CECA41DA45ED700C22FBC /* recovery_key.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C0CEC9E1DA45EA200C22FBC /* recovery_key.m */; }; + 0C0D920C23BFEAB30070A68C /* OTCDPRecoveryInformation.proto in Sources */ = {isa = PBXBuildFile; fileRef = 0C0D920523BFEA740070A68C /* OTCDPRecoveryInformation.proto */; }; 0C0DA5CE1FE1EAB9003BD3BB /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; 0C0DA5CF1FE1F1C5003BD3BB /* OTControlProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0D1FCB452300580909 /* OTControlProtocol.m */; }; 0C0DA5D01FE1F1F3003BD3BB /* CKKSControlProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF7A8A21F0450EB00CABE89 /* CKKSControlProtocol.m */; }; 0C0E60DA20D033E400E654F2 /* OTControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0E1FCB452400580909 /* OTControl.m */; }; 0C0E60E020D033E400E654F2 /* OTControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0E1FCB452400580909 /* OTControl.m */; }; 0C12B1F12138D31600BE0A98 /* OTClientStateMachine.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C12B1F02138D31600BE0A98 /* OTClientStateMachine.m */; }; + 0C147A2823F39CD10034F08B /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; 0C16371C1FD116B300210823 /* MockCloudKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3502E61E0214C800BC0587 /* MockCloudKit.m */; }; 0C1637271FD2065400210823 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; 0C1637291FD2066A00210823 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; @@ -802,6 +819,8 @@ 0C1B8BB72233244F0094D5DA /* OTVouchWithRecoveryKeyOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C1B8BB52233241E0094D5DA /* OTVouchWithRecoveryKeyOperation.m */; }; 0C29BF222323288C003C807E /* OTDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = EBCE06E521C6E26000FB1493 /* OTDefines.m */; }; 0C29BF2523232897003C807E /* OTDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = EBCE06E521C6E26000FB1493 /* OTDefines.m */; }; + 0C2B32A423C4000F00A97B18 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + 0C2B32A523C4001900A97B18 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; 0C2BCBAF1D06401F00ED7A2F /* ioSock.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A65809C79E0600D27A3F /* ioSock.c */; }; 0C2BCBB01D06401F00ED7A2F /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A65A09C79E0600D27A3F /* sslAppUtils.cpp */; }; 0C2BCBB41D06401F00ED7A2F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; @@ -814,50 +833,72 @@ 0C2BCBCF1D0648EF00ED7A2F /* dtlsEchoServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C2BCBA61D063F7D00ED7A2F /* dtlsEchoServer.c */; }; 0C2F337220DD64930031A92D /* OTRamping.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C2F337120DD647D0031A92D /* OTRamping.m */; }; 0C2F337320DD64940031A92D /* OTRamping.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C2F337120DD647D0031A92D /* OTRamping.m */; }; + 0C3810F123EF6FC4002D7E19 /* OctagonTrust.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */; }; 0C38AA92212B2D1900C90A1D /* OTEpochOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C4F4DE121153659007F7E20 /* OTEpochOperation.h */; }; 0C38AA96212B2D1E00C90A1D /* OTClientVoucherOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CC8A9002123AA3B005D7F6A /* OTClientVoucherOperation.h */; }; 0C38AA98212B2D2300C90A1D /* OTJoinWithVoucherOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CC8A9052123AF16005D7F6A /* OTJoinWithVoucherOperation.h */; }; 0C3BB3582188E18C0018FC14 /* OTPrivateKey+SF.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3BB3522188E18A0018FC14 /* OTPrivateKey+SF.m */; }; 0C3BB35A2188E18C0018FC14 /* OTAuthenticatedCiphertext+SF.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3BB3542188E18B0018FC14 /* OTAuthenticatedCiphertext+SF.m */; }; 0C3C00731EF3636500AB19FE /* secd-155-otr-negotiation-monitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3C00721EF3636300AB19FE /* secd-155-otr-negotiation-monitor.m */; }; + 0C3C47C624902D960084B951 /* OTSupportOctagonMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3C47C024902D450084B951 /* OTSupportOctagonMessage.m */; }; + 0C3C47C724902D960084B951 /* OTSupportSOSMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3C47C324902D460084B951 /* OTSupportSOSMessage.m */; }; + 0C3C47C824902DA50084B951 /* OTSupportSOSMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3C47C324902D460084B951 /* OTSupportSOSMessage.m */; }; + 0C3C47C924902DA50084B951 /* OTSupportOctagonMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3C47C024902D450084B951 /* OTSupportOctagonMessage.m */; }; + 0C3DF8C824789C3C009CF03A /* Container_Peers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C3DF8C524789C04009CF03A /* Container_Peers.swift */; }; + 0C3DF8C924789D06009CF03A /* Container_Peers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C3DF8C524789C04009CF03A /* Container_Peers.swift */; }; + 0C3DF8CA24789D0A009CF03A /* Container_Peers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C3DF8C524789C04009CF03A /* Container_Peers.swift */; }; 0C3E316B21372FA50093C04B /* OctagonPairingTests+ProximitySetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C6604812134DD5D00BFBBB8 /* OctagonPairingTests+ProximitySetup.swift */; }; + 0C468FE123C7D487006F4582 /* OTEscrowRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FDE23C7D471006F4582 /* OTEscrowRecord.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FE223C7D487006F4582 /* OTEscrowRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */; }; + 0C468FE323C7D487006F4582 /* OTEscrowRecordMetadata.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FDA23C7D41D006F4582 /* OTEscrowRecordMetadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FE423C7D487006F4582 /* OTEscrowRecordMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */; }; + 0C468FE523C7D487006F4582 /* OTEscrowRecordMetadataClientMetadata.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FDB23C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FE623C7D487006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */; }; + 0C468FEF23C7D4D5006F4582 /* OTCDPRecoveryInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FEA23C7D4C8006F4582 /* OTCDPRecoveryInformation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FF023C7D4D5006F4582 /* OTCDPRecoveryInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FEE23C7D4CA006F4582 /* OTCDPRecoveryInformation.m */; }; + 0C468FF123C7D4D5006F4582 /* OTEscrowAuthenticationInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FE823C7D4C8006F4582 /* OTEscrowAuthenticationInformation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FF223C7D4D5006F4582 /* OTEscrowAuthenticationInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FEC23C7D4C9006F4582 /* OTEscrowAuthenticationInformation.m */; }; + 0C468FF323C7D4D5006F4582 /* OTICDPRecordContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FE723C7D4C7006F4582 /* OTICDPRecordContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FF423C7D4D5006F4582 /* OTICDPRecordContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FED23C7D4C9006F4582 /* OTICDPRecordContext.m */; }; + 0C468FF523C7D4D5006F4582 /* OTICDPRecordSilentContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C468FE923C7D4C8006F4582 /* OTICDPRecordSilentContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C468FF623C7D4D5006F4582 /* OTICDPRecordSilentContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FEB23C7D4C9006F4582 /* OTICDPRecordSilentContext.m */; }; + 0C468FF723C7D4E3006F4582 /* OTEscrowRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */; }; + 0C468FF823C7D4E3006F4582 /* OTEscrowRecordMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */; }; + 0C468FF923C7D4E3006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */; }; + 0C468FFA23C7D4EF006F4582 /* OTEscrowRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */; }; + 0C468FFB23C7D4EF006F4582 /* OTEscrowRecordMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */; }; + 0C468FFC23C7D4EF006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */; }; + 0C468FFD23C7D4F9006F4582 /* OTEscrowRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */; }; + 0C468FFE23C7D4F9006F4582 /* OTEscrowRecordMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */; }; + 0C468FFF23C7D4F9006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */; }; 0C46A5712034C6BA00F17112 /* OTControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0E1FCB452400580909 /* OTControl.m */; }; 0C48990B1E0E0FF300C6CF70 /* SOSTransportCircleCK.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C48990A1E0E0FF300C6CF70 /* SOSTransportCircleCK.h */; }; 0C4899121E0E105D00C6CF70 /* SOSTransportCircleCK.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C4899111E0E105D00C6CF70 /* SOSTransportCircleCK.m */; }; 0C4899231E0F386900C6CF70 /* SOSAccountTrustClassic.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C4899221E0F386900C6CF70 /* SOSAccountTrustClassic.h */; }; 0C48B380202E438100A0E1AA /* CloudKitKeychainSyncingMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC08D1C31E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m */; }; - 0C4C547620E1A0B400BA61BA /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C4C548020E1A53D00BA61BA /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; 0C4CDE6F22922E550050C499 /* OctagonTests+RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C4CDE6D22922E360050C499 /* OctagonTests+RecoveryKey.swift */; }; - 0C4D96A621F24E5700617E60 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C4D96A721F25F2C00617E60 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; 0C4F4DE221153E9E007F7E20 /* OTEpochOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C4F4DDA211535E8007F7E20 /* OTEpochOperation.m */; }; 0C5258BA21BB062F00B32C96 /* FakeSOSControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C5258B821BB05C100B32C96 /* FakeSOSControl.m */; }; 0C5258BB21BB128000B32C96 /* FakeSOSControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C5258B821BB05C100B32C96 /* FakeSOSControl.m */; }; 0C5258BD21BB137900B32C96 /* FakeSOSControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C5258BC21BB137800B32C96 /* FakeSOSControl.h */; }; - 0C5663EC20BE2DF30035F362 /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; - 0C5663EF20BE2E220035F362 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; + 0C570B7923F3A015001FEB3B /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; + 0C570B7B23F3A09A001FEB3B /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; + 0C570B7C23F3A0E3001FEB3B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + 0C570B8123F3A1EC001FEB3B /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; 0C5824A52286002D009E8C15 /* OctagonTests+HealthCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C5824A322860001009E8C15 /* OctagonTests+HealthCheck.swift */; }; 0C5960641FB2E2070095BA29 /* libprequelite.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CE98B5B1FA9360700CF1D54 /* libprequelite.tbd */; settings = {ATTRIBUTES = (Weak, ); }; }; 0C5960811FB369C50095BA29 /* CKKSHealTLKSharesOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBF2F841F913EF000ED0CA4 /* CKKSHealTLKSharesOperation.m */; }; 0C61F1F62194FC79009566D4 /* OTPrivateKey+SF.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3BB3522188E18A0018FC14 /* OTPrivateKey+SF.m */; }; 0C61F1F92194FC82009566D4 /* OTAuthenticatedCiphertext+SF.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C3BB3542188E18B0018FC14 /* OTAuthenticatedCiphertext+SF.m */; }; + 0C64C0802485B2EF00D84A5D /* OTPreloadOctagonKeysOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C64C07C2485A53000D84A5D /* OTPreloadOctagonKeysOperation.m */; }; 0C66046A2134983900BFBBB8 /* OTEstablishOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C6604692134983900BFBBB8 /* OTEstablishOperation.m */; }; 0C66047E2134CA5600BFBBB8 /* OTDeviceInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C66047B2134C88C00BFBBB8 /* OTDeviceInformation.m */; }; - 0C6C0FCB21F1415B00CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FCF21F1457600CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FD021F145F600CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FD121F1465500CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FD221F146E700CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FD321F1494C00CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C6C0FD621F14D3900CD5B9E /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C78826F20132069002B7475 /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; - 0C78827520132074002B7475 /* SFSignInAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */; }; 0C78F1CC16A5E1BF00654E08 /* sectask-10-sectask.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CA16A5E1BF00654E08 /* sectask-10-sectask.c */; }; 0C78F1CD16A5E1BF00654E08 /* sectask-10-sectask.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CA16A5E1BF00654E08 /* sectask-10-sectask.c */; }; 0C78F1CE16A5E1BF00654E08 /* sectask_ipc.defs in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CB16A5E1BF00654E08 /* sectask_ipc.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; }; 0C78F1CF16A5E1BF00654E08 /* sectask_ipc.defs in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CB16A5E1BF00654E08 /* sectask_ipc.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; }; 0C78F1D016A5E3EB00654E08 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; + 0C79213D23C3F6E100193389 /* OctagonTrust.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD743B723C3ED7E00FA0EC5 /* OctagonTrust.m */; }; 0C7A8BBF21714CDC00F4C480 /* OTJoiningConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8FD549214AECD70098E3FB /* OTJoiningConfiguration.m */; }; 0C7A8BC021714D0E00F4C480 /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 0C84D8341FCF43AF00B822E3 /* OTControlProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0D1FCB452300580909 /* OTControlProtocol.m */; }; @@ -894,11 +935,10 @@ 0C8FD52521483EF20098E3FB /* OT.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CCCC7C820261D310024405E /* OT.m */; }; 0C97867D235A77230040A867 /* com.apple.security.signposts.plist in Copy System logging profile */ = {isa = PBXBuildFile; fileRef = 0C97867C235A76E70040A867 /* com.apple.security.signposts.plist */; }; 0C98122821ACCC9300784441 /* OTClique.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C2F336A20DD643B0031A92D /* OTClique.m */; }; - 0C9AEEAF20783FBB00BF6237 /* SFSignInAnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */; }; - 0C9AEEBB20783FF900BF6237 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - 0C9AEEBE207843D000BF6237 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; - 0C9FB40720D872A600864612 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; - 0C9FB40920D8735500864612 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; + 0C9A54B6250C286100FF007B /* OctagonTrustTests+Errors.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9A54B4250C27F100FF007B /* OctagonTrustTests+Errors.m */; }; + 0C9F65AD23E3AD2E00B1A2C5 /* OTEscrowTranslation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C9F65AC23E3ACF700B1A2C5 /* OTEscrowTranslation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C9F65AE23E3AD3200B1A2C5 /* OTEscrowTranslation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9F65AA23E3ACF700B1A2C5 /* OTEscrowTranslation.m */; }; + 0CA1D0B923E9034600021038 /* OctagonTests+EscrowTestVectors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA1D0B223E9023100021038 /* OctagonTests+EscrowTestVectors.swift */; }; 0CA2282F2187A5CA00A1C56C /* BottledPeer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0C4F84216FB56B00C14C61 /* BottledPeer.swift */; }; 0CA378E723876DFC00090B7E /* reset_ick_account in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0C7382F023863AD5004F98CB /* reset_ick_account */; }; 0CA4B4722171410200B17169 /* EscrowKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C0C4F83216FB55600C14C61 /* EscrowKeys.swift */; }; @@ -933,22 +973,54 @@ 0CB8DC9A2194B14C0021A7C8 /* OTVouchWithBottleOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CB8DC992194B1440021A7C8 /* OTVouchWithBottleOperation.m */; }; 0CB9754F2023A8F5008D6B48 /* CloudKitMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC222CA71E08A7D900B09171 /* CloudKitMockXCTest.m */; }; 0CBA047D214C4E4D005B3A2F /* OctagonPairingTests+ProxMultiClients.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CBA047C214C4E4D005B3A2F /* OctagonPairingTests+ProxMultiClients.swift */; }; - 0CBD55B31FE883F200A8CE21 /* SFBehavior.m in Sources */ = {isa = PBXBuildFile; fileRef = EB82A2A51FAFF26900CA64A9 /* SFBehavior.m */; }; 0CBEF3432242CA0600015691 /* TestsObjcTranslation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CBEF3412242C9AE00015691 /* TestsObjcTranslation.m */; }; - 0CBFEACA200FCD2D009A60E9 /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; - 0CBFEACB200FCD2D009A60E9 /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; - 0CBFEACC200FCD33009A60E9 /* SFSignInAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0CBFEACD200FCD33009A60E9 /* SFSignInAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0CBF883D23AAD9F100652EDD /* OctagonTests+EscrowRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CBF883A23AAD9DC00652EDD /* OctagonTests+EscrowRecords.swift */; }; 0CC319241DA46FBF005D42EA /* ProtectedCloudStorage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43DB542E1BB1F85B0083C3F1 /* ProtectedCloudStorage.framework */; }; - 0CC3771320A222BC00B58D2D /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; 0CC593F02299B9AA006C34B5 /* SecInternalRelease.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC761D8C68CF00070CB0 /* SecInternalRelease.c */; }; 0CC593F62299EC3D006C34B5 /* OTDeviceInformationAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC19484B21812EC5007C2260 /* OTDeviceInformationAdapter.m */; }; 0CC593F92299EE06006C34B5 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; 0CC8A8FE2123A9F6005D7F6A /* OTClientVoucherOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CC8A8FA2123A9EB005D7F6A /* OTClientVoucherOperation.m */; }; 0CC8A9032123AF06005D7F6A /* OTJoinWithVoucherOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CC8A9012123AEF7005D7F6A /* OTJoinWithVoucherOperation.m */; }; + 0CC9403023F39E84004B71AA /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; + 0CCC21FC23F33DA900E1FCD0 /* OTICDPRecordContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FED23C7D4C9006F4582 /* OTICDPRecordContext.m */; }; + 0CCC21FD23F33DCE00E1FCD0 /* OTCDPRecoveryInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FEE23C7D4CA006F4582 /* OTCDPRecoveryInformation.m */; }; + 0CCC21FE23F33DD400E1FCD0 /* OTEscrowAuthenticationInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C468FEC23C7D4C9006F4582 /* OTEscrowAuthenticationInformation.m */; }; + 0CCC21FF23F3577A00E1FCD0 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; + 0CCC22A023F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CCC229F23F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m */; }; + 0CCC22A423F374EB00E1FCD0 /* OctagonTrust.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */; }; + 0CCC22A523F3763C00E1FCD0 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; + 0CCC22A623F3868400E1FCD0 /* OTControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C8BBF0E1FCB452400580909 /* OTControl.m */; }; + 0CCC22A823F38AD600E1FCD0 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; + 0CCC22A923F38AFD00E1FCD0 /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; + 0CCC22AE23F38B2D00E1FCD0 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + 0CCC22B223F38B5B00E1FCD0 /* libsqlite3.0.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22B123F38B5B00E1FCD0 /* libsqlite3.0.tbd */; }; + 0CCC22B323F38B6D00E1FCD0 /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; + 0CCC22B623F38BCD00E1FCD0 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; }; + 0CCC22B723F38BF500E1FCD0 /* CloudKitMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC222CA71E08A7D900B09171 /* CloudKitMockXCTest.m */; }; + 0CCC22B823F38C0E00E1FCD0 /* MockCloudKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3502E61E0214C800BC0587 /* MockCloudKit.m */; }; + 0CCC22B923F38C3000E1FCD0 /* CKKSMockSOSPresentAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA9BC06221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.m */; }; + 0CCC22BB23F38C8800E1FCD0 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; + 0CCC22BC23F38D3500E1FCD0 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; + 0CCC22BD23F38D4B00E1FCD0 /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EB49B2DC202DF251003F34A0 /* libbsm.tbd */; }; + 0CCC22BE23F38D7C00E1FCD0 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; + 0CCC22BF23F38D8E00E1FCD0 /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; + 0CCC22C023F38DA100E1FCD0 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; + 0CCC22C123F38DC100E1FCD0 /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; + 0CCC22C723F3904D00E1FCD0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 0CCC22C823F390E400E1FCD0 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47D1838B1FB3827700CFCD89 /* OCMock.framework */; }; + 0CCC22C923F3932600E1FCD0 /* CloudKitKeychainSyncingTestsBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CA4EBF2202B8D1D002B1D96 /* CloudKitKeychainSyncingTestsBase.m */; }; + 0CCC22CA23F3933000E1FCD0 /* CloudKitKeychainSyncingMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC08D1C31E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m */; }; + 0CCC22D623F39B2E00E1FCD0 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; + 0CCC22D723F39B7200E1FCD0 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; + 0CCC22D823F39BCA00E1FCD0 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; 0CCDE7171EEB08220021A946 /* secd-156-timers.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CCDE7161EEB08220021A946 /* secd-156-timers.m */; }; 0CD3D519224048A800024755 /* OTSetRecoveryKeyOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD3D5152240479600024755 /* OTSetRecoveryKeyOperation.m */; }; + 0CD5040523F39DEA0036C279 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */; }; 0CD5797A21498F8200C43496 /* OctagonPairingTests+Piggybacking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD5797721498F7700C43496 /* OctagonPairingTests+Piggybacking.swift */; }; + 0CD743AA23C3EC8000FA0EC5 /* OctagonTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CD743A823C3EC8000FA0EC5 /* OctagonTrust.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0CD743AF23C3ECEB00FA0EC5 /* ProtocolBuffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C441E2537CC007F95E5 /* ProtocolBuffer.framework */; }; + 0CD743BB23C3EF1D00FA0EC5 /* OTClique+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CD743BA23C3EF0D00FA0EC5 /* OTClique+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0CD743BC23C3EF1E00FA0EC5 /* OTClique+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CD743BA23C3EF0D00FA0EC5 /* OTClique+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0CD8CB051ECA50780076F37F /* SOSPeerOTRTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD8CB041ECA50780076F37F /* SOSPeerOTRTimer.m */; }; 0CD8CB0B1ECA50920076F37F /* SOSPeerOTRTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD8CB041ECA50780076F37F /* SOSPeerOTRTimer.m */; }; 0CD9E34323592DD7002995DE /* OctagonSignPosts.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CD9E33E235928D1002995DE /* OctagonSignPosts.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -956,7 +1028,6 @@ 0CD9E34523592EA6002995DE /* OctagonSignPosts.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD9E340235928E9002995DE /* OctagonSignPosts.m */; }; 0CD9E34623592EA7002995DE /* OctagonSignPosts.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD9E340235928E9002995DE /* OctagonSignPosts.m */; }; 0CDD6F79226E83F6009094C2 /* OTTriggerEscrowUpdateOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CDD6F76226E62AD009094C2 /* OTTriggerEscrowUpdateOperation.m */; }; - 0CE079F41FEA15B20040A3F1 /* SFBehavior.m in Sources */ = {isa = PBXBuildFile; fileRef = EB82A2A51FAFF26900CA64A9 /* SFBehavior.m */; }; 0CE15E2C222DF63600B7EAA4 /* RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E2A222DF63500B7EAA4 /* RecoveryKey.swift */; }; 0CE15E2D222DF63600B7EAA4 /* RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E2A222DF63500B7EAA4 /* RecoveryKey.swift */; }; 0CE15E2F222DF63600B7EAA4 /* RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E2A222DF63500B7EAA4 /* RecoveryKey.swift */; }; @@ -971,7 +1042,6 @@ 0CE15E43222DF6A800B7EAA4 /* Recovery.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E3C222DF6A700B7EAA4 /* Recovery.m */; }; 0CE15E44222DF6A800B7EAA4 /* Recovery.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E3C222DF6A700B7EAA4 /* Recovery.m */; }; 0CE15E46222DF6A800B7EAA4 /* Recovery.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CE15E3C222DF6A700B7EAA4 /* Recovery.m */; }; - 0CE751AF20ACC497002B2832 /* SFSignInAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */; }; 0CE760501E1301DC00B4381E /* SOSAccountTrustClassic+Expansion.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CE7604F1E1301DC00B4381E /* SOSAccountTrustClassic+Expansion.h */; }; 0CE760521E1314F700B4381E /* SOSAccountTrustClassic+Identity.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CE760511E1314F700B4381E /* SOSAccountTrustClassic+Identity.h */; }; 0CE760541E13155100B4381E /* SOSAccountTrustClassic+Circle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CE760531E13155100B4381E /* SOSAccountTrustClassic+Circle.h */; }; @@ -982,7 +1052,6 @@ 0CE887D32299A9090082D120 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 0CE887D52299A9C70082D120 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; 0CE902352395D0A3005E3F8C /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; - 0CF406522072E422003D6A7F /* SFSignInAnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */; }; 0CF70BD9218BED1000EC3515 /* CuttlefishExtensionWorkaround.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF70BD6218BECF500EC3515 /* CuttlefishExtensionWorkaround.swift */; }; 0CF70BDA218BEFAE00EC3515 /* CuttlefishExtensionWorkaround.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF70BD6218BECF500EC3515 /* CuttlefishExtensionWorkaround.swift */; }; 0CF70BDB218BEFF000EC3515 /* CuttlefishExtensionWorkaround.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF70BD6218BECF500EC3515 /* CuttlefishExtensionWorkaround.swift */; }; @@ -1089,7 +1158,6 @@ 3DD1FF9F201FC5410086D049 /* STLegacyTests+sslciphers.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1FE81201AA5100086D049 /* STLegacyTests+sslciphers.m */; }; 3DD1FFA0201FC5450086D049 /* STLegacyTests+tls12.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1FE7D201AA50E0086D049 /* STLegacyTests+tls12.m */; }; 3DD1FFA1201FC5660086D049 /* ssl-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCA451D8B82CD00070CB0 /* ssl-utils.c */; }; - 3DD1FFA2201FC5800086D049 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; 3DD1FFA3201FC5870086D049 /* libDiagnosticMessagesClient.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41D36701EB14D87007FA978 /* libDiagnosticMessagesClient.tbd */; }; 3DD1FFA4201FC58F0086D049 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 3DD1FFA5201FC59D0086D049 /* libsecurity_ssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BC9CF1D8B824700070CB0 /* libsecurity_ssl.a */; }; @@ -1116,13 +1184,15 @@ 3DD1FFC6201FDB1D0086D049 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; 3DD1FFC8201FDB1D0086D049 /* libsecurity_ssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BC9CF1D8B824700070CB0 /* libsecurity_ssl.a */; }; 3DD1FFC9201FDB1D0086D049 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; - 3DD1FFCB201FDB1D0086D049 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; 3DD1FFD1201FDC460086D049 /* STLegacyTests+clientauth41.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1FE78201AA50C0086D049 /* STLegacyTests+clientauth41.m */; }; 3DD1FFD5201FF7860086D049 /* SecureTransport_iosTests.plist in Copy Plist */ = {isa = PBXBuildFile; fileRef = 3DD1FE86201AA5120086D049 /* SecureTransport_iosTests.plist */; }; 3DD1FFD7201FF7B10086D049 /* SecureTransport_macosTests.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3DD1FE79201AA50D0086D049 /* SecureTransport_macosTests.plist */; }; 3DD2589F20478CF900F5DA78 /* STLegacyTests+session.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD2589820478CCE00F5DA78 /* STLegacyTests+session.m */; }; 3DD258A020478CFA00F5DA78 /* STLegacyTests+session.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD2589820478CCE00F5DA78 /* STLegacyTests+session.m */; }; 3DD258AC2051F10300F5DA78 /* STLegacyTests+sni.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD1FE7F201AA50F0086D049 /* STLegacyTests+sni.m */; }; + 3E88360D24F068EF00E9F4D6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 3E88361424F0699F00E9F4D6 /* secseccodeapitest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3E88361324F0699F00E9F4D6 /* secseccodeapitest.c */; }; + 3E88361B24F08DA100E9F4D6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; 433E519E1B66D5F600482618 /* AppSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 433E519D1B66D5F600482618 /* AppSupport.framework */; }; 4381603A1B4DCE8F00C54D58 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; 4381603B1B4DCEFF00C54D58 /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; @@ -1258,7 +1328,6 @@ 4718AE92205B39C40068EC3F /* CKKSSIV.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D541E2826DB0089CF55 /* CKKSSIV.m */; }; 4718AE96205B39C40068EC3F /* CKKSZoneChangeFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = DC9082C31EA0276000D0C1C5 /* CKKSZoneChangeFetcher.m */; }; 4718AE97205B39C40068EC3F /* CKKSCondition.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFE1C331F17ECE5007640C8 /* CKKSCondition.m */; }; - 4718AE98205B39C40068EC3F /* CKKSZone.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D961E3014250089CF55 /* CKKSZone.m */; }; 4718AE99205B39C40068EC3F /* SFKeychainServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 47FF17251FD60ACA00875565 /* SFKeychainServer.m */; }; 4718AE9B205B39C40068EC3F /* swcagent_client.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78EA01D80860C00865A7C /* swcagent_client.c */; }; 4718AE9E205B39C40068EC3F /* SecDbKeychainSerializedAKSWrappedKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 47922D371FAA7C040008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.h */; }; @@ -1338,7 +1407,6 @@ 4727FBC91F991E5A0003AE36 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 4727FBCD1F991F660003AE36 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBCC1F991F660003AE36 /* libsqlite3.dylib */; }; 4727FBCE1F991F820003AE36 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBCF1F991F820003AE36 /* SecurityFoundation.framework */; }; - 4727FBD11F991F990003AE36 /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD01F991F990003AE36 /* libMobileGestalt.dylib */; }; 4727FBD31F9920290003AE36 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD21F9920290003AE36 /* CloudKit.framework */; }; 4727FBD51F9920510003AE36 /* ProtocolBuffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD41F9920510003AE36 /* ProtocolBuffer.framework */; }; 4727FBD61F9920960003AE36 /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; @@ -1363,7 +1431,6 @@ 475F37201EE8F23900248FB5 /* SFAnalytics.plist in Resources */ = {isa = PBXBuildFile; fileRef = 475F371F1EE8F23900248FB5 /* SFAnalytics.plist */; }; 475F37211EE8F23900248FB5 /* SFAnalytics.plist in Resources */ = {isa = PBXBuildFile; fileRef = 475F371F1EE8F23900248FB5 /* SFAnalytics.plist */; }; 4764E9272059D866005497C9 /* KeychainModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 470D966B1FCDE4BA0065FE90 /* KeychainModel.xcdatamodeld */; }; - 4764E92D2059D8BF005497C9 /* KeychainModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 470D966B1FCDE4BA0065FE90 /* KeychainModel.xcdatamodeld */; }; 476541651F339F6300413F65 /* SecdWatchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = 476541631F339F6300413F65 /* SecdWatchdog.h */; }; 476541701F33B59300413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 476541711F33B59500413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; @@ -1371,8 +1438,6 @@ 476541A11F33EDA500413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 476541A21F33EDAD00413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 476541A31F33EDCC00413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; - 476541A41F33EDED00413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; - 476541A51F33EE1E00413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 476541A61F33EE2700413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 476541A71F33EE3F00413F65 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; 47702B181E5E58E600B29577 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40B6A881E2B5F9900CD6EE5 /* Foundation.framework */; }; @@ -1386,47 +1451,13 @@ 4771D9A0209B7C2700BA9772 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4771D99F209B7C2600BA9772 /* Security.framework */; }; 4771D9A2209B7C3900BA9772 /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4771D9A1209B7C3900BA9772 /* Accounts.framework */; }; 477A1F5220320E4A00ACD81D /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 477A1F4C20320E4900ACD81D /* Accounts.framework */; }; - 477A1F5320320E5100ACD81D /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF4C19C171E0EA600877419 /* Accounts.framework */; }; 477A1FE4203763A500ACD81D /* KeychainAPITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 477A1FE1203763A500ACD81D /* KeychainAPITests.m */; }; - 477A1FE5203763A500ACD81D /* KeychainAPITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 477A1FE1203763A500ACD81D /* KeychainAPITests.m */; }; 477A1FED2037A0E000ACD81D /* KeychainXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 477A1FEC2037A0E000ACD81D /* KeychainXCTest.m */; }; - 477A1FEE2037A0E000ACD81D /* KeychainXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 477A1FEC2037A0E000ACD81D /* KeychainXCTest.m */; }; 478014541FBF577000C4043D /* si-44-seckey-proxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 09A3B9DF1F8271A200C5C324 /* si-44-seckey-proxy.m */; }; 4780146A1FBF5BD600C4043D /* SecKeyProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 09E9991F1F7D76550018DF67 /* SecKeyProxy.m */; }; 478014701FBF5BD800C4043D /* SecKeyProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 09E9991F1F7D76550018DF67 /* SecKeyProxy.m */; }; 478014791FBF5D2000C4043D /* SecKeyProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 09A3B9D71F8267BB00C5C324 /* SecKeyProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4780147F1FBF5D2100C4043D /* SecKeyProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 09A3B9D71F8267BB00C5C324 /* SecKeyProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 478D42761FD72A8100CAB645 /* server_xpc.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB2214A1E8B0861001598BC /* server_xpc.m */; }; - 478D42771FD72A8100CAB645 /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; - 478D42781FD72A8100CAB645 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; - 478D42791FD72A8100CAB645 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; - 478D427A1FD72A8100CAB645 /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; - 478D427B1FD72A8100CAB645 /* KeychainCryptoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4727FBB91F9918590003AE36 /* KeychainCryptoTests.m */; }; - 478D427C1FD72A8100CAB645 /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; - 478D427F1FD72A8100CAB645 /* libprequelite.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 472339611FD7155C00CB6A72 /* libprequelite.dylib */; }; - 478D42801FD72A8100CAB645 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47D1838B1FB3827700CFCD89 /* OCMock.framework */; }; - 478D42811FD72A8100CAB645 /* libregressionBase.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCBFD1D8C648C00070CB0 /* libregressionBase.a */; }; - 478D42821FD72A8100CAB645 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBE81F9921D00003AE36 /* libACM.a */; }; - 478D42831FD72A8100CAB645 /* ApplePushService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBE61F9921890003AE36 /* ApplePushService.framework */; }; - 478D42841FD72A8100CAB645 /* SharedWebCredentials.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBE41F99217A0003AE36 /* SharedWebCredentials.framework */; }; - 478D42851FD72A8100CAB645 /* MobileKeyBag.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBE21F9921660003AE36 /* MobileKeyBag.framework */; }; - 478D42861FD72A8100CAB645 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBE01F99212F0003AE36 /* IOKit.framework */; }; - 478D42871FD72A8100CAB645 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBDE1F99211D0003AE36 /* libaks.a */; }; - 478D42881FD72A8100CAB645 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBDC1F9920F10003AE36 /* libaks_acl.a */; }; - 478D42891FD72A8100CAB645 /* WirelessDiagnostics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBDA1F9920CB0003AE36 /* WirelessDiagnostics.framework */; }; - 478D428A1FD72A8100CAB645 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD81F9920BB0003AE36 /* SystemConfiguration.framework */; }; - 478D428B1FD72A8100CAB645 /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; - 478D428C1FD72A8100CAB645 /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; - 478D428D1FD72A8100CAB645 /* ProtocolBuffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD41F9920510003AE36 /* ProtocolBuffer.framework */; }; - 478D428E1FD72A8100CAB645 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBD21F9920290003AE36 /* CloudKit.framework */; }; - 478D42901FD72A8100CAB645 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBCF1F991F820003AE36 /* SecurityFoundation.framework */; }; - 478D42911FD72A8100CAB645 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBCC1F991F660003AE36 /* libsqlite3.dylib */; }; - 478D42931FD72A8100CAB645 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; - 478D42951FD72A8100CAB645 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; }; - 478D42961FD72A8100CAB645 /* libsecdRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52EDB11D80D58400B0A59C /* libsecdRegressions.a */; }; - 478D42971FD72A8100CAB645 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBC41F991C460003AE36 /* Foundation.framework */; }; - 478D429E1FD72C4800CAB645 /* CrashReporterSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E9391D7F3DF200AFB96E /* CrashReporterSupport.framework */; }; - 478D429F1FD72C8400CAB645 /* AppleSystemInfo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3F1D78F2FF002223DE /* AppleSystemInfo.framework */; }; 479108B71EE879F9008CEFA0 /* CKKSAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 479108B51EE879F9008CEFA0 /* CKKSAnalytics.h */; }; 4791B4652118BBFF00977C3F /* OTControlProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C8BBF0C1FCB452200580909 /* OTControlProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4791B46B2118BC0000977C3F /* OTControlProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C8BBF0C1FCB452200580909 /* OTControlProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -1440,7 +1471,6 @@ 47922D541FAA7E060008F7E0 /* SecDbKeychainSerializedItemV7.h in Headers */ = {isa = PBXBuildFile; fileRef = 47922D501FAA7DF60008F7E0 /* SecDbKeychainSerializedItemV7.h */; }; 47922D561FAA7E0D0008F7E0 /* SecDbKeychainSerializedItemV7.m in Sources */ = {isa = PBXBuildFile; fileRef = 47922D511FAA7DF70008F7E0 /* SecDbKeychainSerializedItemV7.m */; }; 479231E82065B31300B2718C /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; - 479231EE2065B32200B2718C /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; 479231EF2065C52200B2718C /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; }; 479231F02065C52D00B2718C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; 479DA1721EBBA8D10065C98F /* CKKSManifest.m in Sources */ = {isa = PBXBuildFile; fileRef = 47CEED1F1E60DE900044EAB4 /* CKKSManifest.m */; }; @@ -1449,7 +1479,6 @@ 47A05B181FDB5DBC00D0816E /* SFKeychainControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 47A05B101FDB5A8B00D0816E /* SFKeychainControl.h */; }; 47A0ABA81E6F7B24001B388C /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 474B5FBF1E662E21007546F8 /* SecurityFoundation.framework */; }; 47A91562201A43BA00FF8F46 /* SecSharedCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = BE061FE01899ECEE00C739F6 /* SecSharedCredential.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 47B011991F17D78D0030B49F /* SFSQLiteStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BF1F152EB10082882F /* SFSQLiteStatement.m */; }; 47B90C901F350966006500BC /* CrashReporterSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E9391D7F3DF200AFB96E /* CrashReporterSupport.framework */; }; 47C2F1762059A2300062DE30 /* libprequelite.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CE98B5B1FA9360700CF1D54 /* libprequelite.tbd */; }; 47C2F1842059CB680062DE30 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4727FBC41F991C460003AE36 /* Foundation.framework */; }; @@ -1471,15 +1500,13 @@ 482FE5642177C6850031C11E /* libprequelite.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CE98B5B1FA9360700CF1D54 /* libprequelite.tbd */; }; 482FE5652177C6D90031C11E /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF4C19C171E0EA600877419 /* Accounts.framework */; }; 482FE5662177C6E40031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; - 482FE5672177C7260031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; - 482FE5682177C73C0031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 482FE5692177C7670031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; - 482FE56A2177C7980031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 482FE56C2177CEEF0031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 482FE56D2177CF150031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 482FE56E2177CF340031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 482FE56B2177C7AE0031C11E /* AuthKit.framework */; }; 482FE56F2177CF520031C11E /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; 483E798F1DC87605005C0008 /* secd-67-prefixedKeyIDs.m in Sources */ = {isa = PBXBuildFile; fileRef = 483E79891DC875F2005C0008 /* secd-67-prefixedKeyIDs.m */; }; + 487A65F4245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m in Sources */ = {isa = PBXBuildFile; fileRef = 487A65F3245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m */; }; 48AC7B73232B1DA600F02B6F /* SOSIntervalEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 48AC7B71232B1A7000F02B6F /* SOSIntervalEvent.m */; }; 48CC589F1DA5FF2700EBD9DB /* secd-66-account-recovery.m in Sources */ = {isa = PBXBuildFile; fileRef = 48CC58971DA5FF0B00EBD9DB /* secd-66-account-recovery.m */; }; 48FE669620E6E69D00FAEF17 /* SOSAuthKitHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 48FE668F20E6E69B00FAEF17 /* SOSAuthKitHelpers.m */; }; @@ -1693,13 +1720,9 @@ 5A04BB1A22986717001848A0 /* SecXPCHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A04BB182298670C001848A0 /* SecXPCHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5A06118E229ED5EB006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; 5A061191229ED6DB006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; - 5A061192229ED6E5006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; - 5A061193229ED6E6006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; 5A061194229ED6E7006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; 5A061196229ED6E8006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; 5A061197229ED6EB006AF14A /* NSDate+SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A06118D229ED5EB006AF14A /* NSDate+SFAnalytics.m */; }; - 5A061198229ED8F3006AF14A /* NSDate+SFAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A061190229ED60C006AF14A /* NSDate+SFAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 5A061199229ED8F4006AF14A /* NSDate+SFAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A061190229ED60C006AF14A /* NSDate+SFAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5A0F84A522AEAF5B0097AEEA /* NSDate+SFAnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A1A1C2122A71D2A00CB8D1D /* NSDate+SFAnalyticsTests.m */; }; 5A43A083225FA39C005450E4 /* SecProtocolHelperTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A43A07F225FA38D005450E4 /* SecProtocolHelperTest.m */; }; 5A43A084225FA3A5005450E4 /* SecProtocolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = AA44E0B3202E3451001EA371 /* SecProtocolTest.m */; }; @@ -1763,15 +1786,30 @@ 5F00F9592306147A00B832E0 /* SecImportExport.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E551D8085FC00865A7C /* SecImportExport.c */; }; 5F00F95B230614AC00B832E0 /* SecImportExportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F00F95A230614A200B832E0 /* SecImportExportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5F00F95C230614AD00B832E0 /* SecImportExportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F00F95A230614A200B832E0 /* SecImportExportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5F4C22002489C6AB00F0C425 /* simulatecrash_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F4C21FE2489C68900F0C425 /* simulatecrash_assert.h */; }; + 5F4C22012489C6AC00F0C425 /* simulatecrash_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F4C21FE2489C68900F0C425 /* simulatecrash_assert.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5F84950222DFB505008B3EFB /* SecTrustExceptionResetCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F8494FF22DFB502008B3EFB /* SecTrustExceptionResetCount.m */; }; 6C02134E21F7ED25009D5C80 /* SecDbBackupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C02134D21F7ED16009D5C80 /* SecDbBackupTests.m */; }; - 6C02135021F7EF07009D5C80 /* SecDbBackupTests.plist in Copy BATS Test Discovery Plist */ = {isa = PBXBuildFile; fileRef = 6C02134C21F7ED16009D5C80 /* SecDbBackupTests.plist */; }; + 6C06CB902408602900025303 /* SecItemInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEDF7370F3A6CFB0027C4FE /* SecItemInternal.h */; }; + 6C06CB912408602A00025303 /* SecItemInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEDF7370F3A6CFB0027C4FE /* SecItemInternal.h */; }; 6C1260FD1F7DA42D001B2EEC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; 6C13AE471F8E9F5F00F047E3 /* supd.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69517E1F758E1000F68F91 /* supd.m */; }; 6C13AE481F8E9FC800F047E3 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 6C1520D41DCCF71400C85C6D /* secd.8 in Install man8 page */ = {isa = PBXBuildFile; fileRef = 6C1520CD1DCCF57A00C85C6D /* secd.8 */; }; + 6C16258723C4FFEC0086A0FF /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; + 6C16258823C5001C0086A0FF /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; 6C1F93111DD5E41A00585608 /* libDiagnosticMessagesClient.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3C1D78F25C002223DE /* libDiagnosticMessagesClient.dylib */; }; + 6C2045F12424BAC900F9461D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C99786D242362EC008C498D /* main.m */; }; + 6C2045F22424BACE00F9461D /* KeychainStasher.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C99786B242362EC008C498D /* KeychainStasher.m */; }; + 6C2045F42424BBCD00F9461D /* com.apple.security.KeychainStasher.sb in Install Sandbox Profile */ = {isa = PBXBuildFile; fileRef = 6C48D10F2423A3C0004AF950 /* com.apple.security.KeychainStasher.sb */; }; + 6C2045F52424BBDD00F9461D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C997879242364E5008C498D /* Foundation.framework */; }; + 6C2045FB2424BCD600F9461D /* com.apple.security.KeychainStasher.plist in Install LaunchAgent plist */ = {isa = PBXBuildFile; fileRef = 6C2045F92424BCB800F9461D /* com.apple.security.KeychainStasher.plist */; }; + 6C2138C4225183FE007DEDD3 /* SecDbKeychainSerializedMetadataKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */; }; + 6C220088244F075E000A4557 /* SecItemRateLimit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C513A38244F007B00207D5E /* SecItemRateLimit.m */; }; + 6C22008A244F0760000A4557 /* SecItemRateLimit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C513A38244F007B00207D5E /* SecItemRateLimit.m */; }; 6C23F02F227A3A28009F6756 /* com.apple.securityd.sb in Install Sandbox Profile */ = {isa = PBXBuildFile; fileRef = 6C23F02C227A39E9009F6756 /* com.apple.securityd.sb */; }; + 6C2D463D24C88AA10015C3C9 /* LegacyAPICounts.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */; }; + 6C2D463E24C88AA60015C3C9 /* LegacyAPICounts.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C2D463924C88A700015C3C9 /* LegacyAPICounts.h */; }; 6C32BB9920EAE6B00042DF59 /* LocalKeychainAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */; }; 6C32D36420F2C23100ACAB2C /* TPPBPolicyRedaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C70D8DE20EBDFD700AB6FAF /* TPPBPolicyRedaction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6C32D36520F2C23D00ACAB2C /* TPPBPolicyDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C0C807420EAF81900334E33 /* TPPBPolicyDocument.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -1835,12 +1873,56 @@ 6C588D801EAA20AB00D7E322 /* RateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CC7F5B31E9F99EE0014AE63 /* RateLimiter.m */; }; 6C5B36BA1E2F9B95008AD443 /* WirelessDiagnostics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C3D1E2537C6007F95E5 /* WirelessDiagnostics.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 6C5B36C01E2F9BEA008AD443 /* WirelessDiagnostics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C3D1E2537C6007F95E5 /* WirelessDiagnostics.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 6C5D62A6221B6E3F00AF79DC /* secdxctests-entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6C5D62A5221B6E3F00AF79DC /* secdxctests-entitlements.plist */; }; + 6C61D3E9242A2C14008AB9BB /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; + 6C6AF17A221A06790091CE0A /* SecDbKeychainSerializedMetadataKey.proto in Sources */ = {isa = PBXBuildFile; fileRef = 6C6AF178221A03930091CE0A /* SecDbKeychainSerializedMetadataKey.proto */; }; + 6C6AF17F221A07090091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */; }; + 6C6AF180221A070A0091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */; }; + 6C6AF181221A070C0091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */; }; + 6C6AF182221A07230091CE0A /* SecDbKeychainSerializedMetadataKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C6AF17D221A06F70091CE0A /* SecDbKeychainSerializedMetadataKey.h */; }; + 6C6AF183221A07240091CE0A /* SecDbKeychainSerializedMetadataKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C6AF17D221A06F70091CE0A /* SecDbKeychainSerializedMetadataKey.h */; }; + 6C6B3AC623F1A820002827C2 /* KeychainEntitlementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 09BFE35A20A32E0E008511E9 /* KeychainEntitlementsTest.m */; }; + 6C6B3ADF23F1B3E0002827C2 /* KeychainAppClipTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C84E3C723ECBC84003C9710 /* KeychainAppClipTests.m */; }; 6C7094CC2239D21E00C5DAC6 /* SecDbBackupManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AEF8B218A0A400012C5DA /* SecDbBackupManager.m */; }; 6C73F48A2006B839003D5D63 /* SOSAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C7BB0032006B4EE004D1B6B /* SOSAnalytics.m */; }; 6C73F48B2006B83A003D5D63 /* SOSAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C7BB0032006B4EE004D1B6B /* SOSAnalytics.m */; }; 6C73F48D2006B83E003D5D63 /* SOSAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C7BB0032006B4EE004D1B6B /* SOSAnalytics.m */; }; 6C73F48F2006B910003D5D63 /* SOSAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C7BB0042006B4EF004D1B6B /* SOSAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6C73F4902006B911003D5D63 /* SOSAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C7BB0042006B4EF004D1B6B /* SOSAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 6C75560624212B4400025D78 /* keychainstasherinterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C755603242121F000025D78 /* keychainstasherinterface.m */; }; + 6C7BE2B823C3DD64003BB2CA /* SecurityTool.c in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA981D80CC2A00B0A59C /* SecurityTool.c */; }; + 6C7BE2B923C3DD64003BB2CA /* scep.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E231D8085FC00865A7C /* scep.c */; }; + 6C7BE2BA23C3DD64003BB2CA /* trust_update.m in Sources */ = {isa = PBXBuildFile; fileRef = D453C38A1FEC669300DE349B /* trust_update.m */; }; + 6C7BE2BB23C3DD64003BB2CA /* keychain_backup.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E211D8085FC00865A7C /* keychain_backup.c */; }; + 6C7BE2BC23C3DD64003BB2CA /* whoami.m in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA911D80CC2A00B0A59C /* whoami.m */; }; + 6C7BE2BE23C3DD64003BB2CA /* KeychainCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 473337831FDB29A200E19F30 /* KeychainCheck.m */; }; + 6C7BE2BF23C3DD64003BB2CA /* log_control.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E1D1D8085FC00865A7C /* log_control.c */; }; + 6C7BE2C023C3DD64003BB2CA /* not_on_this_platorm.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCDB41D8C6A5B00070CB0 /* not_on_this_platorm.c */; }; + 6C7BE2C123C3DD64003BB2CA /* keychain_util.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E1A1D8085FC00865A7C /* keychain_util.c */; }; + 6C7BE2C223C3DD64003BB2CA /* security_tool_commands.c in Sources */ = {isa = PBXBuildFile; fileRef = E7104A0B169E171900DB0045 /* security_tool_commands.c */; }; + 6C7BE2C323C3DD64003BB2CA /* codesign.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E1E1D8085FC00865A7C /* codesign.c */; }; + 6C7BE2C523C3DD64003BB2CA /* NSFileHandle+Formatting.m in Sources */ = {isa = PBXBuildFile; fileRef = E78A9AD91D34959200006B5B /* NSFileHandle+Formatting.m */; }; + 6C7BE2C623C3DD64003BB2CA /* keychain_find.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E201D8085FC00865A7C /* keychain_find.m */; }; + 6C7BE2C723C3DD64003BB2CA /* readline.c in Sources */ = {isa = PBXBuildFile; fileRef = DC65E7BE1D8CBB1500152EF0 /* readline.c */; }; + 6C7BE2C823C3DD64003BB2CA /* add_internet_password.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E1C1D8085FC00865A7C /* add_internet_password.c */; }; + 6C7BE2C923C3DD64003BB2CA /* digest_calc.c in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA8F1D80CC2A00B0A59C /* digest_calc.c */; }; + 6C7BE2CA23C3DD64003BB2CA /* leaks.c in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA931D80CC2A00B0A59C /* leaks.c */; }; + 6C7BE2CB23C3DD64003BB2CA /* show_certificates.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E251D8085FC00865A7C /* show_certificates.c */; }; + 6C7BE2CC23C3DD64003BB2CA /* spc.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E261D8085FC00865A7C /* spc.c */; }; + 6C7BE2CD23C3DD64003BB2CA /* verify_cert.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E191D8085FC00865A7C /* verify_cert.c */; }; + 6C7BE2CE23C3DD64003BB2CA /* ct_exceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = D4A3A596217A85CB00F0A8DA /* ct_exceptions.m */; }; + 6C7BE2CF23C3DD64003BB2CA /* keychain_add.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E1F1D8085FC00865A7C /* keychain_add.c */; }; + 6C7BE2D023C3DD64003BB2CA /* pkcs12_util.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E221D8085FC00865A7C /* pkcs12_util.c */; }; + 6C7BE2D123C3DD64003BB2CA /* print_cert.c in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA951D80CC2A00B0A59C /* print_cert.c */; }; + 6C7BE2D423C3DD64003BB2CA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; + 6C7BE2D723C3DD64003BB2CA /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; + 6C7BE2D823C3DD64003BB2CA /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; + 6C7BE2D923C3DD64003BB2CA /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E43C48C1B00D07000E5ECB2 /* CoreFoundation.framework */; }; + 6C7BE2DC23C3DD64003BB2CA /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.a */; }; + 6C7BE2DD23C3DD64003BB2CA /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; + 6C7BE2E023C3DD64003BB2CA /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 6C7BE2E323C3DD64003BB2CA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 6C7BE2EB23C3DDC3003BB2CA /* libsecurityd_bridge.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4718AEE2205B39C40068EC3F /* libsecurityd_bridge.a */; }; 6C7FD5DF1F87FA42002C2285 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; 6C814A4C2050B4B600CB391B /* LocalKeychainAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C814A4A2050B4B600CB391B /* LocalKeychainAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6C814A4D2050B4B600CB391B /* LocalKeychainAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */; }; @@ -1858,73 +1940,30 @@ 6C8CC3B61E2F98C2009025C5 /* ProtocolBuffer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C0B0C441E2537CC007F95E5 /* ProtocolBuffer.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 6C8CE6C11FA248DA0032ADF0 /* SFAnalyticsActivityTracker+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C8CE6BB1FA248B50032ADF0 /* SFAnalyticsActivityTracker+Internal.h */; }; 6C8CE6C21FA248DB0032ADF0 /* SFAnalyticsActivityTracker+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C8CE6BB1FA248B50032ADF0 /* SFAnalyticsActivityTracker+Internal.h */; }; - 6C8FF4B3224C1A8D00E5C812 /* TrustedPeers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BEF88C281EAFFC3F00357577 /* TrustedPeers.framework */; }; + 6C912AA0227A3E9600671FC6 /* CheckV12DevEnabled.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AEF83218A09210012C5DA /* CheckV12DevEnabled.m */; }; + 6C912AA1227A3E9700671FC6 /* CheckV12DevEnabled.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C4AEF83218A09210012C5DA /* CheckV12DevEnabled.m */; }; + 6C963284242A279B00C53CE2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C963283242A279B00C53CE2 /* main.m */; }; + 6C96328A242A284C00C53CE2 /* MobileKeyBag.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FC30AB1332DE9000802946 /* MobileKeyBag.framework */; }; + 6C97434824D1C8CB00A2025C /* LegacyAPICounts.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C2D463924C88A700015C3C9 /* LegacyAPICounts.h */; }; + 6C97434A24D1C8DE00A2025C /* LegacyAPICounts.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */; }; 6C9791C821C20CFF0074C609 /* NSError+UsefulConstructors.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAE1DD62073FCDE00B4F687 /* NSError+UsefulConstructors.m */; }; 6C9791C921C2EAB60074C609 /* NSError+UsefulConstructors.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAE1DD62073FCDE00B4F687 /* NSError+UsefulConstructors.m */; }; - 6C9791CA21C2EAB70074C609 /* NSError+UsefulConstructors.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAE1DD62073FCDE00B4F687 /* NSError+UsefulConstructors.m */; }; 6C9791CB21C325C30074C609 /* SecDbBackupRecoverySet.proto in Sources */ = {isa = PBXBuildFile; fileRef = 6CB6CC022198D4BC0080AD6F /* SecDbBackupRecoverySet.proto */; }; - 6C98083E1E788AEB00E70590 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; - 6C98084A1E788AEB00E70590 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; - 6C98084D1E788AEB00E70590 /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; - 6C98084E1E788AEB00E70590 /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; - 6C98084F1E788AEB00E70590 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; }; - 6C9808501E788AEB00E70590 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; - 6C9808511E788AEB00E70590 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; - 6C9808521E788AEB00E70590 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; - 6C9808531E788AEB00E70590 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; - 6C9808541E788AEB00E70590 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; }; - 6C9808551E788AEB00E70590 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; - 6C9808561E788AEB00E70590 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3A1D78F228002223DE /* libACM.a */; }; - 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_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 */; }; - 6C9808861E788AFD00E70590 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; - 6C9808891E788AFD00E70590 /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; - 6C98088A1E788AFD00E70590 /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; - 6C98088B1E788AFD00E70590 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; }; - 6C98088C1E788AFD00E70590 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; - 6C98088D1E788AFD00E70590 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; - 6C98088E1E788AFD00E70590 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; - 6C98088F1E788AFD00E70590 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; - 6C9808901E788AFD00E70590 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; }; - 6C9808911E788AFD00E70590 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; - 6C9808921E788AFD00E70590 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC610A3A1D78F228002223DE /* libACM.a */; }; - 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_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 */; }; - 6CAA8CF01F83E65E007B6E03 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; }; - 6CAA8CF61F83E79D007B6E03 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; - 6CAA8CF71F83E79E007B6E03 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; - 6CAA8CF81F83E7A9007B6E03 /* SFAnalyticsSQLiteStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69518D1F75A7DB00F68F91 /* SFAnalyticsSQLiteStore.m */; }; - 6CAA8CF91F83E7AA007B6E03 /* SFAnalyticsSQLiteStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69518D1F75A7DB00F68F91 /* SFAnalyticsSQLiteStore.m */; }; + 6CA9690A24ACC2D100C08B5E /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 6CAA8CFC1F83E7EA007B6E03 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; }; 6CAA8CFD1F83E7EB007B6E03 /* SFObjCType.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BE1F152EB10082882F /* SFObjCType.m */; }; 6CAA8CFE1F83E800007B6E03 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; 6CAA8CFF1F83E800007B6E03 /* SFSQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BC1F152EB10082882F /* SFSQLite.m */; }; - 6CAA8D0D1F83EC57007B6E03 /* SFSQLiteStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9BF1F152EB10082882F /* SFSQLiteStatement.m */; }; - 6CAA8D131F83ECD4007B6E03 /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; - 6CAA8D141F83ECD5007B6E03 /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; 6CAA8D271F843002007B6E03 /* supd.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69517E1F758E1000F68F91 /* supd.m */; }; 6CAA8D351F84306C007B6E03 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6951801F758E1000F68F91 /* main.m */; }; 6CAA8D371F843196007B6E03 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; 6CAA8D3A1F8431A7007B6E03 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; 6CAA8D3B1F8431AE007B6E03 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40B6A881E2B5F9900CD6EE5 /* Foundation.framework */; }; 6CAB39C71E521BEA00566A79 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 6CB0C5F824ACDB5300479FB4 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; 6CB420A52051FDD500FF2D44 /* LocalKeychainAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */; }; 6CB420AB2051FDE000FF2D44 /* LocalKeychainAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C814A4A2050B4B600CB391B /* LocalKeychainAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6CB5F47B1E402E6700DBF3F0 /* KeychainEntitledTestRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CB5F47A1E402E5700DBF3F0 /* KeychainEntitledTestRunner.m */; }; @@ -1937,8 +1976,6 @@ 6CBF65401FA1480C00A68667 /* SFAnalyticsActivityTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CBF65371FA147E500A68667 /* SFAnalyticsActivityTracker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6CBF65411FA1481100A68667 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; 6CBF65421FA2255800A68667 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; - 6CBF65431FA2257100A68667 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; - 6CBF65441FA2257200A68667 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; 6CC1859E1E24E8EB009657D8 /* CKKSRateLimiter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CC185971E24E87D009657D8 /* CKKSRateLimiter.h */; }; 6CC1859F1E24E8EB009657D8 /* CKKSRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CC185981E24E87D009657D8 /* CKKSRateLimiter.m */; }; 6CC952481FB4CB2C0051A823 /* SFAnalytics+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CC952421FB4C5CA0051A823 /* SFAnalytics+Internal.h */; }; @@ -1946,10 +1983,10 @@ 6CCDF78C1E3C26BC003F2555 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CCDF78B1E3C26BC003F2555 /* XCTest.framework */; }; 6CCDF78D1E3C26C2003F2555 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D40B6A881E2B5F9900CD6EE5 /* Foundation.framework */; }; 6CD1DBED21F9281D00D158FB /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; + 6CD224E623949132001B70FD /* SecDbBackupTestsBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6579FC2394878700701C8B /* SecDbBackupTestsBase.m */; }; + 6CD8412C23F5D871003DDF34 /* KeychainBackupTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CD8412B23F5D871003DDF34 /* KeychainBackupTests.m */; }; 6CDB5FF51FA78D1A00410924 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; 6CDB5FF61FA78D1B00410924 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; - 6CDB5FF81FA78D2300410924 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; - 6CDB5FF91FA78D2400410924 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; 6CDB5FFA1FA78D2500410924 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; 6CDB5FFB1FA78D2C00410924 /* SFAnalyticsMultiSampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CDB5FF41FA78CB500410924 /* SFAnalyticsMultiSampler.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6CDB5FFC1FA78D2D00410924 /* SFAnalyticsMultiSampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CDB5FF41FA78CB500410924 /* SFAnalyticsMultiSampler.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -1957,12 +1994,9 @@ 6CDB60111FA9386200410924 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; 6CDB601A1FA93A1800410924 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CB96BB41F966E0C00E11457 /* libsqlite3.tbd */; }; 6CDB601B1FA93A2000410924 /* libprequelite.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CFDC4561F907E1D00646DBB /* libprequelite.tbd */; }; - 6CDF8DEF1F96495600140B54 /* SFAnalyticsSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDF8DE61F95562B00140B54 /* SFAnalyticsSampler.m */; }; - 6CDF8DF01F96495700140B54 /* SFAnalyticsSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDF8DE61F95562B00140B54 /* SFAnalyticsSampler.m */; }; 6CDF8DF21F9649AB00140B54 /* SFAnalyticsSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDF8DE61F95562B00140B54 /* SFAnalyticsSampler.m */; }; 6CDF8DF31F9649C000140B54 /* SFAnalyticsSQLiteStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C69518D1F75A7DB00F68F91 /* SFAnalyticsSQLiteStore.m */; }; 6CDF8DF41F9649C000140B54 /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; - 6CE22D701E49206600974785 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CE22D6F1E49206600974785 /* UIKit.framework */; }; 6CE3654B1FA100D00012F6AB /* SFAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 4723C9DA1F1540CE0082882F /* SFAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6CE3654C1FA100D10012F6AB /* SFAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 4723C9DA1F1540CE0082882F /* SFAnalytics.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6CE3654D1FA100E50012F6AB /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; @@ -1980,9 +2014,6 @@ 6CF4A0B81E45488B00ECD7B5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0B71E45488B00ECD7B5 /* AppDelegate.m */; }; 6CF4A0BB1E45488B00ECD7B5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0BA1E45488B00ECD7B5 /* main.m */; }; 6CF4A0BE1E45488B00ECD7B5 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0BD1E45488B00ECD7B5 /* ViewController.m */; }; - 6CF4A0E41E4549F200ECD7B5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0E31E4549F200ECD7B5 /* main.m */; }; - 6CF4A0E71E4549F300ECD7B5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0E61E4549F300ECD7B5 /* AppDelegate.m */; }; - 6CF4A0EA1E4549F300ECD7B5 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF4A0E91E4549F300ECD7B5 /* ViewController.m */; }; 7200D76F177B9999009BB396 /* ManagedConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72C3EC2D1705F24E0040C87C /* ManagedConfiguration.framework */; }; 7281E0871DFD01800021E1B7 /* SOSAccountGetSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7281E0861DFD015A0021E1B7 /* SOSAccountGetSet.m */; }; 7281E08D1DFD0B520021E1B7 /* XPCNotificationDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = E7C787331DD0FED50087FC34 /* XPCNotificationDispatcher.m */; }; @@ -2019,6 +2050,15 @@ A690B033208A75D1002FB775 /* notarization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A6B1BA78207BD9D400F1E099 /* notarization.cpp */; }; A6B1BA81207BD9EC00F1E099 /* notarization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A6B1BA78207BD9D400F1E099 /* notarization.cpp */; }; A6B1BA82207BDCB200F1E099 /* notarization.h in Headers */ = {isa = PBXBuildFile; fileRef = A6B1BA79207BD9D400F1E099 /* notarization.h */; }; + A6BC648824897C5E00A21CD7 /* CSCommonPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787441D7790A500B50D50 /* CSCommonPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A6BC6491248B0AB400A21CD7 /* SecStaticCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17874C1D7790A500B50D50 /* SecStaticCodePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A6BF3B3623EB95F0009AF079 /* entitlements.h in Headers */ = {isa = PBXBuildFile; fileRef = A6BF3B3123EB94A7009AF079 /* entitlements.h */; }; + A6C737B923F37A480009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; + A6C737BA23F37A4B0009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; + A6C737BB23F37AB00009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; + A6C737BD23F37AB20009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; + A6C737C023F37AB90009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; + A6C737C123F37AC00009C930 /* entitlements.c in Sources */ = {isa = PBXBuildFile; fileRef = A6BF3B3223EB94A7009AF079 /* entitlements.c */; }; AA0DA47A21E818AB009F1C74 /* builtins.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = AA0DA47921E8189E009F1C74 /* builtins.json */; }; AA0DA47B21E818AB009F1C74 /* example1.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = AA0DA47821E8189D009F1C74 /* example1.json */; }; AA0DA47D21E818D2009F1C74 /* builtins.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = AA0DA47921E8189E009F1C74 /* builtins.json */; }; @@ -2054,7 +2094,6 @@ BE197F5B1911723E00BA91D1 /* SpringBoardUIServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE197F5A1911723E00BA91D1 /* SpringBoardUIServices.framework */; }; BE197F5C1911724900BA91D1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE411314471B000DE34E /* UIKit.framework */; }; BE197F5E191173A800BA91D1 /* SWCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE197F5D191173A800BA91D1 /* SWCViewController.m */; }; - BE197F61191173F200BA91D1 /* entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = BE197F60191173F200BA91D1 /* entitlements.plist */; }; BE22FBC61EE0E8AB00893431 /* Monkey.m in Sources */ = {isa = PBXBuildFile; fileRef = BE22FBC51EE0E8AB00893431 /* Monkey.m */; }; BE22FBCE1EE1E26600893431 /* Keychain.m in Sources */ = {isa = PBXBuildFile; fileRef = BE22FBCD1EE1E26600893431 /* Keychain.m */; }; BE22FBD11EE2084100893431 /* Config.m in Sources */ = {isa = PBXBuildFile; fileRef = BE22FBD01EE2084100893431 /* Config.m */; }; @@ -2076,7 +2115,6 @@ BE536019209BB76B0027E25A /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA311DEE768000D0F733 /* CloudKit.framework */; }; BE53601A209BB7F80027E25A /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; BE53601B209BB8390027E25A /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; - BE53601C209BB8970027E25A /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; BE53602D209BBF630027E25A /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; BE536030209BC1FD0027E25A /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; BE536031209BC2F90027E25A /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; @@ -2085,8 +2123,10 @@ BE536034209BC3C40027E25A /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; BE55C77C2044D0C90045863D /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE55C77B2044D0C90045863D /* Client.swift */; }; BE55C77E2044D7E60045863D /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE55C77D2044D7E60045863D /* main.swift */; }; + BE57B1182509E1000045B7FD /* ca_revocation_additions.m in Sources */ = {isa = PBXBuildFile; fileRef = BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */; }; + BE57B1192509E1000045B7FD /* ca_revocation_additions.m in Sources */ = {isa = PBXBuildFile; fileRef = BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */; }; + BE57B11A2509E1000045B7FD /* ca_revocation_additions.m in Sources */ = {isa = PBXBuildFile; fileRef = BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */; }; BE61F5AF1EB0060C00556CCF /* TrustedPeers.h in Headers */ = {isa = PBXBuildFile; fileRef = BEF88C641EB0005F00357577 /* TrustedPeers.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BE6215BE1DB6E69100961E15 /* si-84-sectrust-allowlist.m in Sources */ = {isa = PBXBuildFile; fileRef = BE6215BD1DB6E69100961E15 /* si-84-sectrust-allowlist.m */; }; BE64A7FA22AF006F001209F3 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 474B5FBF1E662E21007546F8 /* SecurityFoundation.framework */; }; BE64A7FC22AF008D001209F3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D848541C6C1D9C0025BB44 /* Foundation.framework */; }; BE64A80022AF010B001209F3 /* trusted_cert_ssl.m in Sources */ = {isa = PBXBuildFile; fileRef = BE64A7FE22AF010A001209F3 /* trusted_cert_ssl.m */; }; @@ -2095,12 +2135,11 @@ BE72782B209D27C800F0DA77 /* TPKeyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BE72782A209D27C800F0DA77 /* TPKeyTests.m */; }; BE72782C209D2C1400F0DA77 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; BE759DCB1917E38D00801E02 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE451314471B000DE34E /* CoreGraphics.framework */; }; + BE7B8E132415579900E1CF4F /* SecSharedCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = BE7B8E112415579800E1CF4F /* SecSharedCredential.m */; }; + BE7B8E142415579900E1CF4F /* SecSharedCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = BE7B8E112415579800E1CF4F /* SecSharedCredential.m */; }; + BE7B8E152415580D00E1CF4F /* SecSharedCredential.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E8C1D8085FC00865A7C /* SecSharedCredential.c */; }; BE8ABDD81DC2DD9100EC2D58 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; }; BE92249E204F203C0052E828 /* TrustedPeersHelper.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = BE92249C204F203C0052E828 /* TrustedPeersHelper.xcdatamodeld */; }; - BE9B8B4A202BB4A20081EF87 /* si-88-sectrust-valid.m in Sources */ = {isa = PBXBuildFile; fileRef = BE9B8B49202BB4A10081EF87 /* si-88-sectrust-valid.m */; }; - BE9B8B4B202BB4D10081EF87 /* si-88-sectrust-valid-data in Resources */ = {isa = PBXBuildFile; fileRef = BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */; }; - BE9B8B4C202BB4E30081EF87 /* si-88-sectrust-valid-data in Resources */ = {isa = PBXBuildFile; fileRef = BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */; }; - BE9B8B4D202BB4F30081EF87 /* si-88-sectrust-valid-data in Resources */ = {isa = PBXBuildFile; fileRef = BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */; }; BE9F4F8C2072D881004A52C2 /* Cuttlefish.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F4F8B2072D881004A52C2 /* Cuttlefish.pb.swift */; }; BE9F8D10206C099800B53D16 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F8D0F206C099800B53D16 /* Container.swift */; }; BE9F8D12206C121400B53D16 /* Decrypter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F8D11206C121400B53D16 /* Decrypter.swift */; }; @@ -2110,7 +2149,7 @@ BEAA0046202B785000E51F45 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; BEB0B06E1FE9E81D007E6A83 /* TPPBPeerDynamicInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BE7089CF1FA3BA01001ACC20 /* TPPBPeerDynamicInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; BEB0B06F1FE9E850007E6A83 /* TPPBPeerPermanentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BE7089DD1FA40B93001ACC20 /* TPPBPeerPermanentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BEB0B0701FE9E8F6007E6A83 /* TPPBPeerStableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BE7089D41FA3BA04001ACC20 /* TPPBPeerStableInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BEB0B0701FE9E8F6007E6A83 /* TPPBPeerStableInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BE7089D41FA3BA04001ACC20 /* TPPBPeerStableInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; BEB0B0711FE9E936007E6A83 /* TPPBPolicySecret.h in Headers */ = {isa = PBXBuildFile; fileRef = BE7089D31FA3BA03001ACC20 /* TPPBPolicySecret.h */; settings = {ATTRIBUTES = (Private, ); }; }; BEB49F30206E98D0008DA7F4 /* TPECPublicKeyFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB49F29206E98CD008DA7F4 /* TPECPublicKeyFactory.h */; settings = {ATTRIBUTES = (Private, ); }; }; BEB49F31206E98D0008DA7F4 /* TPECPublicKeyFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = BEB49F2F206E98CE008DA7F4 /* TPECPublicKeyFactory.m */; }; @@ -2224,7 +2263,6 @@ D40B6A991E2B68A400CD6EE5 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */; }; D40B6A9A1E2B68E800CD6EE5 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; D40B6A9B1E2B690E00CD6EE5 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E9A1D8085FC00865A7C /* SecuritydXPC.c */; }; - D40B6A9D1E2B6A2700CD6EE5 /* login.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E8271D7A4F0E00AFB96E /* login.framework */; }; D40B6A9E1E2B6A6F00CD6EE5 /* libtrustd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D4ADA3191E2B41670031CEA3 /* libtrustd.a */; }; D40B7CA021605BF800AC9A75 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; settings = {ATTRIBUTES = (Required, ); }; }; D4119E78202BDF490048587B /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; @@ -2243,6 +2281,10 @@ D418CC701E690CAD00330A44 /* MobileAsset.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7273402816CAFB3C0096622A /* MobileAsset.framework */; }; D418CC711E690CBC00330A44 /* MobileAsset.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7273402816CAFB3C0096622A /* MobileAsset.framework */; }; D41D36711EB14D87007FA978 /* libDiagnosticMessagesClient.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41D36701EB14D87007FA978 /* libDiagnosticMessagesClient.tbd */; }; + D423114323725F9F000E470A /* SMIMEPolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D423114223725F9F000E470A /* SMIMEPolicyTests.m */; }; + D423114423725F9F000E470A /* SMIMEPolicyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D423114223725F9F000E470A /* SMIMEPolicyTests.m */; }; + D4231148237261F8000E470A /* SMIMEPolicyTests-data in Resources */ = {isa = PBXBuildFile; fileRef = D4231147237261F7000E470A /* SMIMEPolicyTests-data */; }; + D4231149237261F8000E470A /* SMIMEPolicyTests-data in Resources */ = {isa = PBXBuildFile; fileRef = D4231147237261F7000E470A /* SMIMEPolicyTests-data */; }; D425EC1D1DD3C3CF00DE5DEC /* SecInternalRelease.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC761D8C68CF00070CB0 /* SecInternalRelease.c */; }; D425EC231DD3FFF200DE5DEC /* SecInternalRelease.c in Sources */ = {isa = PBXBuildFile; fileRef = DC0BCC761D8C68CF00070CB0 /* SecInternalRelease.c */; }; D4267BD123440F8900B54678 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; @@ -2398,7 +2440,6 @@ D458C517214E2C690043D982 /* si-20-sectrust-policies-data in Resources */ = {isa = PBXBuildFile; fileRef = D4EC94FA1CEA482D0083E753 /* si-20-sectrust-policies-data */; }; D458C51A214E2CC80043D982 /* si-20-sectrust-policies-data in Resources */ = {isa = PBXBuildFile; fileRef = D4EC94FA1CEA482D0083E753 /* si-20-sectrust-policies-data */; }; D458C51C214E2DEB0043D982 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D458C4C5214E1A400043D982 /* Assets.xcassets */; }; - D458C51D214E2DEB0043D982 /* Base.lproj in Resources */ = {isa = PBXBuildFile; fileRef = D458C4C7214E1A400043D982 /* Base.lproj */; }; D458C51F214E2E0C0043D982 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D458C51E214E2E0C0043D982 /* Main.storyboard */; }; D458C520214E33260043D982 /* ECTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AC5766214E195300A32C01 /* ECTests.m */; }; D458C521214E33260043D982 /* ECTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AC5766214E195300A32C01 /* ECTests.m */; }; @@ -2406,7 +2447,10 @@ D458C523214E33380043D982 /* KeySizeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AC5768214E195400A32C01 /* KeySizeTests.m */; }; D458C524214E33430043D982 /* VerifyDateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AC5764214E195200A32C01 /* VerifyDateTests.m */; }; D458C525214E33440043D982 /* VerifyDateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AC5764214E195200A32C01 /* VerifyDateTests.m */; }; + D458DAC32375FEA300E5890E /* TrustSettingsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D458DAC22375FEA300E5890E /* TrustSettingsTests.m */; }; + D458DAC42375FEA300E5890E /* TrustSettingsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D458DAC22375FEA300E5890E /* TrustSettingsTests.m */; }; D45917E41DC13E6700752D25 /* SecCertificateRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E3E1D8085FC00865A7C /* SecCertificateRequest.c */; }; + D4593EFF24C131180069F577 /* SecTrustStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C1B442C0BB9CAF900461B82 /* SecTrustStore.h */; settings = {ATTRIBUTES = (Private, ); }; }; D46246971F9AE2E400D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246911F9AE2E400D63882 /* libDER.a */; }; D46246A31F9AE59E00D63882 /* oids.h in Headers */ = {isa = PBXBuildFile; fileRef = D46246A21F9AE49E00D63882 /* oids.h */; settings = {ATTRIBUTES = (Private, ); }; }; D46246A81F9AE64000D63882 /* oids.h in Headers */ = {isa = PBXBuildFile; fileRef = D46246A21F9AE49E00D63882 /* oids.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -2418,8 +2462,6 @@ D46246B91F9AE79000D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; D46246BA1F9AE7A000D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; D46246BB1F9AE7B300D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; - D46246BC1F9AE82B00D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; - D46246BD1F9AE83600D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; D46246BE1F9AE86400D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246AF1F9AE73F00D63882 /* libDER.a */; }; D46246C91F9AEA5300D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246C31F9AEA5200D63882 /* libDER.a */; }; D46246D41F9AEAE300D63882 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246CE1F9AEAE300D63882 /* libDER.a */; }; @@ -2447,10 +2489,22 @@ D4707A2D2114C1E8005BCFDA /* SecCmsContentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = D4707A2B2114B31A005BCFDA /* SecCmsContentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; D4707A2F2114C315005BCFDA /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D4707A2E2114C30A005BCFDA /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; D4707A302114C316005BCFDA /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D4707A2E2114C30A005BCFDA /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D477CB5C237B6E0E00C02355 /* PersonalizationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB5B237B6E0E00C02355 /* PersonalizationTests.m */; }; + D477CB5D237B6E0E00C02355 /* PersonalizationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB5B237B6E0E00C02355 /* PersonalizationTests.m */; }; + D477CB6A237CBA2C00C02355 /* TrustDaemonTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB69237CBA2C00C02355 /* TrustDaemonTestCase.m */; }; + D477CB6B237CBA2C00C02355 /* TrustDaemonTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB69237CBA2C00C02355 /* TrustDaemonTestCase.m */; }; D477CB78237E482800C02355 /* si-88-sectrust-valid-data in Resources */ = {isa = PBXBuildFile; fileRef = D477CB76237E453C00C02355 /* si-88-sectrust-valid-data */; }; D477CB79237E484300C02355 /* si-88-sectrust-valid-data in Resources */ = {isa = PBXBuildFile; fileRef = D477CB76237E453C00C02355 /* si-88-sectrust-valid-data */; }; D477CB7B237E4BD700C02355 /* ExceptionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB7A237E4BD700C02355 /* ExceptionTests.m */; }; D477CB7C237E4BD700C02355 /* ExceptionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB7A237E4BD700C02355 /* ExceptionTests.m */; }; + D477CB82237F692400C02355 /* RevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB81237F692400C02355 /* RevocationTests.m */; }; + D477CB83237F692400C02355 /* RevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB81237F692400C02355 /* RevocationTests.m */; }; + D477CB87237F8B2F00C02355 /* CAIssuerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB86237F8B2F00C02355 /* CAIssuerTests.m */; }; + D477CB88237F8B2F00C02355 /* CAIssuerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB86237F8B2F00C02355 /* CAIssuerTests.m */; }; + D477CB8B237F8DBC00C02355 /* AllowlistBlocklistTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB8A237F8DBB00C02355 /* AllowlistBlocklistTests.m */; }; + D477CB8C237F8DBC00C02355 /* AllowlistBlocklistTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB8A237F8DBB00C02355 /* AllowlistBlocklistTests.m */; }; + D477CB8F237F975500C02355 /* ValidTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB8E237F975500C02355 /* ValidTests.m */; }; + D477CB90237F975500C02355 /* ValidTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D477CB8E237F975500C02355 /* ValidTests.m */; }; D479F6E21F980FAB00388D28 /* Trust.strings in Resources */ = {isa = PBXBuildFile; fileRef = D479F6DF1F980F8F00388D28 /* Trust.strings */; }; D479F6E31F981FD600388D28 /* OID.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C198F1F0ACDB4BF00AAB142 /* OID.strings */; }; D479F6E41F981FD600388D28 /* Certificate.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C198F1D0ACDB4BF00AAB142 /* Certificate.strings */; }; @@ -2487,14 +2541,14 @@ D491116F209559510066A1E4 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; D49111702095595B0066A1E4 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; D4911172209559630066A1E4 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - D4911173209559630066A1E4 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4911167209558900066A1E4 /* CoreData.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; D4961BC42079424200F16DA7 /* TrustURLSessionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D4961BBD2079423300F16DA7 /* TrustURLSessionDelegate.m */; }; - D49A370323873A580065719F /* RevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370023873A570065719F /* RevocationTests.m */; }; - D49A370423873A580065719F /* RevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370023873A570065719F /* RevocationTests.m */; }; - D49A370623873BD30065719F /* TrustDaemonTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370523873BD30065719F /* TrustDaemonTestCase.m */; }; - D49A370723873BD30065719F /* TrustDaemonTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370523873BD30065719F /* TrustDaemonTestCase.m */; }; + D4981B8F24F723EA004B033B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; D49A370C23877ECC0065719F /* OCSPCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370B23877ECC0065719F /* OCSPCacheTests.m */; }; D49A370D23877ECC0065719F /* OCSPCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370B23877ECC0065719F /* OCSPCacheTests.m */; }; + D49BD0742476F67700FC7E1C /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; + D49BD0762476F74B00FC7E1C /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; + D49BD0772476F7C000FC7E1C /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; + D49BD07824770E2D00FC7E1C /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BE53602C209BBF2F0027E25A /* libMobileGestalt.tbd */; }; D4A0F8C2211E6A2F00443CA1 /* si-82-sectrust-ct-data in Resources */ = {isa = PBXBuildFile; fileRef = D4A0F8C1211E6A2F00443CA1 /* si-82-sectrust-ct-data */; }; D4A0F8C7211E6A5800443CA1 /* TrustFrameworkTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D4A0F8C4211E6A5700443CA1 /* TrustFrameworkTestCase.m */; }; D4A0F8C8211E6A5800443CA1 /* CertificateInterfaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4A0F8C6211E6A5700443CA1 /* CertificateInterfaceTests.m */; }; @@ -2585,6 +2639,7 @@ D4D92DA622788FEB0009A7CF /* NISTTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4D92DA422788FEB0009A7CF /* NISTTests.m */; }; D4D92DA8227890500009A7CF /* nist-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4D92DA72278904F0009A7CF /* nist-certs */; }; D4D92DA9227890500009A7CF /* nist-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4D92DA72278904F0009A7CF /* nist-certs */; }; + D4E6D8592404EAD40074CB26 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246911F9AE2E400D63882 /* libDER.a */; }; D4EA5CF822B225D100883439 /* LoggingServerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4EA5CF622B225C000883439 /* LoggingServerTests.m */; }; D4EA5CF922B225D100883439 /* LoggingServerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4EA5CF622B225C000883439 /* LoggingServerTests.m */; }; D4EF32172156B025000A31A5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; @@ -2601,12 +2656,39 @@ D4FD4227217D7C4F002B7EE2 /* si-87-sectrust-name-constraints in Resources */ = {isa = PBXBuildFile; fileRef = D4C6C5C71FB2AD3F007EA57E /* si-87-sectrust-name-constraints */; }; DA20716222E9367500E209E4 /* NSError+UsefulConstructors.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAE1DD62073FCDE00B4F687 /* NSError+UsefulConstructors.m */; }; DA2C402E2189302F005F1CC3 /* mach_notify.defs in Sources */ = {isa = PBXBuildFile; fileRef = DA2C402D2189302E005F1CC3 /* mach_notify.defs */; settings = {ATTRIBUTES = (Server, ); }; }; + DA2F591823A32BC100C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F591E23A986A300C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F592123A9874800C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F592523A99E8400C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F592623A99EC900C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F592723A99F2900C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA2F592823A99F6300C30285 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; DA30D6851DF8CA4100EC6B43 /* KeychainSyncAccountUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = DA30D6841DF8CA4100EC6B43 /* KeychainSyncAccountUpdater.m */; }; DA31CB212319DC8F0039F1CC /* TPStringTable.m in Sources */ = {isa = PBXBuildFile; fileRef = DA700FC82310C0E00051A7DE /* TPStringTable.m */; }; + DA3862A723A9CD2E001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA3862A923AAD1FD001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA3862AA23AAD959001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA3862AB23AAE3A8001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA3862AC23AAE3D3001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA3862AE23AAE65E001E21F1 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; DA3AD86A2319AA5D0049AFD6 /* TPStringTableTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3AD8682319AA310049AFD6 /* TPStringTableTests.m */; }; DA41FE1A2241AF4600838FB3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DA41FE192241AF3E00838FB3 /* main.m */; }; DA41FE1B2241AF8200838FB3 /* IDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD744683195A00BB00FB01C0 /* IDS.framework */; }; DA45865C2245AEDB0073F993 /* OTPairingService.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4586592245AEDA0073F993 /* OTPairingService.m */; }; + DA53FC3923A9BA68002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC3C23A9BDD5002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC3D23A9BF28002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC3E23A9C180002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC3F23A9C26F002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4023A9C351002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4123A9C3CE002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4223A9C442002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4423A9C779002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4523A9C801002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4623A9CB13002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4723A9CBAA002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4823A9CC16002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; + DA53FC4923A9CC8D002D5EA9 /* SoftLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2F591523A32BB400C30285 /* SoftLinking.framework */; }; DA5B871C2065A8440093F083 /* SecAutorelease.h in Headers */ = {isa = PBXBuildFile; fileRef = DA5B871A2065A8410093F083 /* SecAutorelease.h */; }; DA5B871D2065A8440093F083 /* SecAutorelease.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5B871B2065A8430093F083 /* SecAutorelease.m */; }; DA6AA1651FE88AFB004565B0 /* CKKSControlServer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6AA15E1FE88AF9004565B0 /* CKKSControlServer.m */; }; @@ -2667,7 +2749,6 @@ DC00ABF11D821FC400513D74 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; DC00ABF21D821FC800513D74 /* libSOSRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52EC681D80D0C400B0A59C /* libSOSRegressions.a */; }; DC00ABF31D821FCD00513D74 /* libSecureObjectSyncServer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E8C61D80C25800B0A59C /* libSecureObjectSyncServer.a */; }; - DC00C91D20B3B79600628BEB /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC78EA91D8088E200865A7C /* libsecurity.a */; }; DC00C92020B3B7CC00628BEB /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D46246911F9AE2E400D63882 /* libDER.a */; }; DC00C92320B3B80500628BEB /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EB49B2DC202DF251003F34A0 /* libbsm.tbd */; }; DC00C92420B3B82600628BEB /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; @@ -2682,7 +2763,8 @@ DC05037A21409A4100A8EDB7 /* OCMockUmbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = DC05037821409A4100A8EDB7 /* OCMockUmbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; DC05038121409A6100A8EDB7 /* OCMock.framework in Embed OCMock */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; DC05038221409B3400A8EDB7 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC3502E81E02172C00BC0587 /* OCMock.framework */; }; - DC066DF02102563300694EAF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; + DC061A71246213660026ADB3 /* CKKSLocalResetOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC061A70246211DE0026ADB3 /* CKKSLocalResetOperation.m */; }; + DC061A722462136F0026ADB3 /* CKKSOperationDependencies.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3412E6245780BA008ABD0A /* CKKSOperationDependencies.m */; }; DC07090422936DB2002711B9 /* OctagonTests+ErrorHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC07090222936BCC002711B9 /* OctagonTests+ErrorHandling.swift */; }; DC08D1C41E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC08D1C31E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m */; }; DC08D1CC1E64FCC5006237DA /* CKKSSOSTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DC08D1CB1E64FCC5006237DA /* CKKSSOSTests.m */; }; @@ -3284,7 +3366,6 @@ DC1787261D778FDE00B50D50 /* SecManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787241D778FDE00B50D50 /* SecManifest.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787271D778FDE00B50D50 /* SecureDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787251D778FDE00B50D50 /* SecureDownloadInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787351D77903700B50D50 /* SecAccessPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787281D77903700B50D50 /* SecAccessPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - DC1787361D77903700B50D50 /* SecCertificateBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787291D77903700B50D50 /* SecCertificateBundle.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787371D77903700B50D50 /* SecFDERecoveryAsymmetricCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17872A1D77903700B50D50 /* SecFDERecoveryAsymmetricCrypto.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787381D77903700B50D50 /* SecIdentitySearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17872B1D77903700B50D50 /* SecIdentitySearchPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787391D77903700B50D50 /* SecKeychainItemExtendedAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17872C1D77903700B50D50 /* SecKeychainItemExtendedAttributes.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -3315,7 +3396,6 @@ DC1787701D77911D00B50D50 /* osKeyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787671D77911D00B50D50 /* osKeyTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787711D77911D00B50D50 /* secasn1t.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787681D77911D00B50D50 /* secasn1t.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787721D77911D00B50D50 /* X509Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787691D77911D00B50D50 /* X509Templates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - DC1787741D77915500B50D50 /* SecBreadcrumb.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1787731D77915500B50D50 /* SecBreadcrumb.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787751D77916000B50D50 /* SecAccessControlPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 443381DA18A3D81400215606 /* SecAccessControlPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787761D77916600B50D50 /* SecCFAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = D47F514B1C3B812500A7CEFE /* SecCFAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC1787771D77916A00B50D50 /* SecDH.h in Headers */ = {isa = PBXBuildFile; fileRef = 7940D4110C3ACF9000FDB5D8 /* SecDH.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -3345,7 +3425,6 @@ DC1789281D779A0F00B50D50 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF8C1A01472C000958DC /* libaks_acl.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 */; }; - DC1789A21D779DF400B50D50 /* SecBreadcrumb.c in Sources */ = {isa = PBXBuildFile; fileRef = DC1789A01D779DEE00B50D50 /* SecBreadcrumb.c */; }; DC1789A51D779E3B00B50D50 /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC1789A41D779E3B00B50D50 /* dummy.cpp */; }; DC1789E91D77A0F300B50D50 /* CloudKeychain.strings in Resources */ = {isa = PBXBuildFile; fileRef = 53C0E1F1177FAC2C00F8A018 /* CloudKeychain.strings */; }; DC178A1F1D77A1E700B50D50 /* cssm.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = DC178A0E1D77A1E700B50D50 /* cssm.mdsinfo */; }; @@ -3368,7 +3447,6 @@ DC178A421D77A1F600B50D50 /* FDEPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = DC178A311D77A1F500B50D50 /* FDEPrefs.plist */; }; DC178A431D77A1F600B50D50 /* SecDebugErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC178A321D77A1F500B50D50 /* SecDebugErrorMessages.strings */; }; DC178A441D77A1F600B50D50 /* SecErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC178A331D77A1F500B50D50 /* SecErrorMessages.strings */; }; - DC178A451D77A1F600B50D50 /* framework.sb in Resources */ = {isa = PBXBuildFile; fileRef = DC178A351D77A1F500B50D50 /* framework.sb */; }; DC178A471D77A1F600B50D50 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC178A381D77A1F500B50D50 /* InfoPlist.strings */; }; DC178A481D77A1F600B50D50 /* TimeStampingPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = DC178A3A1D77A1F500B50D50 /* TimeStampingPrefs.plist */; }; DC178A491D77A1F600B50D50 /* authorization.dfr.prompts.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC178A3B1D77A1F500B50D50 /* authorization.dfr.prompts.strings */; }; @@ -3391,12 +3469,6 @@ DC222C361E02419B00B09171 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; DC222C8A1E089BAE00B09171 /* CKKSSQLTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DC222C891E089BAE00B09171 /* CKKSSQLTests.m */; }; DC222CA81E08A7D900B09171 /* CloudKitMockXCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC222CA71E08A7D900B09171 /* CloudKitMockXCTest.m */; }; - DC2353291ECA658300D7C1BE /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; - DC23532F1ECA658400D7C1BE /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; - DC2353301ECA658900D7C1BE /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; - DC2353311ECA658B00D7C1BE /* server_security_helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4269061E82FBDF002B7110 /* server_security_helpers.m */; }; - DC2353321ECA659000D7C1BE /* server_xpc.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB2214A1E8B0861001598BC /* server_xpc.m */; }; - DC2353331ECA659000D7C1BE /* server_xpc.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB2214A1E8B0861001598BC /* server_xpc.m */; }; DC25B3AC233C2EBC00CB1409 /* CloudKitCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = DC94BCC91F10448600E07CEB /* CloudKitCategories.m */; }; DC26666A21CAC32700F19960 /* OTControlCLI.m in Sources */ = {isa = PBXBuildFile; fileRef = DC26666921CAC32700F19960 /* OTControlCLI.m */; }; DC26666C21CAC97000F19960 /* OTControlCLI.m in Sources */ = {isa = PBXBuildFile; fileRef = DC26666921CAC32700F19960 /* OTControlCLI.m */; }; @@ -3424,8 +3496,6 @@ DC2C5F511F0D935300FEBDA7 /* CKKSControlProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF7A89F1F04502300CABE89 /* CKKSControlProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; DC2C5F5D1F0EB97E00FEBDA7 /* CKKSNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = DC2C5F5A1F0EB97E00FEBDA7 /* CKKSNotifier.h */; }; DC2C5F601F0EB97E00FEBDA7 /* CKKSNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = DC2C5F5B1F0EB97E00FEBDA7 /* CKKSNotifier.m */; }; - DC2D438F1F0EEC2A0005D382 /* MockCloudKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3502E61E0214C800BC0587 /* MockCloudKit.m */; }; - DC2D43951F0EEC300005D382 /* MockCloudKit.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3502E61E0214C800BC0587 /* MockCloudKit.m */; }; DC2FA71120E5770400DB7518 /* OTClique.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C2F336A20DD643B0031A92D /* OTClique.m */; }; DC2FA72520E57AB500DB7518 /* SOSPeerInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D631D8085F200865A7C /* SOSPeerInfo.m */; }; DC2FA72A20E57BFD00DB7518 /* SOSAccountTrust.m in Sources */ = {isa = PBXBuildFile; fileRef = CD31F8601DCD4C1400414B46 /* SOSAccountTrust.m */; }; @@ -3540,7 +3610,6 @@ DC3D748C1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3D748A1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.h */; }; DC3D748E1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3D748B1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.m */; }; DC3E18C82125015300073D80 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; - DC3E18EB2125FB8700073D80 /* libaks_mock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC36895E21235F42003A3735 /* libaks_mock.a */; }; DC4268F61E82036F002B7110 /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; DC4268FC1E820370002B7110 /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; DC4268FE1E820371002B7110 /* server_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6ACC401E81DF9400125DC5 /* server_endpoint.m */; }; @@ -3565,9 +3634,6 @@ DC4A76A3221267D4006F2D8F /* EscrowRequestServerHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DC4A76A2221267D4006F2D8F /* EscrowRequestServerHelpers.m */; }; DC4A76A5221268A6006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; DC4A76A62212691F006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; - DC4A76A72212694F006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; - DC4A76A822126959006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; - DC4A76AA22126993006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; DC4A76AB221269B8006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC4A76A92212698B006F2D8F /* CloudServices.framework */; }; DC4A76AC221269E4006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; DC4A76AD22126A17006F2D8F /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; @@ -3775,21 +3841,17 @@ DC52EDFA1D80D66600B0A59C /* SOSRegressionUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D0A1D8085F200865A7C /* SOSRegressionUtilities.m */; }; DC52EE441D80D71900B0A59C /* si-21-sectrust-asr.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DBD1D8085FC00865A7C /* si-21-sectrust-asr.c */; }; DC52EE451D80D71900B0A59C /* si-22-sectrust-iap.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DBE1D8085FC00865A7C /* si-22-sectrust-iap.c */; }; - DC52EE471D80D71900B0A59C /* si-23-sectrust-ocsp.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC01D8085FC00865A7C /* si-23-sectrust-ocsp.c */; }; DC52EE481D80D71900B0A59C /* si-24-sectrust-digicert-malaysia.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC11D8085FC00865A7C /* si-24-sectrust-digicert-malaysia.c */; }; DC52EE491D80D71900B0A59C /* si-24-sectrust-diginotar.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC21D8085FC00865A7C /* si-24-sectrust-diginotar.c */; }; DC52EE4A1D80D71900B0A59C /* si-24-sectrust-itms.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC31D8085FC00865A7C /* si-24-sectrust-itms.c */; }; DC52EE4C1D80D71900B0A59C /* si-24-sectrust-passbook.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC51D8085FC00865A7C /* si-24-sectrust-passbook.c */; }; DC52EE4D1D80D71900B0A59C /* si-26-sectrust-copyproperties.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC61D8085FC00865A7C /* si-26-sectrust-copyproperties.c */; }; - DC52EE4F1D80D71900B0A59C /* si-28-sectrustsettings.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DC81D8085FC00865A7C /* si-28-sectrustsettings.m */; }; DC52EE531D80D73800B0A59C /* si-44-seckey-gen.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DD31D8085FC00865A7C /* si-44-seckey-gen.m */; }; DC52EE541D80D73800B0A59C /* si-44-seckey-rsa.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DD41D8085FC00865A7C /* si-44-seckey-rsa.m */; }; DC52EE551D80D73800B0A59C /* si-44-seckey-ec.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DD51D8085FC00865A7C /* si-44-seckey-ec.m */; }; DC52EE561D80D73800B0A59C /* si-44-seckey-ies.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DD61D8085FC00865A7C /* si-44-seckey-ies.m */; }; - DC52EE571D80D73800B0A59C /* si-67-sectrust-blocklist.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DF71D8085FC00865A7C /* si-67-sectrust-blocklist.c */; }; DC52EE581D80D73800B0A59C /* si-70-sectrust-unified.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DFA1D8085FC00865A7C /* si-70-sectrust-unified.c */; }; DC52EE5A1D80D73800B0A59C /* si-83-seccertificate-sighashalg.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E061D8085FC00865A7C /* si-83-seccertificate-sighashalg.c */; }; - DC52EE601D80D79900B0A59C /* si-74-OTAPKISigner.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DFE1D8085FC00865A7C /* si-74-OTAPKISigner.c */; }; DC52EE611D80D79E00B0A59C /* si-71-mobile-store-policy.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78DFB1D8085FC00865A7C /* si-71-mobile-store-policy.c */; }; DC52EE6F1D80D83F00B0A59C /* SecPasswordGenerate.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E7A1D8085FC00865A7C /* SecPasswordGenerate.c */; }; DC52EE701D80D84700B0A59C /* SecItemConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E5C1D8085FC00865A7C /* SecItemConstants.c */; }; @@ -3907,7 +3969,6 @@ DC5AC0C21D83538D00CF422C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789241D7799CD00B50D50 /* CoreFoundation.framework */; }; DC5AC0C41D8353BB00CF422C /* System.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5AC0C31D8353B900CF422C /* System.framework */; }; DC5AC0C51D8353C200CF422C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; - DC5AC0C71D8353C800CF422C /* PCSC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5AC0C61D8353C800CF422C /* PCSC.framework */; }; DC5AC0C91D8353D100CF422C /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789181D77998C00B50D50 /* libbsm.dylib */; }; DC5AC0CE1D83542B00CF422C /* libsecurity_tokend_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC5AC0CD1D83542700CF422C /* libsecurity_tokend_client.a */; }; DC5AC0D31D83544D00CF422C /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DC17891E1D77999D00B50D50 /* libsqlite3.dylib */; }; @@ -3930,7 +3991,6 @@ DC5AC0E61D8354CA00CF422C /* tokendatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABF9B1D83511A00CF422C /* tokendatabase.cpp */; }; DC5AC0E71D8354CA00CF422C /* tokenkey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABF9D1D83511A00CF422C /* tokenkey.cpp */; }; DC5AC0E81D8354CA00CF422C /* tokenaccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABF9F1D83511A00CF422C /* tokenaccess.cpp */; }; - DC5AC0E91D8354CA00CF422C /* pcscmonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABFA31D83511A00CF422C /* pcscmonitor.cpp */; }; DC5AC0EA1D8354CA00CF422C /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABFA51D83511A00CF422C /* reader.cpp */; }; DC5AC0EB1D8354CA00CF422C /* token.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABFA71D83511A00CF422C /* token.cpp */; }; DC5AC0EC1D8354CA00CF422C /* tokend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC5ABFA91D83511A00CF422C /* tokend.cpp */; }; @@ -4011,13 +4071,10 @@ DC5F35AE1EE0F27C00900966 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; DC5F35AF1EE0F27C00900966 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; DC5F35B01EE0F27C00900966 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; - DC5F35B11EE0F28B00900966 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; - DC5F35B21EE0F28C00900966 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; DC5F65AE2225C22C0051E9FA /* CKKSProvideKeySetOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC5F65AC2225C22C0051E9FA /* CKKSProvideKeySetOperation.h */; }; DC5F65AF2225C22C0051E9FA /* CKKSProvideKeySetOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC5F65AD2225C22C0051E9FA /* CKKSProvideKeySetOperation.m */; }; DC5F65B12225CD720051E9FA /* CKKSProvideKeySetOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC5F65AD2225C22C0051E9FA /* CKKSProvideKeySetOperation.m */; }; DC60132E2147220600863C1A /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; - DC6013312147220F00863C1A /* libaks_mock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC36895E21235F42003A3735 /* libaks_mock.a */; }; DC6013392147227800863C1A /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; DC6063B221B09AB200069B82 /* KCJoiningRequestCircleSession.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6063B121B09AB200069B82 /* KCJoiningRequestCircleSession.m */; }; DC610A181D78F129002223DE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C0BDB31175685B000BC1A7E /* main.m */; }; @@ -4106,6 +4163,7 @@ DC6D2C931DD2836500BE372D /* CKKSOutgoingQueueEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = DC9B7AE61DCBF651004E9385 /* CKKSOutgoingQueueEntry.h */; }; DC6DE899213076C000C6B56D /* OTSOSUpgradeOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC6DE897213076C000C6B56D /* OTSOSUpgradeOperation.h */; }; DC6DE89C213076C000C6B56D /* OTSOSUpgradeOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6DE898213076C000C6B56D /* OTSOSUpgradeOperation.m */; }; + DC6E02162405DE3900C61335 /* OTModifyUserControllableViewStatusOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6E02132405DDC400C61335 /* OTModifyUserControllableViewStatusOperation.m */; }; DC71D85C1D94CCD40065FB93 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; DC71D8F51D959F150065FB93 /* com.apple.securityd.plist in Copy Logging Files */ = {isa = PBXBuildFile; fileRef = DCE4E80D1D7A4E3A00AFB96E /* com.apple.securityd.plist */; }; DC725030229600C000493D88 /* OctagonTests+Reset.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC72502D229600A800493D88 /* OctagonTests+Reset.swift */; }; @@ -4168,8 +4226,14 @@ DC8506B52097F1FD00C712EC /* whoami.m in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA911D80CC2A00B0A59C /* whoami.m */; }; DC8506B62097F39100C712EC /* libSOSCommands.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52EC341D80CFB200B0A59C /* libSOSCommands.a */; }; DC85687E2284E7860088D3EF /* OctagonTestMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC85687C2284E7850088D3EF /* OctagonTestMocks.swift */; }; + DC86122C2408AC190092E93B /* CKKSTests+ItemSyncChoice.m in Sources */ = {isa = PBXBuildFile; fileRef = DC86122B2408AC190092E93B /* CKKSTests+ItemSyncChoice.m */; }; DC8757F4218D2003000E65F1 /* OTRemovePeersOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC8757F2218D2003000E65F1 /* OTRemovePeersOperation.h */; }; DC8757F5218D2003000E65F1 /* OTRemovePeersOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC8757F3218D2003000E65F1 /* OTRemovePeersOperation.m */; }; + DC880F68243D4CC00059806D /* CKKSLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = DC880F67243D4CC00059806D /* CKKSLogging.m */; }; + DC880F69243D4CE50059806D /* CKKSLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = DC880F67243D4CC00059806D /* CKKSLogging.m */; }; + DC880F6A243D4D640059806D /* CKKSLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = DC880F67243D4CC00059806D /* CKKSLogging.m */; }; + DC880F6B243D4D730059806D /* CKKSLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = DC880F67243D4CC00059806D /* CKKSLogging.m */; }; + DC880F6C243D4DC00059806D /* CKKSLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = DC880F67243D4CC00059806D /* CKKSLogging.m */; }; DC8834521D8A21AA00CE0ACA /* SecAsn1Coder.c in Sources */ = {isa = PBXBuildFile; fileRef = DC88340A1D8A21AA00CE0ACA /* SecAsn1Coder.c */; }; DC8834541D8A21AA00CE0ACA /* SecAsn1Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = DC88340C1D8A21AA00CE0ACA /* SecAsn1Templates.c */; }; DC8834571D8A21AA00CE0ACA /* certExtensionTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = DC88340F1D8A21AA00CE0ACA /* certExtensionTemplates.c */; }; @@ -4210,12 +4274,9 @@ DC926F081F33F7D30012A315 /* SecCodeHost.h in Headers */ = {isa = PBXBuildFile; fileRef = DCD067981D8CDF7E007602F1 /* SecCodeHost.h */; settings = {ATTRIBUTES = (Public, ); }; }; DC926F091F33FA8D0012A315 /* CKKSControlProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF7A8A21F0450EB00CABE89 /* CKKSControlProtocol.m */; }; DC926F0A1F33FA8E0012A315 /* CKKSControlProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF7A8A21F0450EB00CABE89 /* CKKSControlProtocol.m */; }; - DC93C4C5214713C5008F8362 /* libaks_mock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC36895E21235F42003A3735 /* libaks_mock.a */; }; - DC93C4CA214713E5008F8362 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; - DC93C4CB214713ED008F8362 /* libaks_mock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC36895E21235F42003A3735 /* libaks_mock.a */; }; - DC93C4D021471FD8008F8362 /* libsecurityd_ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC52E7C21D80BC8000B0A59C /* libsecurityd_ios.a */; }; DC93F02922387A010072720A /* OTSOSUpdatePreapprovalsOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DC93F02722387A010072720A /* OTSOSUpdatePreapprovalsOperation.h */; }; DC93F02A22387A010072720A /* OTSOSUpdatePreapprovalsOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC93F02822387A010072720A /* OTSOSUpdatePreapprovalsOperation.m */; }; + DC947E8524638320005B8669 /* CKKSCheckKeyHierarchyOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DC947E832463831F005B8669 /* CKKSCheckKeyHierarchyOperation.m */; }; DC94BCCA1F10448600E07CEB /* CloudKitCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = DC94BCC81F10448600E07CEB /* CloudKitCategories.h */; }; DC94BCCC1F10448600E07CEB /* CloudKitCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = DC94BCC91F10448600E07CEB /* CloudKitCategories.m */; }; DC96053F1ECA2D6400AF9BDA /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = 107226D00D91DB32003CF14F /* SecTask.c */; }; @@ -4224,6 +4285,9 @@ DC963E821D95EC1C008A153E /* libsecurity_codesigning.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = DCD068CB1D8CDFFE007602F1 /* libsecurity_codesigning.plist */; }; DC963E841D95EC31008A153E /* libsecurity_codesigning.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = DCD068CC1D8CDFFE007602F1 /* libsecurity_codesigning.txt */; }; DC963EC61D95F646008A153E /* der_plist.h in Headers */ = {isa = PBXBuildFile; fileRef = 524492931AFD6D480043695A /* der_plist.h */; }; + DC9978B82404AA3200A5EE2F /* Container_UserSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */; }; + DC9978B92404AA3200A5EE2F /* Container_UserSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */; }; + DC9978BB2404B26900A5EE2F /* Container_UserSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */; }; DC99B86B20EACA470065B73B /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; DC99B86C20EACA470065B73B /* FakeCuttlefish.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA8557F20B5DC7D00D5AD11 /* FakeCuttlefish.swift */; }; DC99B86D20EACA470065B73B /* SecdWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 476541641F339F6300413F65 /* SecdWatchdog.m */; }; @@ -4274,12 +4338,14 @@ DCA4D1FF1E552DD50056214F /* CKKSCurrentKeyPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA4D1F41E5520550056214F /* CKKSCurrentKeyPointer.m */; }; DCA4D2151E5684220056214F /* CKKSReencryptOutgoingItemsOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCA4D2131E5684220056214F /* CKKSReencryptOutgoingItemsOperation.h */; }; DCA4D2171E5684220056214F /* CKKSReencryptOutgoingItemsOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA4D2141E5684220056214F /* CKKSReencryptOutgoingItemsOperation.m */; }; + DCA7F7EF23A44AA200927989 /* OctagonPolicyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA7F7EE23A44AA200927989 /* OctagonPolicyTests.swift */; }; DCA85B931E8D97E400BA7241 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; DCA85B941E8D97E400BA7241 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; DCA85B971E8D980200BA7241 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; DCA85B981E8D980A00BA7241 /* client_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC844AEC1E81F315007AAB71 /* client_endpoint.m */; }; DCA85B991E8D980B00BA7241 /* client_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC844AEC1E81F315007AAB71 /* client_endpoint.m */; }; DCA85B9B1E8D981200BA7241 /* client_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC844AEC1E81F315007AAB71 /* client_endpoint.m */; }; + DCA992AD2400BB99007959AF /* TPPBAncientEpoch.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC373A820D810DA00DBDF5B /* TPPBAncientEpoch.proto */; }; DCA9BC02221B721E00B4EB26 /* CKKSCloudKitClassDependencies.h in Headers */ = {isa = PBXBuildFile; fileRef = DCA9BC00221B721D00B4EB26 /* CKKSCloudKitClassDependencies.h */; }; DCA9BC03221B721E00B4EB26 /* CKKSCloudKitClassDependencies.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA9BC01221B721E00B4EB26 /* CKKSCloudKitClassDependencies.m */; }; DCA9BC07221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA9BC06221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.m */; }; @@ -4294,6 +4360,7 @@ DCAA209A23AAF8F600DCB594 /* Container_RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.swift */; }; DCAA209B23AAF8FD00DCB594 /* Container_RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.swift */; }; DCAA209C23AAF93700DCB594 /* Container_RecoveryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.swift */; }; + DCAAF3362493F9C600D4EB55 /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EAFA4CD1EF16059002DC188 /* LocalAuthentication.framework */; }; DCAB14271E40039600C81511 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; DCAB17CE21FFF75B00E1DFCF /* MockSynchronousEscrowServer.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAB17CC21FFF6C400E1DFCF /* MockSynchronousEscrowServer.m */; }; DCAB17D12200D26900E1DFCF /* SecEscrowPendingRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = DCAB17CF2200D26700E1DFCF /* SecEscrowPendingRecord.h */; }; @@ -4492,7 +4559,6 @@ DCB342FB1D8A32A20054D16E /* SecBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342441D8A32A20054D16E /* SecBase.cpp */; }; DCB342FC1D8A32A20054D16E /* SecBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB342451D8A32A20054D16E /* SecBridge.h */; }; DCB342FD1D8A32A20054D16E /* SecCertificate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342461D8A32A20054D16E /* SecCertificate.cpp */; }; - DCB342FE1D8A32A20054D16E /* SecCertificateBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342471D8A32A20054D16E /* SecCertificateBundle.cpp */; }; DCB343001D8A32A20054D16E /* SecIdentity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342491D8A32A20054D16E /* SecIdentity.cpp */; }; DCB343011D8A32A20054D16E /* SecIdentitySearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB3424A1D8A32A20054D16E /* SecIdentitySearch.cpp */; }; DCB343021D8A32A20054D16E /* SecItemConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = DCB3424B1D8A32A20054D16E /* SecItemConstants.c */; }; @@ -4543,7 +4609,6 @@ DCB3435A1D8A32A20054D16E /* PolicyCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB342A51D8A32A20054D16E /* PolicyCursor.h */; }; DCB3435B1D8A32A20054D16E /* SecCFTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342A61D8A32A20054D16E /* SecCFTypes.cpp */; }; DCB3435C1D8A32A20054D16E /* SecCFTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB342A71D8A32A20054D16E /* SecCFTypes.h */; }; - DCB3435D1D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342A81D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp */; }; DCB3435E1D8A32A20054D16E /* StorageManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342AA1D8A32A20054D16E /* StorageManager.cpp */; }; DCB3435F1D8A32A20054D16E /* Trust.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCB342AB1D8A32A20054D16E /* Trust.cpp */; }; DCB343601D8A32A20054D16E /* Trust.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB342AC1D8A32A20054D16E /* Trust.h */; }; @@ -4670,13 +4735,9 @@ DCB4584C2240396E00115F8C /* NSError+UsefulConstructors.m in Sources */ = {isa = PBXBuildFile; fileRef = DCAE1DD62073FCDE00B4F687 /* NSError+UsefulConstructors.m */; }; DCB468DF20EC25FF00BA7E5B /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE55C77B2044D0C90045863D /* Client.swift */; }; DCB468E520EC262C00BA7E5B /* ContainerMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9F8D18206C4AD300B53D16 /* ContainerMap.swift */; }; - DCB515DE1ED3CF86001F1152 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; - DCB515DF1ED3CF95001F1152 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; - DCB515E01ED3D111001F1152 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; - DCB515E11ED3D11A001F1152 /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 7908507F0CA87CF00083CC4D /* client.c */; }; - DCB515E21ED3D134001F1152 /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = 107226D00D91DB32003CF14F /* SecTask.c */; }; - DCB515E31ED3D135001F1152 /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = 107226D00D91DB32003CF14F /* SecTask.c */; }; - DCB515E41ED3D15A001F1152 /* client_endpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = DC844AEC1E81F315007AAB71 /* client_endpoint.m */; }; + DCB55175247F48290009A859 /* CKKSDeleteCKZoneOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB55173247F48290009A859 /* CKKSDeleteCKZoneOperation.h */; }; + DCB55176247F48290009A859 /* CKKSDeleteCKZoneOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB55174247F48290009A859 /* CKKSDeleteCKZoneOperation.m */; }; + DCB55177247F483D0009A859 /* CKKSCreateCKZoneOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB5516B247F3DB50009A859 /* CKKSCreateCKZoneOperation.m */; }; DCB5D93B1E4A9A3400BE22AB /* CKKSSynchronizeOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB5D9391E4A9A3400BE22AB /* CKKSSynchronizeOperation.h */; }; DCB5D93D1E4A9A3400BE22AB /* CKKSSynchronizeOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB5D93A1E4A9A3400BE22AB /* CKKSSynchronizeOperation.m */; }; DCB7D8C31D8E181B00867385 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD06AB01D8E0D53007602F1 /* libsecurity_utilities.a */; }; @@ -4688,6 +4749,7 @@ DCB9475621274A1900ED9272 /* TPHObjcTranslation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB9475421274A1900ED9272 /* TPHObjcTranslation.m */; }; DCB9475821274F9D00ED9272 /* TPHObjcTranslation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB9475421274A1900ED9272 /* TPHObjcTranslation.m */; }; DCB9475A2127534C00ED9272 /* OctagonTests+SOSUpgrade.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB947592127534C00ED9272 /* OctagonTests+SOSUpgrade.swift */; }; + DCBA6F2924105399009A5187 /* CKKSTests+ForwardCompatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBA6F2824105399009A5187 /* CKKSTests+ForwardCompatibility.m */; }; DCBB8AC41D80DD95007ED154 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; DCBDB3B71E57C82300B61300 /* CKKSKeychainView.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBDB3B11E57C67500B61300 /* CKKSKeychainView.m */; }; DCBDB3BB1E57CA7A00B61300 /* CKKSViewManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DCBDB3B91E57CA7A00B61300 /* CKKSViewManager.h */; }; @@ -4702,7 +4764,6 @@ DCBF4ABA21FFC82100539F0A /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; DCBF4ABB21FFC82100539F0A /* SecFramework.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E4F1D8085FC00865A7C /* SecFramework.c */; }; DCBF4ABE21FFC82100539F0A /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; - DCBF4AC121FFC82100539F0A /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9FB40120D8729A00864612 /* CoreCDP.framework */; }; DCBF4AC221FFC82100539F0A /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; DCBF4AC321FFC82100539F0A /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF4C19C171E0EA600877419 /* Accounts.framework */; }; DCBF4AC421FFC82100539F0A /* AppleAccount.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C84DA541720698900AEE225 /* AppleAccount.framework */; }; @@ -4728,6 +4789,8 @@ DCBF4AE521FFC9B300539F0A /* SecEscrowRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBF4AE321FFC9A800539F0A /* SecEscrowRequestTests.m */; }; DCBFF832222611A200C5C044 /* OTFetchCKKSKeysOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCBFF830222611A200C5C044 /* OTFetchCKKSKeysOperation.h */; }; DCBFF833222611A200C5C044 /* OTFetchCKKSKeysOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBFF831222611A200C5C044 /* OTFetchCKKSKeysOperation.m */; }; + DCC03FA423FF521100A4DA3F /* TPSyncingPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC03FA223FF521100A4DA3F /* TPSyncingPolicy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DCC03FA523FF521100A4DA3F /* TPSyncingPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC03FA323FF521100A4DA3F /* TPSyncingPolicy.m */; }; DCC093791D80B02100F984E4 /* SecOnOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC78E671D8085FC00865A7C /* SecOnOSX.h */; }; DCC0937A1D80B07200F984E4 /* SecOTRSessionPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFFC15AFB73800B9D400 /* SecOTRSessionPriv.h */; }; DCC0937B1D80B07B00F984E4 /* SecOTRSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFFB15AFB73800B9D400 /* SecOTRSession.h */; }; @@ -4738,6 +4801,8 @@ DCC093801D80B0B700F984E4 /* SecCFAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = D47F514B1C3B812500A7CEFE /* SecCFAllocator.h */; }; DCC19518214C53FD00C9E0B6 /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; }; DCC1951C214C668A00C9E0B6 /* AppleAccount.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C84DA541720698900AEE225 /* AppleAccount.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + DCC40B112383786D00402CB9 /* CKKSStates.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC40B0F2383786D00402CB9 /* CKKSStates.h */; }; + DCC40B122383786D00402CB9 /* CKKSStates.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC40B102383786D00402CB9 /* CKKSStates.m */; }; DCC51C99209B7C1500A40387 /* print_cert.c in Sources */ = {isa = PBXBuildFile; fileRef = DC52EA951D80CC2A00B0A59C /* print_cert.c */; }; DCC54181225C05180095D926 /* OTUploadNewCKKSTLKsOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC5417F225C05170095D926 /* OTUploadNewCKKSTLKsOperation.h */; }; DCC54182225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC54180225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m */; }; @@ -4808,7 +4873,6 @@ DCC78EE51D808B2100865A7C /* SecBase64.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78E351D8085FC00865A7C /* SecBase64.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 */; }; DCCBFA391DBAE445001DD54D /* SecInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6416F00BB357D5001C83FD /* SecInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; DCCD33C91E3FE95900AA4AD1 /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = DCC78CB01D8085D800865A7C /* spi.c */; }; @@ -5299,6 +5363,8 @@ DCD8A20A1E09FB5900E4FA0A /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; settings = {ATTRIBUTES = (Weak, ); }; }; DCD8A20B1E09FB5A00E4FA0A /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; DCD8A20C1E09FB6600E4FA0A /* libSecureObjectSyncFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */; }; + DCDACB5924A3F38E0054080C /* com.apple.security.ckks.plist in Copy Logging Files */ = {isa = PBXBuildFile; fileRef = DCDACB5724A3F1AA0054080C /* com.apple.security.ckks.plist */; }; + DCDACB5A24A3F39A0054080C /* com.apple.security.ckks.plist in Copy Logging Files */ = {isa = PBXBuildFile; fileRef = DCDACB5724A3F1AA0054080C /* com.apple.security.ckks.plist */; }; DCDB296C1FD8820400B5D242 /* SFAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 4723C9DB1F1540CE0082882F /* SFAnalytics.m */; }; DCDB296E1FD8821400B5D242 /* SFAnalyticsActivityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CBF65381FA147E500A68667 /* SFAnalyticsActivityTracker.m */; }; DCDB29701FD8821800B5D242 /* SFAnalyticsMultiSampler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */; }; @@ -5319,7 +5385,7 @@ DCDCCB391DF25D18006E840E /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA311DEE768000D0F733 /* CloudKit.framework */; }; DCDCCB3A1DF25D1D006E840E /* ApplePushService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA231DEE36FE00D0F733 /* ApplePushService.framework */; }; DCDCCB3B1DF25D69006E840E /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA311DEE768000D0F733 /* CloudKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - DCDCCB3C1DF25D74006E840E /* ApplePushService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA231DEE36FE00D0F733 /* ApplePushService.framework */; }; + DCDCCB3C1DF25D74006E840E /* ApplePushService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA231DEE36FE00D0F733 /* ApplePushService.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; DCDCCB3E1DF25DA0006E840E /* ApplePushService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC9EBA231DEE36FE00D0F733 /* ApplePushService.framework */; }; DCDCCB8F1DF7B8D4006E840E /* CKKSItem.h in Headers */ = {isa = PBXBuildFile; fileRef = DCDCCB8D1DF7B8D4006E840E /* CKKSItem.h */; }; DCDCCB901DF7B8D4006E840E /* CKKSItem.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDCCB8E1DF7B8D4006E840E /* CKKSItem.m */; }; @@ -5334,7 +5400,6 @@ DCE0774321ADD635002662FD /* TPPBPeerDynamicInfo.proto in Sources */ = {isa = PBXBuildFile; fileRef = BE7089CB1FA3B19A001ACC20 /* TPPBPeerDynamicInfo.proto */; }; DCE0774621ADD638002662FD /* TPPBDisposition.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC3739B20CF2AA200DBDF5B /* TPPBDisposition.proto */; }; DCE0774721ADD63A002662FD /* TPPBDispositionEntry.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC373C120D8224A00DBDF5B /* TPPBDispositionEntry.proto */; }; - DCE0774821ADD63C002662FD /* TPPBAncientEpoch.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC373A820D810DA00DBDF5B /* TPPBAncientEpoch.proto */; }; DCE0774921ADD63E002662FD /* TPPBPolicyProhibits.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC373A620D810D800DBDF5B /* TPPBPolicyProhibits.proto */; }; DCE0774A21ADD640002662FD /* TPPBUnknownMachineID.proto in Sources */ = {isa = PBXBuildFile; fileRef = BEC373A720D810D900DBDF5B /* TPPBUnknownMachineID.proto */; }; DCE0774B21ADD642002662FD /* TPPBPeerStableInfo.proto in Sources */ = {isa = PBXBuildFile; fileRef = BE7089CC1FA3B332001ACC20 /* TPPBPeerStableInfo.proto */; }; @@ -5450,11 +5515,9 @@ DCE4E7AB1D7A43B500AFB96E /* Invalid-webmail.jaring.my.crt in Copy DigiCertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */; }; DCE4E7AC1D7A43B500AFB96E /* Invalid-www.cybersecurity.my.crt in Copy DigiCertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */; }; DCE4E7B51D7A43FF00AFB96E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE4E6D71D7A420D00AFB96E /* main.m */; }; - DCE4E7B61D7A440A00AFB96E /* bc-10-knife-on-bread.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE4E6D41D7A41E400AFB96E /* bc-10-knife-on-bread.m */; }; DCE4E7BF1D7A463400AFB96E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789041D77980500B50D50 /* Security.framework */; }; DCE4E7C11D7A463E00AFB96E /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE4E7C01D7A463E00AFB96E /* SecurityFoundation.framework */; }; DCE4E7C61D7A468300AFB96E /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EB2CA4D81D2C28C800AB770F /* libaks.a */; }; - DCE4E7DF1D7A4B4C00AFB96E /* bc-10-knife-on-bread.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE4E6D41D7A41E400AFB96E /* bc-10-knife-on-bread.m */; }; DCE4E7E21D7A4B7F00AFB96E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = DCE4E7E11D7A4B7F00AFB96E /* main.c */; }; DCE4E7E41D7A4B8F00AFB96E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D848541C6C1D9C0025BB44 /* Foundation.framework */; }; DCE4E7E71D7A4B9C00AFB96E /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1789261D7799D300B50D50 /* IOKit.framework */; }; @@ -5544,7 +5607,6 @@ DCEA5D571E2826DB0089CF55 /* CKKSSIV.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D541E2826DB0089CF55 /* CKKSSIV.m */; }; DCEA5D851E2F14810089CF55 /* OctagonAPSReceiver.h in Headers */ = {isa = PBXBuildFile; fileRef = DCEA5D831E2F14810089CF55 /* OctagonAPSReceiver.h */; }; DCEA5D871E2F14810089CF55 /* OctagonAPSReceiver.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D841E2F14810089CF55 /* OctagonAPSReceiver.m */; }; - DCEA5D971E3015830089CF55 /* CKKSZone.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA5D961E3014250089CF55 /* CKKSZone.m */; }; DCEDE3511D80B0FA00C3826E /* secd-71-engine-save-sample1.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC78C651D8085D800865A7C /* secd-71-engine-save-sample1.h */; }; DCEDE3901D80B10100C3826E /* SecOTRIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFF615AFB73800B9D400 /* SecOTRIdentityPriv.h */; }; DCEDE3911D80B10800C3826E /* SecCTKKeyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC78E451D8085FC00865A7C /* SecCTKKeyPriv.h */; }; @@ -5878,7 +5940,6 @@ DCF94A7C222D9F2400C01744 /* OctagonCKKSPeerAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF94A7A222D9F2400C01744 /* OctagonCKKSPeerAdapter.m */; }; DCFABF8E20081E2F001128B5 /* CKKSDeviceStateUploadTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFABF8D20081E2F001128B5 /* CKKSDeviceStateUploadTests.m */; }; DCFAEDCF1D999859005187E4 /* SOSAccountGhost.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFAEDC81D999851005187E4 /* SOSAccountGhost.m */; }; - DCFAEDD21D99991F005187E4 /* secd-668-ghosts.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFAEDD11D9998DD005187E4 /* secd-668-ghosts.m */; }; DCFAEDD61D99A47A005187E4 /* secd-36-ks-encrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFAEDD51D99A464005187E4 /* secd-36-ks-encrypt.m */; }; DCFAEDD71D99A4AB005187E4 /* secd-154-engine-backoff.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78C771D8085D800865A7C /* secd-154-engine-backoff.m */; }; DCFB12C51E95A4C000510F5F /* CKKSAccountStateTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = DCFB12C31E95A4C000510F5F /* CKKSAccountStateTracker.h */; }; @@ -5968,7 +6029,6 @@ E7F482961C74FDF800390FDB /* KCJoiningSession.h in Headers */ = {isa = PBXBuildFile; fileRef = E7F480131C7397CE00390FDB /* KCJoiningSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; E7F482A11C7543E500390FDB /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; E7F482A31C7544E600390FDB /* libctkclient_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7F482A21C7544E600390FDB /* libctkclient_test.a */; }; - E7F482A61C75453900390FDB /* libcoreauthd_test_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7F482A51C75453900390FDB /* libcoreauthd_test_client.a */; }; E7F482AA1C7554FB00390FDB /* NSError+KCCreationHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = E7F482A91C7554F500390FDB /* NSError+KCCreationHelpers.m */; }; E7F482AC1C7558F700390FDB /* KCJoiningAcceptSession.m in Sources */ = {isa = PBXBuildFile; fileRef = E7F482AB1C7558F700390FDB /* KCJoiningAcceptSession.m */; }; E7F482E61C7640D300390FDB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; @@ -6070,8 +6130,6 @@ EB49B2DD202DF259003F34A0 /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = EB49B2DC202DF251003F34A0 /* libbsm.tbd */; }; EB49B2E0202DF5D7003F34A0 /* server_entitlement_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = DC5F35A41EE0F1A900900966 /* server_entitlement_helpers.c */; }; EB49B308202FF421003F34A0 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47D1838B1FB3827700CFCD89 /* OCMock.framework */; }; - EB4B6E201DC0682A00AFC494 /* SecADWrapper.c in Sources */ = {isa = PBXBuildFile; fileRef = EBF3749A1DC064200065D840 /* SecADWrapper.c */; }; - EB4B6E261DC0683600AFC494 /* SecADWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = EBF3749B1DC064200065D840 /* SecADWrapper.h */; }; EB4E0CDB1FF36A9700CDCACC /* CKKSReachabilityTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = EB4E0CD51FF36A1900CDCACC /* CKKSReachabilityTracker.m */; }; EB58A0511E74BF07009C10D7 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; EB59D6731E95F01600997EAC /* libcompression.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EB59D66B1E95EF2900997EAC /* libcompression.dylib */; }; @@ -6140,13 +6198,10 @@ EB75B48C1E75407C00E469CC /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; }; EB75B48D1E75408900E469CC /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC8834081D8A218F00CE0ACA /* libASN1.a */; }; EB75B48F1E75409A00E469CC /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; - EB75B4901E7540AA00E469CC /* libctkclient_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FBDC1AA0A45C0021AA26 /* libctkclient_test.a */; }; - EB75B4911E7540BF00E469CC /* libcoreauthd_test_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E8B53A41AA0B8A600345E7B /* libcoreauthd_test_client.a */; }; EB75B4951E75A44100E469CC /* SOSPiggyback.h in Headers */ = {isa = PBXBuildFile; fileRef = EB75B4931E75A44100E469CC /* SOSPiggyback.h */; }; EB76B7591DCB0CA200C43FBC /* CloudKeychainProxy.8 in Install man8 page */ = {isa = PBXBuildFile; fileRef = DC24B5851DA432E900330B48 /* CloudKeychainProxy.8 */; }; EB7732C221963B0500FCF513 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; EB7732D921963BA500FCF513 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EB80DE57219600CF005B10FA /* libz.dylib */; }; - EB7732DB21963BC100FCF513 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D4119E72202BDF2B0048587B /* libz.tbd */; }; EB78D3F91E600E93009AFE05 /* SOSCloudCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC78D891D8085F200865A7C /* SOSCloudCircle.m */; }; EB7AE6F81E86DACC00B80B15 /* SecPLWrappers.m in Sources */ = {isa = PBXBuildFile; fileRef = EB7AE6F61E86D55400B80B15 /* SecPLWrappers.m */; }; EB7AE6F91E86DAD200B80B15 /* SecPLWrappers.h in Headers */ = {isa = PBXBuildFile; fileRef = EB7AE6F71E86D55400B80B15 /* SecPLWrappers.h */; }; @@ -6217,8 +6272,6 @@ EB973651234E8F4B00518B2B /* CKKSPBFileStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = EB97364F234E8F4A00518B2B /* CKKSPBFileStorage.h */; }; EB973652234E8F4B00518B2B /* CKKSPBFileStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = EB973650234E8F4B00518B2B /* CKKSPBFileStorage.m */; }; EB9795B522FE9256002BDBFB /* SecItemTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EB6D1D5322FE8D3000205E83 /* SecItemTests.m */; }; - EB9B283321C7755700173DC2 /* OTDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C8BBE971FC9DA5A00580909 /* OTDefines.h */; settings = {ATTRIBUTES = (Private, ); }; }; - EB9B283421C7755800173DC2 /* OTDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C8BBE971FC9DA5A00580909 /* OTDefines.h */; settings = {ATTRIBUTES = (Private, ); }; }; EB9B285721C77C8D00173DC2 /* OTDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = EBCE06E521C6E26000FB1493 /* OTDefines.m */; }; EB9B285821C77C8D00173DC2 /* OTDefines.m in Sources */ = {isa = PBXBuildFile; fileRef = EBCE06E521C6E26000FB1493 /* OTDefines.m */; }; EB9C02481E8A15B40040D3C6 /* secd-37-pairing-initial-sync.m in Sources */ = {isa = PBXBuildFile; fileRef = EB9C02421E8A112A0040D3C6 /* secd-37-pairing-initial-sync.m */; }; @@ -6290,13 +6343,18 @@ F667EC611E96E9E700203D5C /* authdtests.m in Sources */ = {isa = PBXBuildFile; fileRef = F6A0971F1E953ABD00B1E7D6 /* authdtests.m */; }; F667EC621E96EAD200203D5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F667EC551E96E94800203D5C /* main.m */; }; F667EC631E96EDC500203D5C /* libregressionBase.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCBFD1D8C648C00070CB0 /* libregressionBase.a */; }; + F681C3AB2386B8C30083F22C /* PreloginUserDb.m in Sources */ = {isa = PBXBuildFile; fileRef = F681C3A82386B8B40083F22C /* PreloginUserDb.m */; }; F682C1D41F4486F700F1B029 /* libctkloginhelper.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F682C1CE1F4486F600F1B029 /* libctkloginhelper.a */; }; F6AF96681E646CAF00917214 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4432AF6A1A01458F000958DC /* libcoreauthd_client.a */; }; + F6B1B48B24144B5F00CB3E3F /* libctkloginhelperlite.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B1B48924144B5E00CB3E3F /* libctkloginhelperlite.a */; }; F6EEF76F21675E8000FB7F79 /* AuthorizationTrampolinePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D600702166551800F9F7C9 /* AuthorizationTrampolinePriv.h */; }; F6EEF77521675EF000FB7F79 /* AuthorizationTrampolinePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D600702166551800F9F7C9 /* AuthorizationTrampolinePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F6F4105324AC622F00369037 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EB2CA4D81D2C28C800AB770F /* libaks.a */; }; F964772C1E5832540019E4EB /* SecCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = DCD0678E1D8CDF7E007602F1 /* SecCodePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; F9F77E98223C2F9A00E5CBF6 /* requirement.c in Sources */ = {isa = PBXBuildFile; fileRef = F9F77E96223C2F7B00E5CBF6 /* requirement.c */; }; F9F77E99223C2F9A00E5CBF6 /* requirement.h in Headers */ = {isa = PBXBuildFile; fileRef = F9F77E97223C2F7C00E5CBF6 /* requirement.h */; }; + FC63722F237B5D1C00973738 /* SecItemServer+SWC.m in Sources */ = {isa = PBXBuildFile; fileRef = FC63722A237B5CF900973738 /* SecItemServer+SWC.m */; }; + FC637231237B5D2200973738 /* SecItemServer+SWC.m in Sources */ = {isa = PBXBuildFile; fileRef = FC63722A237B5CF900973738 /* SecItemServer+SWC.m */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ @@ -6310,10 +6368,9 @@ ); isEditable = 1; outputFiles = ( - "$(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).exp", + "$(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).$(CURRENT_ARCH).exp", ); - runOncePerArchitecture = 0; - script = "#!/bin/sh\n\nfor file in ${HEADER_SEARCH_PATHS[@]} ; do\nHEADER_SEARCH_OPTIONS=\"${HEADER_SEARCH_OPTIONS} -I${file}\"\ndone\n\nfor prep in ${GCC_PREPROCESSOR_DEFINITIONS[@]} ; do\nPREPROCESSOR=\"${PREPROCESSOR} -D${prep}\"\ndone\n\nxcrun clang -E -Xpreprocessor -P -x objective-c ${HEADER_SEARCH_OPTIONS} ${OTHER_INPUT_FILE_FLAGS} ${PREPROCESSOR} ${INPUT_FILE_PATH} -o \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.exp\"\n"; + script = "#!/bin/sh\n\nfor file in ${HEADER_SEARCH_PATHS[@]} ; do\nHEADER_SEARCH_OPTIONS=\"${HEADER_SEARCH_OPTIONS} -I${file}\"\ndone\n\nfor prep in ${GCC_PREPROCESSOR_DEFINITIONS[@]} ; do\nPREPROCESSOR=\"${PREPROCESSOR} -D${prep}\"\ndone\n\nxcrun clang -E -Xpreprocessor -P -x objective-c -arch ${CURRENT_ARCH} ${HEADER_SEARCH_OPTIONS} ${OTHER_INPUT_FILE_FLAGS} ${PREPROCESSOR} ${INPUT_FILE_PATH} -o \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.${CURRENT_ARCH}.exp\"\n"; }; DCF216DD21ADD5D10029CCC1 /* PBXBuildRule */ = { isa = PBXBuildRule; @@ -6362,6 +6419,20 @@ remoteGlobalIDString = DC0BCC211D8C684F00070CB0; remoteInfo = utilities; }; + 0C2B36C223C42EBC00000718 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CD743A523C3EC8000FA0EC5; + remoteInfo = Clique; + }; + 0C2B36C423C42EC800000718 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CD743A523C3EC8000FA0EC5; + remoteInfo = Clique; + }; 0C2BCBBB1D0640B200ED7A2F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6376,19 +6447,19 @@ remoteGlobalIDString = 0C2BCBBD1D0648D100ED7A2F; remoteInfo = dtlsEchoServer; }; - 0C3E2EA82073F5C400F5B95B /* PBXContainerItemProxy */ = { + 0C65BB4C23C3F31B0063D2B7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 4C32C0AE0A4975F6002891BD; - remoteInfo = Security_ios; + remoteGlobalIDString = 0CD743A523C3EC8000FA0EC5; + remoteInfo = Clique; }; - 0C5663ED20BE2E1A0035F362 /* PBXContainerItemProxy */ = { + 0C65BB4E23C3F3270063D2B7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DC0BCC211D8C684F00070CB0; - remoteInfo = utilities; + remoteGlobalIDString = 0CD743A523C3EC8000FA0EC5; + remoteInfo = Clique; }; 0C78CCE41FCC97E7008B4B24 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -6404,6 +6475,20 @@ remoteGlobalIDString = 0C8BBEFD1FCB446400580909; remoteInfo = otctl; }; + 0C7EB14C23F3D13C0089097B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; + remoteInfo = aks_support; + }; + 0C7EB14E23F3D1480089097B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC0BCC211D8C684F00070CB0; + remoteInfo = utilities; + }; 0C85DFD91FB38BB6000343A7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6439,13 +6524,6 @@ remoteGlobalIDString = DCC78EA81D8088E200865A7C; remoteInfo = security; }; - 0C9AEEB920783FE000BF6237 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC1789031D77980500B50D50; - remoteInfo = Security_osx; - }; 0CA378E823876E0900090B7E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6467,6 +6545,48 @@ remoteGlobalIDString = DC52E7731D80BC8000B0A59C; remoteInfo = libsecurityd_ios; }; + 0CCC22AA23F38B0600E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; + remoteInfo = SecureObjectSyncServer; + }; + 0CCC22AC23F38B0E00E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC52E7731D80BC8000B0A59C; + remoteInfo = libsecurityd_ios; + }; + 0CCC22CD23F39A6300E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CCC220023F357EE00E1FCD0; + remoteInfo = OctagonTrustTests; + }; + 0CCC22CF23F39A6A00E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CCC220023F357EE00E1FCD0; + remoteInfo = OctagonTrustTests; + }; + 0CCC22D123F39A7500E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CCC220023F357EE00E1FCD0; + remoteInfo = OctagonTrustTests; + }; + 0CCC22D323F39A7C00E1FCD0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CCC220023F357EE00E1FCD0; + remoteInfo = OctagonTrustTests; + }; 0CF0920F219649DB002B0AEE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6523,6 +6643,13 @@ remoteGlobalIDString = DC0BCC211D8C684F00070CB0; remoteInfo = utilities; }; + 3E88361C24F08F5400E9F4D6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3E88360824F068EF00E9F4D6; + remoteInfo = secseccodeapitest; + }; 438169E61B4EE4B300C54D58 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6586,27 +6713,6 @@ remoteGlobalIDString = 4771D971209A755800BA9772; remoteInfo = KeychainDataclassOwner; }; - 478D426E1FD72A8100CAB645 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52EDA61D80D58400B0A59C; - remoteInfo = secdRegressions; - }; - 478D42701FD72A8100CAB645 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC0BCBD91D8C648C00070CB0; - remoteInfo = regressionBase; - }; - 478D42741FD72A8100CAB645 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCC78EA81D8088E200865A7C; - remoteInfo = security; - }; 47A6FC69206B461700BD6C54 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6614,13 +6720,6 @@ remoteGlobalIDString = DC52E7731D80BC8000B0A59C; remoteInfo = libsecurityd_ios; }; - 47A6FC6B206B462400BD6C54 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E7731D80BC8000B0A59C; - remoteInfo = libsecurityd_ios; - }; 47C2F18B2059CBEA0062DE30 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6656,13 +6755,6 @@ remoteGlobalIDString = DC1789031D77980500B50D50; remoteInfo = Security_osx; }; - 47D991CF20407F7E0078CAE2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4727FBB61F9918580003AE36; - remoteInfo = secdxctests_ios; - }; 47DE88CD1FA7AD6200DD3254 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6712,103 +6804,96 @@ remoteGlobalIDString = 5346480017331E1100FE9172; remoteInfo = KeychainSyncAccountNotification; }; - 6C4AA1A92228B640006FA945 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = EB9C1DAE1BDFD4DE00F89272; - remoteInfo = SecurityBatsTests; - }; - 6C8FF4B5224C1A9800E5C812 /* PBXContainerItemProxy */ = { + 5AAE383523D261CF0025CF9E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = BEF88C271EAFFC3F00357577; - remoteInfo = TrustedPeers; + remoteGlobalIDString = 5A442F81233C330F00918373; + remoteInfo = experimentTool; }; - 6C9808301E788AEB00E70590 /* PBXContainerItemProxy */ = { + 6C14CA0323C4F6830097B572 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DC8834011D8A218F00CE0ACA; - remoteInfo = ASN1_not_installed; + remoteGlobalIDString = 4718AE2E205B39C40068EC3F; + remoteInfo = libsecurityd_bridge; }; - 6C9808321E788AEB00E70590 /* PBXContainerItemProxy */ = { + 6C16258023C4FFC40086A0FF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DC0BCC211D8C684F00070CB0; - remoteInfo = utilities; + remoteGlobalIDString = D4ADA3181E2B41670031CEA3; + remoteInfo = libtrustd; }; - 6C9808361E788AEB00E70590 /* PBXContainerItemProxy */ = { + 6C16258323C4FFD40086A0FF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; remoteInfo = SecureObjectSyncFramework; }; - 6C9808381E788AEB00E70590 /* PBXContainerItemProxy */ = { + 6C16258523C4FFD40086A0FF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; remoteInfo = SecureObjectSyncServer; }; - 6C98083A1E788AEB00E70590 /* PBXContainerItemProxy */ = { + 6C2045F72424BC4400F9461D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DCC78EA81D8088E200865A7C; - remoteInfo = security; + remoteGlobalIDString = 6C2045E92424BA7E00F9461D; + remoteInfo = KeychainStasher; }; - 6C98086C1E788AFD00E70590 /* PBXContainerItemProxy */ = { + 6C2D797222C06CEB00C3CE32 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DC8834011D8A218F00CE0ACA; - remoteInfo = ASN1_not_installed; + remoteGlobalIDString = 6C39234421F13E4D00D018AD; + remoteInfo = SecDbBackupTests; }; - 6C98086E1E788AFD00E70590 /* PBXContainerItemProxy */ = { + 6C2D797422C06CEF00C3CE32 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DC0BCC211D8C684F00070CB0; - remoteInfo = utilities; + remoteGlobalIDString = 4727FBB61F9918580003AE36; + remoteInfo = secdxctests; }; - 6C9808721E788AFD00E70590 /* PBXContainerItemProxy */ = { + 6C4AA1A92228B640006FA945 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; - remoteInfo = SecureObjectSyncFramework; + remoteGlobalIDString = EB9C1DAE1BDFD4DE00F89272; + remoteInfo = SecurityBatsTests; }; - 6C9808741E788AFD00E70590 /* PBXContainerItemProxy */ = { + 6C61D3E7242A29BA008AB9BB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; - remoteInfo = SecureObjectSyncServer; + remoteGlobalIDString = 6C963280242A279B00C53CE2; + remoteInfo = stashtester; }; - 6C9808761E788AFD00E70590 /* PBXContainerItemProxy */ = { + 6C7BE2AB23C3DD64003BB2CA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = DCC78EA81D8088E200865A7C; - remoteInfo = security; + remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; + remoteInfo = aks_support; }; - 6C98089F1E788B9400E70590 /* PBXContainerItemProxy */ = { + 6C7BE2AD23C3DD64003BB2CA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 6CF4A0B31E45488B00ECD7B5; - remoteInfo = KeychainEntitledTestApp_mac; + remoteGlobalIDString = DC0BCC211D8C684F00070CB0; + remoteInfo = utilities; }; - 6C9808A31E788CB100E70590 /* PBXContainerItemProxy */ = { + 6C7BE2E923C3DD9C003BB2CA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 6CF4A0DF1E4549F200ECD7B5; - remoteInfo = KeychainEntitledTestApp_ios; + remoteGlobalIDString = 6C7BE2A923C3DD64003BB2CA; + remoteInfo = securitytool_bridge; }; 6C9A49B11FAB647D00239D58 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -6817,6 +6902,13 @@ remoteGlobalIDString = DC0BCC211D8C684F00070CB0; remoteInfo = utilities; }; + 6CA9690C24ACC5C100C08B5E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC0BCC211D8C684F00070CB0; + remoteInfo = utilities; + }; 6CAA8D3C1F8431BC007B6E03 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -6831,6 +6923,76 @@ remoteGlobalIDString = 6CAA8D1F1F842FB3007B6E03; remoteInfo = supd; }; + 6CC638E6226695B900E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; + remoteInfo = SecureObjectSyncServer; + }; + 6CC638E8226695B900E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; + remoteInfo = SecureObjectSyncFramework; + }; + 6CC638EA226695C300E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; + remoteInfo = SecureObjectSyncServer; + }; + 6CC638EC226695C300E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; + remoteInfo = SecureObjectSyncFramework; + }; + 6CC638FD2266AE0A00E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4727FBB61F9918580003AE36; + remoteInfo = secdxctests; + }; + 6CC638FF2266AE0A00E5DB0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6C39234421F13E4D00D018AD; + remoteInfo = SecDbBackupTests; + }; + 6CE2AEAA22B2C1BE00C96AE7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6CF4A0B31E45488B00ECD7B5; + remoteInfo = "KeychainEntitledTestApp-mac"; + }; + 6CE2AEAC22B2C1C300C96AE7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6CF4A0B31E45488B00ECD7B5; + remoteInfo = "KeychainEntitledTestApp-mac"; + }; + 6CF33CA52387156600D1E75D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4727FBB61F9918580003AE36; + remoteInfo = secdxctests; + }; + 6CF33CA72387157200D1E75D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4727FBB61F9918580003AE36; + remoteInfo = secdxctests; + }; 873C14B121540FED003C9C00 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -7223,13 +7385,6 @@ remoteGlobalIDString = 6CCDF7831E3C25FA003F2555; remoteInfo = KeychainEntitledTestRunner; }; - D45D8F832224DBEF00D6C124 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6C9808681E788AFD00E70590; - remoteInfo = CKKSCloudKitTests_ios; - }; D45D8F852224DBF800D6C124 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -7377,13 +7532,6 @@ remoteGlobalIDString = BEF88C2F1EAFFC3F00357577; remoteInfo = TrustedPeersTests; }; - D477EE8221ED48E800C9AAFF /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 478D426C1FD72A8100CAB645; - remoteInfo = secdxctests_mac; - }; D4794E6A21222E72007C6725 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -7426,20 +7574,6 @@ remoteGlobalIDString = DC3502B41E0208BE00BC0587; remoteInfo = CKKSTests; }; - D4A763DA2224BDAB0063B2B9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6C98082C1E788AEB00E70590; - remoteInfo = CKKSCloudKitTests_mac; - }; - D4A763DC2224BDCC0063B2B9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6CF4A0B31E45488B00ECD7B5; - remoteInfo = KeychainEntitledTestApp_mac; - }; D4A763DE2224BDDC0063B2B9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -7713,20 +7847,6 @@ remoteGlobalIDString = 47702B2D1E5F492C00B29577; remoteInfo = seckeychainnetworkextensionunauthorizedaccesstest; }; - D4E0E9752224DE9100A802E0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4727FBB61F9918580003AE36; - remoteInfo = secdxctests_ios; - }; - D4E0E9792224DEE600A802E0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6CF4A0DF1E4549F200ECD7B5; - remoteInfo = KeychainEntitledTestApp_ios; - }; D4E0E97B2224DF0300A802E0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -7888,13 +8008,6 @@ remoteGlobalIDString = 47702B2D1E5F492C00B29577; remoteInfo = seckeychainnetworkextensionunauthorizedaccesstest; }; - D4E0E9AB2224DFEB00A802E0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4727FBB61F9918580003AE36; - remoteInfo = secdxctests_ios; - }; D4E0E9AD2224E00600A802E0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -8728,27 +8841,6 @@ remoteGlobalIDString = DC52E7731D80BC8000B0A59C; remoteInfo = libsecurityd_ios; }; - DC34CD2C20326C2C00302481 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; - remoteInfo = SecureObjectSyncServer; - }; - DC34CD3320326C3100302481 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; - remoteInfo = SecureObjectSyncFramework; - }; - DC34CD3520326C3B00302481 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC0BCC211D8C684F00070CB0; - remoteInfo = utilities; - }; DC3502C31E020D4D00BC0587 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -9267,13 +9359,6 @@ remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; remoteInfo = aks_support; }; - DC69A5862165298500512BD6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; - remoteInfo = aks_support; - }; DC6BC2731D90D07800DD57B3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -9379,20 +9464,6 @@ remoteGlobalIDString = DC8834011D8A218F00CE0ACA; remoteInfo = ASN1_not_installed; }; - DC93C4C8214713DC008F8362 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E7731D80BC8000B0A59C; - remoteInfo = libsecurityd_ios; - }; - DC93C4CC21471401008F8362 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E7731D80BC8000B0A59C; - remoteInfo = libsecurityd_ios; - }; DC99B85D20EACA470065B73B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -9743,20 +9814,6 @@ remoteGlobalIDString = DCD66DC41D8205C400DB1393; remoteInfo = libSecOtrOSX; }; - DCD6BF5321E919610015F7A8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; - remoteInfo = aks_support; - }; - DCD6BF5521E9196E0015F7A8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; - remoteInfo = aks_support; - }; DCD6BF5721E919820015F7A8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -9890,6 +9947,13 @@ remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2; remoteInfo = aks_support; }; + DCE27860245B81BD00381FE8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4771D971209A755800BA9772; + remoteInfo = KeychainDataclassOwner; + }; DCE4E8D71D7F37F200AFB96E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -10324,20 +10388,6 @@ remoteGlobalIDString = DC0BC5501D8B6D2D00070CB0; remoteInfo = XPCKeychainSandboxCheck; }; - EBD7DF8021FF475B0089F2DF /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DC52E8BE1D80C25800B0A59C; - remoteInfo = SecureObjectSyncServer; - }; - EBD7DF8221FF475B0089F2DF /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C35DB69094F906D002917C4 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A; - remoteInfo = SecureObjectSyncFramework; - }; EBF374811DC058B60065D840 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -10432,16 +10482,6 @@ name = "Copy System logging profile"; runOnlyForDeploymentPostprocessing = 1; }; - 0C9AEEB320783FBB00BF6237 /* Embed OCMock */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed OCMock"; - runOnlyForDeploymentPostprocessing = 0; - }; 0CA378E623876DEC00090B7E /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -10452,16 +10492,6 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - 0CF4064A2072E3E3003D6A7F /* Embed OCMock */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed OCMock"; - runOnlyForDeploymentPostprocessing = 0; - }; 3D58394821890FFB000ACA44 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -10556,6 +10586,7 @@ dstPath = /System/Library/Preferences/Logging/Subsystems; dstSubfolderSpec = 0; files = ( + DCDACB5A24A3F39A0054080C /* com.apple.security.ckks.plist in Copy Logging Files */, DC71D8F51D959F150065FB93 /* com.apple.securityd.plist in Copy Logging Files */, ); name = "Copy Logging Files"; @@ -10756,6 +10787,28 @@ name = "Install man8 page"; runOnlyForDeploymentPostprocessing = 1; }; + 6C2045F32424BBB900F9461D /* Install Sandbox Profile */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/Sandbox/Profiles; + dstSubfolderSpec = 0; + files = ( + 6C2045F42424BBCD00F9461D /* com.apple.security.KeychainStasher.sb in Install Sandbox Profile */, + ); + name = "Install Sandbox Profile"; + runOnlyForDeploymentPostprocessing = 1; + }; + 6C2045FA2424BCC300F9461D /* Install LaunchAgent plist */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/LaunchAgents; + dstSubfolderSpec = 0; + files = ( + 6C2045FB2424BCD600F9461D /* com.apple.security.KeychainStasher.plist in Install LaunchAgent plist */, + ); + name = "Install LaunchAgent plist"; + runOnlyForDeploymentPostprocessing = 1; + }; 6C23F02E227A39FD009F6756 /* Install Sandbox Profile */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -10777,17 +10830,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6C7E8F1F21F7BE64008A2D56 /* Copy BATS Test Discovery Plist */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /AppleInternal/CoreOS/BATS/unit_tests; - dstSubfolderSpec = 0; - files = ( - 6C02135021F7EF07009D5C80 /* SecDbBackupTests.plist in Copy BATS Test Discovery Plist */, - ); - name = "Copy BATS Test Discovery Plist"; - runOnlyForDeploymentPostprocessing = 1; - }; 6C9AA79C1F7C1D8F00D08296 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -11292,6 +11334,7 @@ dstPath = /System/Library/Preferences/Logging/Subsystems; dstSubfolderSpec = 0; files = ( + DCDACB5924A3F38E0054080C /* com.apple.security.ckks.plist in Copy Logging Files */, DCE4E80E1D7A4E3B00AFB96E /* com.apple.securityd.plist in Copy Logging Files */, ); name = "Copy Logging Files"; @@ -11646,16 +11689,18 @@ 09E9991F1F7D76550018DF67 /* SecKeyProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecKeyProxy.m; sourceTree = ""; }; 0C00FC81217A971800C8BF00 /* OTLocalCuttlefishReset.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTLocalCuttlefishReset.m; sourceTree = ""; }; 0C00FC85217A972E00C8BF00 /* OTLocalCuttlefishReset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTLocalCuttlefishReset.h; sourceTree = ""; }; + 0C0203E023A8564E005D0A68 /* OTEscrowRecord.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; name = OTEscrowRecord.proto; path = proto/OTEscrowRecord.proto; sourceTree = ""; }; 0C0BDB2F175685B000BC1A7E /* secdtests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secdtests; sourceTree = BUILT_PRODUCTS_DIR; }; 0C0BDB31175685B000BC1A7E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 0C0BDB441756868B00BC1A7E /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testlist.h; sourceTree = ""; }; 0C0C4F83216FB55600C14C61 /* EscrowKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EscrowKeys.swift; sourceTree = ""; }; 0C0C4F84216FB56B00C14C61 /* BottledPeer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottledPeer.swift; sourceTree = ""; }; 0C0C88771CCEC5BD00617D1B /* si-82-sectrust-ct-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-82-sectrust-ct-data"; path = "../OSX/shared_regressions/si-82-sectrust-ct-data"; sourceTree = ""; }; + 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_EscrowRecords.swift; sourceTree = ""; }; 0C0CEC9D1DA45EA200C22FBC /* recovery_key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = recovery_key.h; sourceTree = ""; }; 0C0CEC9E1DA45EA200C22FBC /* recovery_key.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = recovery_key.m; sourceTree = ""; }; + 0C0D920523BFEA740070A68C /* OTCDPRecoveryInformation.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; name = OTCDPRecoveryInformation.proto; path = proto/OTCDPRecoveryInformation.proto; sourceTree = ""; }; 0C0F76DD21399AF40074EDDF /* OTPairingMessage.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = OTPairingMessage.proto; sourceTree = ""; }; - 0C108C4B208A677100E8CF70 /* SFSignInAnalytics+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFSignInAnalytics+Internal.h"; sourceTree = ""; }; 0C12B1F02138D31600BE0A98 /* OTClientStateMachine.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTClientStateMachine.m; sourceTree = ""; }; 0C12B1F52138D32F00BE0A98 /* OTClientStateMachine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTClientStateMachine.h; sourceTree = ""; }; 0C1B8BB3223323710094D5DA /* OTVouchWithRecoveryKeyOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTVouchWithRecoveryKeyOperation.h; sourceTree = ""; }; @@ -11675,6 +11720,26 @@ 0C3BB3562188E18B0018FC14 /* OTPrivateKey+SF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OTPrivateKey+SF.h"; path = "keychain/TrustedPeersHelper/categories/OTPrivateKey+SF.h"; sourceTree = SOURCE_ROOT; }; 0C3BB3572188E18C0018FC14 /* OTAuthenticatedCiphertext+SF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OTAuthenticatedCiphertext+SF.h"; path = "keychain/TrustedPeersHelper/categories/OTAuthenticatedCiphertext+SF.h"; sourceTree = SOURCE_ROOT; }; 0C3C00721EF3636300AB19FE /* secd-155-otr-negotiation-monitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-155-otr-negotiation-monitor.m"; sourceTree = ""; }; + 0C3C47C024902D450084B951 /* OTSupportOctagonMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSupportOctagonMessage.m; sourceTree = ""; }; + 0C3C47C224902D460084B951 /* OTSupportSOSMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSupportSOSMessage.h; sourceTree = ""; }; + 0C3C47C324902D460084B951 /* OTSupportSOSMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSupportSOSMessage.m; sourceTree = ""; }; + 0C3C47C424902D470084B951 /* OTSupportOctagonMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSupportOctagonMessage.h; sourceTree = ""; }; + 0C3C47C524902D470084B951 /* OTGlobalEnums.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTGlobalEnums.h; sourceTree = ""; }; + 0C3DF8C524789C04009CF03A /* Container_Peers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_Peers.swift; sourceTree = ""; }; + 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowRecordMetadata.m; path = proto/generated_source/OTEscrowRecordMetadata.m; sourceTree = ""; }; + 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowRecordMetadataClientMetadata.m; path = proto/generated_source/OTEscrowRecordMetadataClientMetadata.m; sourceTree = ""; }; + 0C468FDA23C7D41D006F4582 /* OTEscrowRecordMetadata.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowRecordMetadata.h; path = proto/generated_source/OTEscrowRecordMetadata.h; sourceTree = ""; }; + 0C468FDB23C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowRecordMetadataClientMetadata.h; path = proto/generated_source/OTEscrowRecordMetadataClientMetadata.h; sourceTree = ""; }; + 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowRecord.m; path = proto/generated_source/OTEscrowRecord.m; sourceTree = ""; }; + 0C468FDE23C7D471006F4582 /* OTEscrowRecord.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowRecord.h; path = proto/generated_source/OTEscrowRecord.h; sourceTree = ""; }; + 0C468FE723C7D4C7006F4582 /* OTICDPRecordContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTICDPRecordContext.h; path = proto/generated_source/OTICDPRecordContext.h; sourceTree = ""; }; + 0C468FE823C7D4C8006F4582 /* OTEscrowAuthenticationInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowAuthenticationInformation.h; path = proto/generated_source/OTEscrowAuthenticationInformation.h; sourceTree = ""; }; + 0C468FE923C7D4C8006F4582 /* OTICDPRecordSilentContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTICDPRecordSilentContext.h; path = proto/generated_source/OTICDPRecordSilentContext.h; sourceTree = ""; }; + 0C468FEA23C7D4C8006F4582 /* OTCDPRecoveryInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTCDPRecoveryInformation.h; path = proto/generated_source/OTCDPRecoveryInformation.h; sourceTree = ""; }; + 0C468FEB23C7D4C9006F4582 /* OTICDPRecordSilentContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTICDPRecordSilentContext.m; path = proto/generated_source/OTICDPRecordSilentContext.m; sourceTree = ""; }; + 0C468FEC23C7D4C9006F4582 /* OTEscrowAuthenticationInformation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowAuthenticationInformation.m; path = proto/generated_source/OTEscrowAuthenticationInformation.m; sourceTree = ""; }; + 0C468FED23C7D4C9006F4582 /* OTICDPRecordContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTICDPRecordContext.m; path = proto/generated_source/OTICDPRecordContext.m; sourceTree = ""; }; + 0C468FEE23C7D4CA006F4582 /* OTCDPRecoveryInformation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTCDPRecoveryInformation.m; path = proto/generated_source/OTCDPRecoveryInformation.m; sourceTree = ""; }; 0C48990A1E0E0FF300C6CF70 /* SOSTransportCircleCK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportCircleCK.h; sourceTree = ""; }; 0C4899111E0E105D00C6CF70 /* SOSTransportCircleCK.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSTransportCircleCK.m; sourceTree = ""; }; 0C48991B1E0F384700C6CF70 /* SOSAccountTrustClassic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SOSAccountTrustClassic.m; path = SecureObjectSync/SOSAccountTrustClassic.m; sourceTree = ""; }; @@ -11685,6 +11750,8 @@ 0C5258B821BB05C100B32C96 /* FakeSOSControl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FakeSOSControl.m; path = Tests/FakeSOSControl.m; sourceTree = ""; }; 0C5258BC21BB137800B32C96 /* FakeSOSControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FakeSOSControl.h; path = Tests/FakeSOSControl.h; sourceTree = ""; }; 0C5824A322860001009E8C15 /* OctagonTests+HealthCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+HealthCheck.swift"; sourceTree = ""; }; + 0C64C07C2485A53000D84A5D /* OTPreloadOctagonKeysOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTPreloadOctagonKeysOperation.m; sourceTree = ""; }; + 0C64C07F2485A54100D84A5D /* OTPreloadOctagonKeysOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTPreloadOctagonKeysOperation.h; sourceTree = ""; }; 0C6604692134983900BFBBB8 /* OTEstablishOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTEstablishOperation.m; sourceTree = ""; }; 0C66046E2134985100BFBBB8 /* OTEstablishOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTEstablishOperation.h; sourceTree = ""; }; 0C6604782134C86500BFBBB8 /* OTDeviceInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTDeviceInformation.h; sourceTree = ""; }; @@ -11717,6 +11784,8 @@ 0C8FD546214AEC650098E3FB /* OTJoiningConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTJoiningConfiguration.h; sourceTree = ""; }; 0C8FD549214AECD70098E3FB /* OTJoiningConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTJoiningConfiguration.m; sourceTree = ""; }; 0C97867C235A76E70040A867 /* com.apple.security.signposts.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.signposts.plist; sourceTree = ""; }; + 0C9A54B4250C27F100FF007B /* OctagonTrustTests+Errors.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OctagonTrustTests+Errors.m"; sourceTree = ""; }; + 0C9A54B7250C290800FF007B /* OctagonTrustTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonTrustTests.h; sourceTree = ""; }; 0C9AE289214054F4003BFDB5 /* OTSponsorToApplicantRound1M2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSponsorToApplicantRound1M2.h; sourceTree = ""; }; 0C9AE28A214054F5003BFDB5 /* OTSponsorToApplicantRound2M2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSponsorToApplicantRound2M2.h; sourceTree = ""; }; 0C9AE28B214054F5003BFDB5 /* OTApplicantToSponsorRound2M1.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTApplicantToSponsorRound2M1.h; sourceTree = ""; }; @@ -11725,8 +11794,9 @@ 0C9AE290214054F7003BFDB5 /* OTSponsorToApplicantRound2M2.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSponsorToApplicantRound2M2.m; sourceTree = ""; }; 0C9AE2A1214055CE003BFDB5 /* OTPairingMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTPairingMessage.h; sourceTree = ""; }; 0C9AE2A2214055CF003BFDB5 /* OTPairingMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTPairingMessage.m; sourceTree = ""; }; - 0C9AEEB720783FBB00BF6237 /* SignInAnalyticsTests_osx.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SignInAnalyticsTests_osx.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C9FB40120D8729A00864612 /* CoreCDP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreCDP.framework; path = System/Library/PrivateFrameworks/CoreCDP.framework; sourceTree = SDKROOT; }; + 0C9F65AA23E3ACF700B1A2C5 /* OTEscrowTranslation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTEscrowTranslation.m; sourceTree = ""; }; + 0C9F65AC23E3ACF700B1A2C5 /* OTEscrowTranslation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTEscrowTranslation.h; sourceTree = ""; }; + 0CA1D0B223E9023100021038 /* OctagonTests+EscrowTestVectors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+EscrowTestVectors.swift"; sourceTree = ""; }; 0CA4EBF1202B8D1C002B1D96 /* CloudKitKeychainSyncingTestsBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CloudKitKeychainSyncingTestsBase.h; sourceTree = ""; }; 0CA4EBF2202B8D1D002B1D96 /* CloudKitKeychainSyncingTestsBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudKitKeychainSyncingTestsBase.m; sourceTree = ""; }; 0CA702082280D5600085AC54 /* OTCheckHealthOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTCheckHealthOperation.m; sourceTree = ""; }; @@ -11753,16 +11823,29 @@ 0CBA047C214C4E4D005B3A2F /* OctagonPairingTests+ProxMultiClients.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonPairingTests+ProxMultiClients.swift"; sourceTree = ""; }; 0CBEF3412242C9AE00015691 /* TestsObjcTranslation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestsObjcTranslation.m; sourceTree = ""; }; 0CBEF3422242C9BE00015691 /* TestsObjcTranslation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestsObjcTranslation.h; sourceTree = ""; }; + 0CBF883A23AAD9DC00652EDD /* OctagonTests+EscrowRecords.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+EscrowRecords.swift"; sourceTree = ""; }; 0CC8A8FA2123A9EB005D7F6A /* OTClientVoucherOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTClientVoucherOperation.m; sourceTree = ""; }; 0CC8A9002123AA3B005D7F6A /* OTClientVoucherOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTClientVoucherOperation.h; sourceTree = ""; }; 0CC8A9012123AEF7005D7F6A /* OTJoinWithVoucherOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTJoinWithVoucherOperation.m; sourceTree = ""; }; 0CC8A9052123AF16005D7F6A /* OTJoinWithVoucherOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTJoinWithVoucherOperation.h; sourceTree = ""; }; + 0CCC227923F357EE00E1FCD0 /* OctagonTrustTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OctagonTrustTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CCC229223F35D4300E1FCD0 /* OctagonTrustTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "OctagonTrustTests-Info.plist"; sourceTree = ""; }; + 0CCC229F23F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OctagonTrustTests-EscrowRecords.m"; sourceTree = ""; }; + 0CCC22A323F36DD300E1FCD0 /* OctagonTrustTests-EscrowTestVectors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OctagonTrustTests-EscrowTestVectors.h"; sourceTree = ""; }; + 0CCC22B123F38B5B00E1FCD0 /* libsqlite3.0.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.0.tbd; path = usr/lib/libsqlite3.0.tbd; sourceTree = SDKROOT; }; + 0CCC22CC23F395A100E1FCD0 /* OctagonTrustEscrowRecoverer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonTrustEscrowRecoverer.h; sourceTree = ""; }; + 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreCDP.framework; path = System/Library/PrivateFrameworks/CoreCDP.framework; sourceTree = SDKROOT; }; 0CCCC7C720261D050024405E /* OT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OT.h; sourceTree = ""; }; 0CCCC7C820261D310024405E /* OT.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OT.m; sourceTree = ""; }; 0CCDE7161EEB08220021A946 /* secd-156-timers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-156-timers.m"; sourceTree = ""; }; 0CD3D5152240479600024755 /* OTSetRecoveryKeyOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSetRecoveryKeyOperation.m; sourceTree = ""; }; 0CD3D518224047B400024755 /* OTSetRecoveryKeyOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSetRecoveryKeyOperation.h; sourceTree = ""; }; 0CD5797721498F7700C43496 /* OctagonPairingTests+Piggybacking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonPairingTests+Piggybacking.swift"; sourceTree = ""; }; + 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OctagonTrust.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CD743A823C3EC8000FA0EC5 /* OctagonTrust.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonTrust.h; sourceTree = ""; }; + 0CD743A923C3EC8000FA0EC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0CD743B723C3ED7E00FA0EC5 /* OctagonTrust.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OctagonTrust.m; sourceTree = ""; }; + 0CD743BA23C3EF0D00FA0EC5 /* OTClique+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OTClique+Private.h"; sourceTree = ""; }; 0CD8CB041ECA50780076F37F /* SOSPeerOTRTimer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSPeerOTRTimer.m; sourceTree = ""; }; 0CD8CB0C1ECA50D10076F37F /* SOSPeerOTRTimer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSPeerOTRTimer.h; sourceTree = ""; }; 0CD8D654207D6E65005CDBE8 /* SFAnalytics+Signin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFAnalytics+Signin.h"; sourceTree = ""; }; @@ -11788,12 +11871,10 @@ 0CE760531E13155100B4381E /* SOSAccountTrustClassic+Circle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SOSAccountTrustClassic+Circle.h"; path = "SecureObjectSync/SOSAccountTrustClassic+Circle.h"; sourceTree = ""; }; 0CE760551E1316E900B4381E /* SOSAccountTrustClassic+Retirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SOSAccountTrustClassic+Retirement.h"; path = "SecureObjectSync/SOSAccountTrustClassic+Retirement.h"; sourceTree = ""; }; 0CE98B5B1FA9360700CF1D54 /* libprequelite.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libprequelite.tbd; path = usr/lib/libprequelite.tbd; sourceTree = SDKROOT; }; - 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFSignInAnalytics.m; sourceTree = ""; }; - 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFSignInAnalytics.h; sourceTree = ""; }; - 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFSignInAnalyticsTests.m; sourceTree = ""; }; 0CF405FC2072E352003D6A7F /* SFTMTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SFTMTests-Info.plist"; sourceTree = ""; }; - 0CF406502072E3E3003D6A7F /* SignInAnalyticsTests_ios.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SignInAnalyticsTests_ios.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 0CF70BD6218BECF500EC3515 /* CuttlefishExtensionWorkaround.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CuttlefishExtensionWorkaround.swift; sourceTree = ""; }; + 0CF7613D23F24B5D00A3C3AD /* KeychainCircle.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = KeychainCircle.modulemap; path = Modules/KeychainCircle.modulemap; sourceTree = ""; }; + 0CF7613F23F24B5E00A3C3AD /* OctagonTrust.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = OctagonTrust.modulemap; path = Modules/OctagonTrust.modulemap; sourceTree = ""; }; 0CFC029B1D41650700E6283B /* libcoretls.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcoretls.dylib; path = usr/lib/libcoretls.dylib; sourceTree = SDKROOT; }; 107226D00D91DB32003CF14F /* SecTask.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecTask.c; sourceTree = ""; }; 107226D10D91DB32003CF14F /* SecTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTask.h; path = sectask/SecTask.h; sourceTree = ""; }; @@ -11826,6 +11907,8 @@ 2281820D17B4686C0067C9C9 /* BackgroundTaskAgent.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BackgroundTaskAgent.framework; path = System/Library/PrivateFrameworks/BackgroundTaskAgent.framework; sourceTree = SDKROOT; }; 24CBF8731E9D4E4500F09F0E /* kc-44-secrecoverypassword.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-44-secrecoverypassword.c"; path = "regressions/kc-44-secrecoverypassword.c"; sourceTree = ""; }; 3D58394D21890FFB000ACA44 /* SecExperimentTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecExperimentTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3DC5BD58241830D50039ABF4 /* SecureTransportTests_macos.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = SecureTransportTests_macos.xctestplan; path = OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_macos.xctestplan; sourceTree = ""; }; + 3DC5BD59241845100039ABF4 /* SecureTransportTests_ios.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = SecureTransportTests_ios.xctestplan; path = OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan; sourceTree = ""; }; 3DD1FE78201AA50C0086D049 /* STLegacyTests+clientauth41.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "STLegacyTests+clientauth41.m"; sourceTree = ""; }; 3DD1FE79201AA50D0086D049 /* SecureTransport_macosTests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SecureTransport_macosTests.plist; sourceTree = ""; }; 3DD1FE7A201AA50D0086D049 /* STLegacyTests-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "STLegacyTests-Entitlements.plist"; sourceTree = ""; }; @@ -11852,6 +11935,8 @@ 3DD1FFA9201FC5C30086D049 /* libcoretls_cfhelpers.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcoretls_cfhelpers.tbd; path = usr/lib/libcoretls_cfhelpers.tbd; sourceTree = SDKROOT; }; 3DD1FFD0201FDB1D0086D049 /* SecureTransport_ios_tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecureTransport_ios_tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3DD2589820478CCE00F5DA78 /* STLegacyTests+session.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "STLegacyTests+session.m"; sourceTree = ""; }; + 3E88361124F068EF00E9F4D6 /* secseccodeapitest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secseccodeapitest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E88361324F0699F00E9F4D6 /* secseccodeapitest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = secseccodeapitest.c; sourceTree = ""; }; 433E519D1B66D5F600482618 /* AppSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppSupport.framework; path = System/Library/PrivateFrameworks/AppSupport.framework; sourceTree = SDKROOT; }; 4381690C1B4EDCBD00C54D58 /* SOSCCAuthPlugin.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SOSCCAuthPlugin.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 4381690F1B4EDCBD00C54D58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -11886,7 +11971,7 @@ 4723C9D11F1531970082882F /* CKKSLoggerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSLoggerTests.m; sourceTree = ""; }; 4723C9DA1F1540CE0082882F /* SFAnalytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalytics.h; sourceTree = ""; }; 4723C9DB1F1540CE0082882F /* SFAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalytics.m; sourceTree = ""; }; - 4727FBB71F9918580003AE36 /* secdxctests_ios.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = secdxctests_ios.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4727FBB71F9918580003AE36 /* secdxctests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = secdxctests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 4727FBB91F9918590003AE36 /* KeychainCryptoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainCryptoTests.m; sourceTree = ""; }; 4727FBBB1F9918590003AE36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 4727FBC41F991C460003AE36 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; @@ -11905,7 +11990,6 @@ 4727FBE41F99217A0003AE36 /* SharedWebCredentials.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SharedWebCredentials.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.Internal.sdk/System/Library/PrivateFrameworks/SharedWebCredentials.framework; sourceTree = DEVELOPER_DIR; }; 4727FBE61F9921890003AE36 /* ApplePushService.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplePushService.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.Internal.sdk/System/Library/PrivateFrameworks/ApplePushService.framework; sourceTree = DEVELOPER_DIR; }; 4727FBE81F9921D00003AE36 /* libACM.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libACM.a; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.Internal.sdk/usr/local/lib/libACM.a; sourceTree = DEVELOPER_DIR; }; - 472E184F20D9A20D00ECE7C9 /* libcoreauthd_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcoreauthd_client.a; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/usr/local/lib/libcoreauthd_client.a; sourceTree = DEVELOPER_DIR; }; 473337771FDAFBCC00E19F30 /* SFKeychainControlManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFKeychainControlManager.h; sourceTree = ""; }; 473337781FDAFBCC00E19F30 /* SFKeychainControlManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFKeychainControlManager.m; sourceTree = ""; }; 473337821FDB29A200E19F30 /* KeychainCheck.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainCheck.h; sourceTree = ""; }; @@ -11927,7 +12011,6 @@ 475EDCF520D98BCF009D2409 /* libACM.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libACM.a; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/usr/local/lib/libACM.a; sourceTree = DEVELOPER_DIR; }; 475EDCF720D98BF6009D2409 /* CoreCDP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreCDP.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/PrivateFrameworks/CoreCDP.framework; sourceTree = DEVELOPER_DIR; }; 475EDCF920D98C0D009D2409 /* CryptoTokenKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CryptoTokenKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/PrivateFrameworks/CryptoTokenKit.framework; sourceTree = DEVELOPER_DIR; }; - 475EDCFB20D98C3C009D2409 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/libDER.a; sourceTree = SDKROOT; }; 475EDCFD20D98C53009D2409 /* libaks.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks.a; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/usr/local/lib/libaks.a; sourceTree = DEVELOPER_DIR; }; 475EDCFF20D98C64009D2409 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; }; 475EDD0120D98C81009D2409 /* libaks_acl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks_acl.a; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/usr/local/lib/libaks_acl.a; sourceTree = DEVELOPER_DIR; }; @@ -11956,7 +12039,6 @@ 477A1FE1203763A500ACD81D /* KeychainAPITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainAPITests.m; sourceTree = ""; }; 477A1FEB2037A0E000ACD81D /* KeychainXCTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainXCTest.h; sourceTree = ""; }; 477A1FEC2037A0E000ACD81D /* KeychainXCTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainXCTest.m; sourceTree = ""; }; - 478D429C1FD72A8100CAB645 /* secdxctests_mac.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = secdxctests_mac.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 479108B51EE879F9008CEFA0 /* CKKSAnalytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSAnalytics.h; sourceTree = ""; }; 479108B61EE879F9008CEFA0 /* CKKSAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSAnalytics.m; sourceTree = ""; }; 47922D171FAA65120008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecDbKeychainSerializedAKSWrappedKey.proto; sourceTree = ""; }; @@ -11995,6 +12077,7 @@ 48776C7C1DA5BB5F00CC09B9 /* SOSRingRecovery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSRingRecovery.m; sourceTree = ""; }; 48776C7D1DA5BB5F00CC09B9 /* SOSRingRecovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSRingRecovery.h; sourceTree = ""; }; 48776C801DA5BC0E00CC09B9 /* SOSAccountRecovery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSAccountRecovery.m; sourceTree = ""; }; + 487A65F3245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-68-fullPeerInfoIntegrity.m"; sourceTree = ""; }; 48AC7B5C232B1A1700F02B6F /* SOSIntervalEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSIntervalEvent.h; sourceTree = ""; }; 48AC7B71232B1A7000F02B6F /* SOSIntervalEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSIntervalEvent.m; sourceTree = ""; }; 48C2F9321E4BCFC30093D70C /* accountCirclesViewsPrint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = accountCirclesViewsPrint.m; sourceTree = ""; }; @@ -12186,9 +12269,10 @@ 5EBE247A1B00CCAE0007DB0E /* secacltests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secacltests; sourceTree = BUILT_PRODUCTS_DIR; }; 5EBE247C1B00CCAE0007DB0E /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 5F00F95A230614A200B832E0 /* SecImportExportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecImportExportPriv.h; path = keychain/headers/SecImportExportPriv.h; sourceTree = ""; }; + 5F4C21FE2489C68900F0C425 /* simulatecrash_assert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = simulatecrash_assert.h; sourceTree = ""; }; 5F8494FF22DFB502008B3EFB /* SecTrustExceptionResetCount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecTrustExceptionResetCount.m; sourceTree = ""; }; 617570BA22C2D19E00EFBA37 /* Security.macOS.private.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = Security.macOS.private.modulemap; path = Modules/Security.macOS.private.modulemap; sourceTree = ""; }; - 6C02134C21F7ED16009D5C80 /* SecDbBackupTests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = SecDbBackupTests.plist; path = tests/SecDbBackupTests/SecDbBackupTests.plist; sourceTree = SOURCE_ROOT; }; + 61BDC97E242932A100A2ABD8 /* SecTranslocateEnumUtils.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SecTranslocateEnumUtils.hpp; sourceTree = ""; }; 6C02134D21F7ED16009D5C80 /* SecDbBackupTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SecDbBackupTests.m; path = tests/SecDbBackupTests/SecDbBackupTests.m; sourceTree = SOURCE_ROOT; }; 6C02134F21F7ED45009D5C80 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = Info.plist; path = tests/SecDbBackupTests/Info.plist; sourceTree = SOURCE_ROOT; }; 6C0B0C3D1E2537C6007F95E5 /* WirelessDiagnostics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WirelessDiagnostics.framework; path = System/Library/PrivateFrameworks/WirelessDiagnostics.framework; sourceTree = SDKROOT; }; @@ -12208,11 +12292,17 @@ 6C1260FA1F7D631D001B2EEC /* securityuploadd-ios.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "securityuploadd-ios.plist"; sourceTree = ""; }; 6C1520CD1DCCF57A00C85C6D /* secd.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = secd.8; sourceTree = ""; }; 6C1A29FC1F882788002312D8 /* SFAnalyticsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsTests.m; sourceTree = ""; }; - 6C2008EF220BB4B500674B3A /* Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = ""; }; + 6C2008EF220BB4B500674B3A /* SecDbBackupTests-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SecDbBackupTests-Entitlements.plist"; sourceTree = ""; }; + 6C2045EA2424BA7E00F9461D /* KeychainStasher */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = KeychainStasher; sourceTree = BUILT_PRODUCTS_DIR; }; + 6C2045F92424BCB800F9461D /* com.apple.security.KeychainStasher.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.KeychainStasher.plist; sourceTree = ""; }; 6C23F02C227A39E9009F6756 /* com.apple.securityd.sb */ = {isa = PBXFileReference; lastKnownFileType = text; name = com.apple.securityd.sb; path = securityd/etc/com.apple.securityd.sb; sourceTree = SOURCE_ROOT; }; + 6C2D463924C88A700015C3C9 /* LegacyAPICounts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LegacyAPICounts.h; sourceTree = ""; }; + 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LegacyAPICounts.m; sourceTree = ""; }; 6C34462F1E24F6BE00F9522B /* CKKSRateLimiterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSRateLimiterTests.m; sourceTree = ""; }; 6C39237921F13E4D00D018AD /* SecDbBackupTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecDbBackupTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6C4605B81F882B9B001421B6 /* KeychainAnalyticsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KeychainAnalyticsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 6C48D10D2423A2F3004AF950 /* KeychainStasher.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = KeychainStasher.entitlements; sourceTree = ""; }; + 6C48D10F2423A3C0004AF950 /* com.apple.security.KeychainStasher.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.security.KeychainStasher.sb; sourceTree = ""; }; 6C4AEF82218A09210012C5DA /* CheckV12DevEnabled.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckV12DevEnabled.h; sourceTree = ""; }; 6C4AEF83218A09210012C5DA /* CheckV12DevEnabled.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CheckV12DevEnabled.m; sourceTree = ""; }; 6C4AEF8A218A0A400012C5DA /* SecDbBackupManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbBackupManager.h; sourceTree = ""; }; @@ -12221,10 +12311,15 @@ 6C4AEF93218A124B0012C5DA /* SecDbKeychainMetadataKeyStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecDbKeychainMetadataKeyStore.m; sourceTree = ""; }; 6C4AEF9C218A16F80012C5DA /* SecAKSObjCWrappers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecAKSObjCWrappers.h; sourceTree = ""; }; 6C4AEF9D218A16F80012C5DA /* SecAKSObjCWrappers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecAKSObjCWrappers.m; sourceTree = ""; }; + 6C513A37244F007B00207D5E /* SecItemRateLimit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemRateLimit.h; sourceTree = ""; }; + 6C513A38244F007B00207D5E /* SecItemRateLimit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecItemRateLimit.m; sourceTree = ""; }; 6C5232D41E3C183F00330DB1 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/CloudKit.framework; sourceTree = DEVELOPER_DIR; }; + 6C54BE0C23F41497004716CB /* SystemEntitlements.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SystemEntitlements.h; sourceTree = ""; }; 6C588D791EAA149F00D7E322 /* RateLimiterTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RateLimiterTests.m; sourceTree = ""; }; 6C5B101B1F91613E009B091E /* supdctl-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "supdctl-Entitlements.plist"; sourceTree = ""; }; 6C5B10211F9164F5009B091E /* securityuploadd.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = securityuploadd.8; sourceTree = ""; }; + 6C5D62A5221B6E3F00AF79DC /* secdxctests-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "secdxctests-entitlements.plist"; sourceTree = ""; }; + 6C6579FC2394878700701C8B /* SecDbBackupTestsBase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecDbBackupTestsBase.m; sourceTree = ""; }; 6C69517C1F758E1000F68F91 /* supdProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = supdProtocol.h; sourceTree = ""; }; 6C69517D1F758E1000F68F91 /* supd.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = supd.h; sourceTree = ""; }; 6C69517E1F758E1000F68F91 /* supd.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = supd.m; sourceTree = ""; }; @@ -12233,16 +12328,23 @@ 6C69518D1F75A7DB00F68F91 /* SFAnalyticsSQLiteStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsSQLiteStore.m; sourceTree = ""; }; 6C69518E1F75A7DC00F68F91 /* SFAnalyticsSQLiteStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsSQLiteStore.h; sourceTree = ""; }; 6C69518F1F75A8C100F68F91 /* SFAnalyticsDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsDefines.h; sourceTree = ""; }; + 6C6AF178221A03930091CE0A /* SecDbKeychainSerializedMetadataKey.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecDbKeychainSerializedMetadataKey.proto; sourceTree = ""; }; + 6C6AF17D221A06F70091CE0A /* SecDbKeychainSerializedMetadataKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbKeychainSerializedMetadataKey.h; sourceTree = ""; }; + 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecDbKeychainSerializedMetadataKey.m; sourceTree = ""; }; 6C70D8D420EB02B700AB6FAF /* TPPBPolicyCategoriesByView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPPBPolicyCategoriesByView.m; sourceTree = ""; }; 6C70D8D520EBDE4500AB6FAF /* TPPBPolicyRedaction.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = TPPBPolicyRedaction.proto; sourceTree = ""; }; 6C70D8DD20EBDFD600AB6FAF /* TPPBPolicyRedaction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPPBPolicyRedaction.m; sourceTree = ""; }; 6C70D8DE20EBDFD700AB6FAF /* TPPBPolicyRedaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPPBPolicyRedaction.h; sourceTree = ""; }; + 6C755603242121F000025D78 /* keychainstasherinterface.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = keychainstasherinterface.m; sourceTree = ""; }; + 6C755604242121F000025D78 /* keychainstasherinterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = keychainstasherinterface.h; sourceTree = ""; }; 6C758CB01F8826100075BD78 /* SupdTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SupdTests.m; sourceTree = ""; }; 6C758CB21F8826100075BD78 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6C7BB0032006B4EE004D1B6B /* SOSAnalytics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SOSAnalytics.m; path = Analytics/Clients/SOSAnalytics.m; sourceTree = SOURCE_ROOT; }; 6C7BB0042006B4EF004D1B6B /* SOSAnalytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SOSAnalytics.h; path = Analytics/Clients/SOSAnalytics.h; sourceTree = SOURCE_ROOT; }; + 6C7BE2E723C3DD64003BB2CA /* securitytool_bridge */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = securitytool_bridge; sourceTree = BUILT_PRODUCTS_DIR; }; 6C814A4A2050B4B600CB391B /* LocalKeychainAnalytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalKeychainAnalytics.h; sourceTree = ""; }; 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LocalKeychainAnalytics.m; sourceTree = ""; }; + 6C84E3C723ECBC84003C9710 /* KeychainAppClipTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainAppClipTests.m; sourceTree = ""; }; 6C860C741F4F63AD004100A1 /* SOSEnsureBackup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSEnsureBackup.h; sourceTree = ""; }; 6C860C7A1F4F63DB004100A1 /* SOSEnsureBackup.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSEnsureBackup.m; sourceTree = ""; }; 6C880FBE21C334FB00D38D66 /* SecDbBackupBagIdentity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbBackupBagIdentity.h; sourceTree = ""; }; @@ -12257,16 +12359,24 @@ 6C880FC721C334FE00D38D66 /* SecDbBackupRecoverySet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbBackupRecoverySet.h; sourceTree = ""; }; 6C8CE6BB1FA248B50032ADF0 /* SFAnalyticsActivityTracker+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFAnalyticsActivityTracker+Internal.h"; sourceTree = ""; }; 6C8CE6C31FA24A670032ADF0 /* SFAnalyticsSampler+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFAnalyticsSampler+Internal.h"; sourceTree = ""; }; + 6C915BE3242E14BC00DBDAFB /* SecDbInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbInternal.h; sourceTree = ""; }; + 6C963281242A279B00C53CE2 /* stashtester */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = stashtester; sourceTree = BUILT_PRODUCTS_DIR; }; + 6C963283242A279B00C53CE2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6C963289242A27F300C53CE2 /* stashtester.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = stashtester.entitlements; sourceTree = ""; }; 6C9791C421C17D060074C609 /* SecDbBackupManager_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbBackupManager_Internal.h; sourceTree = ""; }; - 6C9808611E788AEB00E70590 /* CKKSCloudKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CKKSCloudKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 6C98089D1E788AFD00E70590 /* CKKSCloudKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CKKSCloudKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 6C997869242362EC008C498D /* KeychainStasherProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainStasherProtocol.h; sourceTree = ""; }; + 6C99786A242362EC008C498D /* KeychainStasher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainStasher.h; sourceTree = ""; }; + 6C99786B242362EC008C498D /* KeychainStasher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainStasher.m; sourceTree = ""; }; + 6C99786D242362EC008C498D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6C99786F242362EC008C498D /* KeychainStasher-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KeychainStasher-Info.plist"; sourceTree = ""; }; + 6C997879242364E5008C498D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.16.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 6C99787C242364FB008C498D /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.16.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; 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 = ""; }; 6CA2B9431E9F9F5700C43444 /* RateLimiter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RateLimiter.h; sourceTree = ""; }; 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 = ""; }; 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 = ""; }; - 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "KeychainEntitledTestRunner-Entitlements.plist"; sourceTree = ""; }; + 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = KeychainEntitledTestRunner.entitlements; sourceTree = ""; }; 6CB5F47A1E402E5700DBF3F0 /* KeychainEntitledTestRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeychainEntitledTestRunner.m; sourceTree = ""; }; 6CB6CC022198D4BC0080AD6F /* SecDbBackupRecoverySet.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecDbBackupRecoverySet.proto; sourceTree = ""; }; 6CB96BB41F966E0C00E11457 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; @@ -12278,7 +12388,8 @@ 6CC952421FB4C5CA0051A823 /* SFAnalytics+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SFAnalytics+Internal.h"; sourceTree = ""; }; 6CCDF7841E3C25FA003F2555 /* KeychainEntitledTestRunner */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = KeychainEntitledTestRunner; sourceTree = BUILT_PRODUCTS_DIR; }; 6CCDF78B1E3C26BC003F2555 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/MacOSX.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - 6CCDF7911E3C2D69003F2555 /* CKKSCloudKitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSCloudKitTests.m; sourceTree = ""; }; + 6CD224E7239493E8001B70FD /* SecDbBackupTestsBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbBackupTestsBase.h; sourceTree = ""; }; + 6CD8412B23F5D871003DDF34 /* KeychainBackupTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainBackupTests.m; sourceTree = ""; }; 6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsMultiSampler.m; sourceTree = ""; }; 6CDB5FF31FA78CB500410924 /* SFAnalyticsMultiSampler+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SFAnalyticsMultiSampler+Internal.h"; sourceTree = ""; }; 6CDB5FF41FA78CB500410924 /* SFAnalyticsMultiSampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsMultiSampler.h; sourceTree = ""; }; @@ -12286,6 +12397,9 @@ 6CDF8DE51F95562B00140B54 /* SFAnalyticsSampler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsSampler.h; sourceTree = ""; }; 6CDF8DE61F95562B00140B54 /* SFAnalyticsSampler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsSampler.m; sourceTree = ""; }; 6CE22D6F1E49206600974785 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.0.Internal.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 6CF1B5C5245077E400FD8CC4 /* SecItemRateLimit_tests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemRateLimit_tests.h; sourceTree = ""; }; + 6CF33CA2238714C900D1E75D /* bats_utd_plist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bats_utd_plist.h; sourceTree = ""; }; + 6CF33CA4238714C900D1E75D /* PreprocessPlist.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = PreprocessPlist.sh; sourceTree = ""; }; 6CF4A0B41E45488B00ECD7B5 /* KeychainEntitledTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KeychainEntitledTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6CF4A0B61E45488B00ECD7B5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 6CF4A0B71E45488B00ECD7B5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -12293,15 +12407,7 @@ 6CF4A0BC1E45488B00ECD7B5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 6CF4A0BD1E45488B00ECD7B5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 6CF4A0BF1E45488B00ECD7B5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 6CF4A0C41E45488B00ECD7B5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6CF4A0E01E4549F200ECD7B5 /* KeychainEntitledTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KeychainEntitledTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6CF4A0E31E4549F200ECD7B5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6CF4A0E51E4549F200ECD7B5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6CF4A0E61E4549F300ECD7B5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6CF4A0E81E4549F300ECD7B5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - 6CF4A0E91E4549F300ECD7B5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; - 6CF4A0EE1E4549F300ECD7B5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 6CF4A0F31E4549F300ECD7B5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6CF4A0C41E45488B00ECD7B5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 6CFDC4561F907E1D00646DBB /* libprequelite.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libprequelite.tbd; path = usr/lib/libprequelite.tbd; sourceTree = SDKROOT; }; 7221843E1EC6782A004C7BED /* sec_action.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sec_action.c; sourceTree = ""; }; 7221843F1EC6782A004C7BED /* sec_action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sec_action.h; sourceTree = ""; }; @@ -12336,6 +12442,8 @@ 8ED6F6C8110904E300D2B368 /* SecPBKDF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPBKDF.h; sourceTree = ""; }; A6B1BA78207BD9D400F1E099 /* notarization.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = notarization.cpp; sourceTree = ""; }; A6B1BA79207BD9D400F1E099 /* notarization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = notarization.h; sourceTree = ""; }; + A6BF3B3123EB94A7009AF079 /* entitlements.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = entitlements.h; sourceTree = ""; }; + A6BF3B3223EB94A7009AF079 /* entitlements.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = entitlements.c; sourceTree = ""; }; AA0DA47821E8189D009F1C74 /* example1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = example1.json; path = protocol/test_data/example1.json; sourceTree = ""; }; AA0DA47921E8189E009F1C74 /* builtins.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = builtins.json; path = protocol/test_data/builtins.json; sourceTree = ""; }; AA44E0B3202E3451001EA371 /* SecProtocolTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SecProtocolTest.m; path = protocol/SecProtocolTest.m; sourceTree = ""; }; @@ -12381,7 +12489,7 @@ BE55C77A2044D0C80045863D /* TrustedPeersHelper-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TrustedPeersHelper-Bridging-Header.h"; sourceTree = ""; }; BE55C77B2044D0C90045863D /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; BE55C77D2044D7E60045863D /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; - BE6215BD1DB6E69100961E15 /* si-84-sectrust-allowlist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-84-sectrust-allowlist.m"; sourceTree = ""; }; + BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ca_revocation_additions.m; sourceTree = ""; }; BE64A7FD22AF0109001209F3 /* trusted_cert_ssl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trusted_cert_ssl.h; sourceTree = ""; }; BE64A7FE22AF010A001209F3 /* trusted_cert_ssl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = trusted_cert_ssl.m; sourceTree = ""; }; BE7089911F9AA027001ACC20 /* TPPBVoucher.proto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.protobuf; path = TPPBVoucher.proto; sourceTree = ""; }; @@ -12400,11 +12508,9 @@ BE7089DD1FA40B93001ACC20 /* TPPBPeerPermanentInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPPBPeerPermanentInfo.h; sourceTree = ""; }; BE7089DE1FA40B95001ACC20 /* TPPBPeerPermanentInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPPBPeerPermanentInfo.m; sourceTree = ""; }; BE72782A209D27C800F0DA77 /* TPKeyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPKeyTests.m; sourceTree = ""; }; - BE8351D41EC0EEDD00ACD5FD /* framework_requiring_modern_objc_runtime.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = framework_requiring_modern_objc_runtime.xcconfig; path = xcconfig/framework_requiring_modern_objc_runtime.xcconfig; sourceTree = ""; }; + BE7B8E112415579800E1CF4F /* SecSharedCredential.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecSharedCredential.m; sourceTree = ""; }; BE8ABDD71DC2DD9100EC2D58 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; BE92249D204F203C0052E828 /* TrustedPeersHelper.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = TrustedPeersHelper.xcdatamodel; sourceTree = ""; }; - BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "si-88-sectrust-valid-data"; sourceTree = ""; }; - BE9B8B49202BB4A10081EF87 /* si-88-sectrust-valid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "si-88-sectrust-valid.m"; path = "OSX/shared_regressions/si-88-sectrust-valid.m"; sourceTree = SOURCE_ROOT; }; BE9F4F8B2072D881004A52C2 /* Cuttlefish.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cuttlefish.pb.swift; sourceTree = ""; }; BE9F8D0F206C099800B53D16 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; BE9F8D11206C121400B53D16 /* Decrypter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Decrypter.swift; sourceTree = ""; }; @@ -12517,6 +12623,8 @@ D41257ED1E941D5B00781F23 /* SecTrustOSXEntryPoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustOSXEntryPoints.h; path = trust/trustd/macOS/SecTrustOSXEntryPoints.h; sourceTree = SOURCE_ROOT; }; D41257EE1E941DA800781F23 /* com.apple.trustd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.trustd.plist; sourceTree = ""; }; D41D36701EB14D87007FA978 /* libDiagnosticMessagesClient.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libDiagnosticMessagesClient.tbd; path = usr/lib/libDiagnosticMessagesClient.tbd; sourceTree = SDKROOT; }; + D423114223725F9F000E470A /* SMIMEPolicyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SMIMEPolicyTests.m; path = tests/TrustTests/EvaluationTests/SMIMEPolicyTests.m; sourceTree = ""; }; + D4231147237261F7000E470A /* SMIMEPolicyTests-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "SMIMEPolicyTests-data"; path = "tests/TrustTests/TestData/SMIMEPolicyTests-data"; sourceTree = ""; }; D42C838721158B3F008D3D83 /* cmsreclist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cmsreclist.h; path = libsecurity_smime/lib/cmsreclist.h; sourceTree = SOURCE_ROOT; }; D42C838821158B40008D3D83 /* SecAsn1Item.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SecAsn1Item.c; path = libsecurity_smime/lib/SecAsn1Item.c; sourceTree = SOURCE_ROOT; }; D42C8390211590BC008D3D83 /* CMSDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CMSDecoder.cpp; path = OSX/libsecurity_cms/lib/CMSDecoder.cpp; sourceTree = ""; }; @@ -12528,6 +12636,7 @@ D42C83A221159569008D3D83 /* cms-trust-settings-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "cms-trust-settings-test.c"; path = "OSX/libsecurity_cms/regressions/cms-trust-settings-test.c"; sourceTree = ""; }; D42C83A321159569008D3D83 /* cms-trust-settings-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cms-trust-settings-test.h"; path = "OSX/libsecurity_cms/regressions/cms-trust-settings-test.h"; sourceTree = ""; }; D42C83A621163866008D3D83 /* cert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cert.h; path = libsecurity_smime/lib/cert.h; sourceTree = SOURCE_ROOT; }; + D42D044124733BEA004E7AA2 /* com.apple.securityuploadd.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.securityuploadd.sb; sourceTree = ""; }; D437185C211671A300EA350A /* cms-01-basic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "cms-01-basic.c"; path = "OSX/libsecurity_smime/regressions/cms-01-basic.c"; sourceTree = ""; }; D437185D211671A400EA350A /* smime-cms-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "smime-cms-test.c"; path = "OSX/libsecurity_smime/regressions/smime-cms-test.c"; sourceTree = ""; }; D437185E211671A400EA350A /* cms-01-basic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cms-01-basic.h"; path = "OSX/libsecurity_smime/regressions/cms-01-basic.h"; sourceTree = ""; }; @@ -12649,7 +12758,6 @@ D458C4C0214E19FB0043D982 /* TrustInterfaceTests_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TrustInterfaceTests_data.h; path = tests/TrustTests/FrameworkTests/TrustInterfaceTests_data.h; sourceTree = ""; }; D458C4C5214E1A400043D982 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = tests/TrustTests/TestRunners/Assets.xcassets; sourceTree = ""; }; D458C4C6214E1A400043D982 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = tests/TrustTests/TestRunners/main.m; sourceTree = ""; }; - D458C4C7214E1A400043D982 /* Base.lproj */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Base.lproj; path = tests/TrustTests/TestRunners/Base.lproj; sourceTree = ""; }; D458C4C8214E1A410043D982 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = tests/TrustTests/TestRunners/AppDelegate.h; sourceTree = ""; }; D458C4C9214E1A410043D982 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ViewController.h; path = tests/TrustTests/TestRunners/ViewController.h; sourceTree = ""; }; D458C4CA214E1A420043D982 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = tests/TrustTests/TestRunners/AppDelegate.m; sourceTree = ""; }; @@ -12665,13 +12773,14 @@ D458C513214E27620043D982 /* PolicyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PolicyTests.m; path = tests/TrustTests/EvaluationTests/PolicyTests.m; sourceTree = ""; }; D458C51B214E2CFF0043D982 /* si-20-sectrust-policies-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-20-sectrust-policies-data"; path = "OSX/shared_regressions/si-20-sectrust-policies-data"; sourceTree = ""; }; D458C51E214E2E0C0043D982 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Main.storyboard; path = tests/TrustTests/TestRunners/Main.storyboard; sourceTree = ""; }; + D458DAC22375FEA300E5890E /* TrustSettingsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TrustSettingsTests.m; path = tests/TrustTests/EvaluationTests/TrustSettingsTests.m; sourceTree = ""; }; + D458DAC52375FEE900E5890E /* TrustSettingsTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TrustSettingsTests_data.h; path = tests/TrustTests/EvaluationTests/TrustSettingsTests_data.h; sourceTree = ""; }; D46246911F9AE2E400D63882 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/security_libDER/libDER.a; sourceTree = SDKROOT; }; D46246A21F9AE49E00D63882 /* oids.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oids.h; path = trust/headers/oids.h; sourceTree = ""; }; D46246A91F9AE6C900D63882 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/security_libDER/libDER.a; sourceTree = SDKROOT; }; D46246AF1F9AE73F00D63882 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/security_libDER/libDER.a; sourceTree = SDKROOT; }; D46246C31F9AEA5200D63882 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/security_libDER/libDER.a; sourceTree = SDKROOT; }; D46246CE1F9AEAE300D63882 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = usr/local/lib/security_libDER/libDER.a; sourceTree = SDKROOT; }; - D46513072097954B005D93FE /* si-23-sectrust-ocsp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "si-23-sectrust-ocsp.h"; sourceTree = ""; }; D47079F221128C46005BCFDA /* SecCMS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecCMS.h; path = CMS/SecCMS.h; sourceTree = ""; }; D47079F9211355B3005BCFDA /* CMSEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMSEncoder.h; path = CMS/CMSEncoder.h; sourceTree = ""; }; D4707A0521136E69005BCFDA /* TrustTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TrustTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -12683,14 +12792,25 @@ D4707A282113ECA0005BCFDA /* SecCmsMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsMessage.h; path = CMS/SecCmsMessage.h; sourceTree = ""; }; D4707A2B2114B31A005BCFDA /* SecCmsContentInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsContentInfo.h; path = CMS/SecCmsContentInfo.h; sourceTree = ""; }; D4707A2E2114C30A005BCFDA /* SecCmsDigestContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDigestContext.h; path = CMS/SecCmsDigestContext.h; sourceTree = ""; }; + D477CB5B237B6E0E00C02355 /* PersonalizationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PersonalizationTests.m; path = tests/TrustTests/DaemonTests/PersonalizationTests.m; sourceTree = ""; }; + D477CB69237CBA2C00C02355 /* TrustDaemonTestCase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TrustDaemonTestCase.m; path = tests/TrustTests/DaemonTests/TrustDaemonTestCase.m; sourceTree = ""; }; + D477CB6D237CBACD00C02355 /* TrustDaemonTestCase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TrustDaemonTestCase.h; path = tests/TrustTests/DaemonTests/TrustDaemonTestCase.h; sourceTree = ""; }; D477CB76237E453C00C02355 /* si-88-sectrust-valid-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-88-sectrust-valid-data"; path = "SecurityTests/si-88-sectrust-valid-data"; sourceTree = ""; }; D477CB7A237E4BD700C02355 /* ExceptionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ExceptionTests.m; path = tests/TrustTests/EvaluationTests/ExceptionTests.m; sourceTree = ""; }; D477CB7D237F321400C02355 /* ExceptionTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ExceptionTests_data.h; path = tests/TrustTests/EvaluationTests/ExceptionTests_data.h; sourceTree = ""; }; + D477CB81237F692400C02355 /* RevocationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RevocationTests.m; path = tests/TrustTests/EvaluationTests/RevocationTests.m; sourceTree = ""; }; + D477CB85237F6A0700C02355 /* RevocationTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RevocationTests_data.h; path = tests/TrustTests/EvaluationTests/RevocationTests_data.h; sourceTree = ""; }; + D477CB86237F8B2F00C02355 /* CAIssuerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CAIssuerTests.m; path = tests/TrustTests/EvaluationTests/CAIssuerTests.m; sourceTree = ""; }; + D477CB89237F8CB300C02355 /* CAIssuerTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CAIssuerTests_data.h; path = tests/TrustTests/EvaluationTests/CAIssuerTests_data.h; sourceTree = ""; }; + D477CB8A237F8DBB00C02355 /* AllowlistBlocklistTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AllowlistBlocklistTests.m; path = tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m; sourceTree = ""; }; + D477CB8D237F8EB200C02355 /* AllowlistBlocklistTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AllowlistBlocklistTests_data.h; path = tests/TrustTests/EvaluationTests/AllowlistBlocklistTests_data.h; sourceTree = ""; }; + D477CB8E237F975500C02355 /* ValidTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ValidTests.m; path = tests/TrustTests/EvaluationTests/ValidTests.m; sourceTree = ""; }; D479F6E01F980F8F00388D28 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = en.lproj/Trust.strings; sourceTree = ""; }; + D47A085B2486EC1A000F2C49 /* AppleExternalRootCertificates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleExternalRootCertificates.h; sourceTree = ""; }; + D47A55892466100A0039285D /* MSUDataAccessor.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MSUDataAccessor.framework; path = System/Library/PrivateFrameworks/MSUDataAccessor.framework; sourceTree = SDKROOT; }; D47AB2CA2356AD72005A3801 /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/Frameworks/Network.framework; sourceTree = SDKROOT; }; D47C56AB1DCA831C00E18518 /* lib_ios_x64.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = lib_ios_x64.xcconfig; path = xcconfig/lib_ios_x64.xcconfig; sourceTree = ""; }; D47C56AF1DCA841D00E18518 /* lib_ios_x64_shim.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = lib_ios_x64_shim.xcconfig; path = xcconfig/lib_ios_x64_shim.xcconfig; sourceTree = ""; }; - D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = all_arches.xcconfig; path = xcconfig/all_arches.xcconfig; sourceTree = ""; }; D47CA65C1EB036450038E2BB /* libMobileGestalt.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libMobileGestalt.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.0.Internal.sdk/usr/lib/libMobileGestalt.dylib; sourceTree = DEVELOPER_DIR; }; D47DCCB423427C7D00B80E37 /* md.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = md.m; sourceTree = ""; }; D47DCCB723427C8D00B80E37 /* md.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = md.h; sourceTree = ""; }; @@ -12701,10 +12821,6 @@ D4911167209558900066A1E4 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; D4961BBD2079423300F16DA7 /* TrustURLSessionDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TrustURLSessionDelegate.m; sourceTree = ""; }; D4961BC52079426000F16DA7 /* TrustURLSessionDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TrustURLSessionDelegate.h; sourceTree = ""; }; - D49A370023873A570065719F /* RevocationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RevocationTests.m; path = tests/TrustTests/EvaluationTests/RevocationTests.m; sourceTree = ""; }; - D49A370223873A570065719F /* RevocationTests_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RevocationTests_data.h; path = tests/TrustTests/EvaluationTests/RevocationTests_data.h; sourceTree = ""; }; - D49A370523873BD30065719F /* TrustDaemonTestCase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TrustDaemonTestCase.m; path = tests/TrustTests/DaemonTests/TrustDaemonTestCase.m; sourceTree = ""; }; - D49A370823873BF10065719F /* TrustDaemonTestCase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TrustDaemonTestCase.h; path = tests/TrustTests/DaemonTests/TrustDaemonTestCase.h; sourceTree = ""; }; D49A370B23877ECC0065719F /* OCSPCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OCSPCacheTests.m; path = tests/TrustTests/DaemonTests/OCSPCacheTests.m; sourceTree = ""; }; D4A0F8BA211E69CB00443CA1 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = tests/TrustTests/Info.plist; sourceTree = ""; }; D4A0F8BB211E69CB00443CA1 /* TestMacroConversions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestMacroConversions.h; path = tests/TrustTests/TestMacroConversions.h; sourceTree = ""; }; @@ -12800,6 +12916,7 @@ D4FD4222217D7B48002B7EE2 /* PathScoringTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PathScoringTests_data.h; path = tests/TrustTests/EvaluationTests/PathScoringTests_data.h; sourceTree = ""; }; D4FD4223217D7BE3002B7EE2 /* libarchive.2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libarchive.2.tbd; path = usr/lib/libarchive.2.tbd; sourceTree = SDKROOT; }; DA2C402D2189302E005F1CC3 /* mach_notify.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = mach_notify.defs; sourceTree = ""; }; + DA2F591523A32BB400C30285 /* SoftLinking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SoftLinking.framework; path = System/Library/PrivateFrameworks/SoftLinking.framework; sourceTree = SDKROOT; }; DA30D6761DF8C8FB00EC6B43 /* KeychainSyncAccountUpdater.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KeychainSyncAccountUpdater.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; DA30D6781DF8C8FB00EC6B43 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DA30D6831DF8CA4100EC6B43 /* KeychainSyncAccountUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeychainSyncAccountUpdater.h; sourceTree = ""; }; @@ -12844,6 +12961,8 @@ DC05037621409A4000A8EDB7 /* OCMockUmbrella.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OCMockUmbrella.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DC05037821409A4100A8EDB7 /* OCMockUmbrella.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OCMockUmbrella.h; sourceTree = ""; }; DC05037921409A4100A8EDB7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DC061A6E246211DD0026ADB3 /* CKKSLocalResetOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSLocalResetOperation.h; sourceTree = ""; }; + DC061A70246211DE0026ADB3 /* CKKSLocalResetOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSLocalResetOperation.m; sourceTree = ""; }; DC07090222936BCC002711B9 /* OctagonTests+ErrorHandling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+ErrorHandling.swift"; sourceTree = ""; }; DC08D1C21E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CloudKitKeychainSyncingMockXCTest.h; sourceTree = ""; }; DC08D1C31E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudKitKeychainSyncingMockXCTest.m; sourceTree = ""; }; @@ -13418,7 +13537,6 @@ DC1787241D778FDE00B50D50 /* SecManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecManifest.h; path = OSX/libsecurity_manifest/lib/SecManifest.h; sourceTree = ""; }; DC1787251D778FDE00B50D50 /* SecureDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureDownloadInternal.h; path = OSX/libsecurity_manifest/lib/SecureDownloadInternal.h; sourceTree = ""; }; DC1787281D77903700B50D50 /* SecAccessPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAccessPriv.h; path = OSX/libsecurity_keychain/lib/SecAccessPriv.h; sourceTree = ""; }; - DC1787291D77903700B50D50 /* SecCertificateBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateBundle.h; path = OSX/libsecurity_keychain/lib/SecCertificateBundle.h; sourceTree = ""; }; DC17872A1D77903700B50D50 /* SecFDERecoveryAsymmetricCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecFDERecoveryAsymmetricCrypto.h; path = OSX/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h; sourceTree = ""; }; DC17872B1D77903700B50D50 /* SecIdentitySearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentitySearchPriv.h; path = OSX/libsecurity_keychain/lib/SecIdentitySearchPriv.h; sourceTree = ""; }; DC17872C1D77903700B50D50 /* SecKeychainItemExtendedAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainItemExtendedAttributes.h; path = OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h; sourceTree = ""; }; @@ -13449,7 +13567,6 @@ DC1787671D77911D00B50D50 /* osKeyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = osKeyTemplates.h; path = OSX/libsecurity_asn1/lib/osKeyTemplates.h; sourceTree = ""; }; DC1787681D77911D00B50D50 /* secasn1t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = secasn1t.h; path = OSX/libsecurity_asn1/lib/secasn1t.h; sourceTree = ""; }; DC1787691D77911D00B50D50 /* X509Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = X509Templates.h; path = OSX/libsecurity_asn1/lib/X509Templates.h; sourceTree = ""; }; - DC1787731D77915500B50D50 /* SecBreadcrumb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecBreadcrumb.h; path = OSX/Breadcrumb/SecBreadcrumb.h; sourceTree = SOURCE_ROOT; }; DC1789041D77980500B50D50 /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DC1789121D7798B300B50D50 /* libDiagnosticMessagesClient.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libDiagnosticMessagesClient.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/lib/libDiagnosticMessagesClient.dylib; sourceTree = DEVELOPER_DIR; }; DC1789141D77997F00B50D50 /* libOpenScriptingUtil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libOpenScriptingUtil.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/lib/libOpenScriptingUtil.dylib; sourceTree = DEVELOPER_DIR; }; @@ -13460,7 +13577,6 @@ DC1789221D7799A600B50D50 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; }; DC1789241D7799CD00B50D50 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; DC1789261D7799D300B50D50 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; }; - DC1789A01D779DEE00B50D50 /* SecBreadcrumb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SecBreadcrumb.c; path = OSX/Breadcrumb/SecBreadcrumb.c; sourceTree = ""; }; DC1789A41D779E3B00B50D50 /* dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dummy.cpp; path = OSX/lib/dummy.cpp; sourceTree = ""; }; DC178A0E1D77A1E700B50D50 /* cssm.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cssm.mdsinfo; path = OSX/libsecurity_cssm/mds/cssm.mdsinfo; sourceTree = ""; }; DC178A0F1D77A1E700B50D50 /* csp_capabilities.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = csp_capabilities.mdsinfo; path = OSX/libsecurity_apple_csp/mds/csp_capabilities.mdsinfo; sourceTree = ""; }; @@ -13482,7 +13598,6 @@ DC178A311D77A1F500B50D50 /* FDEPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = FDEPrefs.plist; path = OSX/lib/FDEPrefs.plist; sourceTree = ""; }; DC178A321D77A1F500B50D50 /* SecDebugErrorMessages.strings */ = {isa = PBXFileReference; explicitFileType = text.plist.strings; fileEncoding = 10; name = SecDebugErrorMessages.strings; path = derived_src/SecDebugErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; DC178A341D77A1F500B50D50 /* SecErrorMessages.strings */ = {isa = PBXFileReference; explicitFileType = text.plist.strings; fileEncoding = 10; name = SecErrorMessages.strings; path = derived_src/en.lproj/SecErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; - DC178A351D77A1F500B50D50 /* framework.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = framework.sb; path = OSX/lib/framework.sb; sourceTree = ""; }; DC178A391D77A1F500B50D50 /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = OSX/lib/en.lproj/InfoPlist.strings; sourceTree = ""; }; DC178A3A1D77A1F500B50D50 /* TimeStampingPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = TimeStampingPrefs.plist; path = OSX/lib/TimeStampingPrefs.plist; sourceTree = ""; }; DC178A3C1D77A1F500B50D50 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = OSX/lib/en.lproj/authorization.dfr.prompts.strings; sourceTree = ""; }; @@ -13528,7 +13643,6 @@ DC24B5681DA326B900330B48 /* rule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rule.h; path = OSX/authd/rule.h; sourceTree = ""; }; DC24B5691DA326B900330B48 /* server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = server.h; path = OSX/authd/server.h; sourceTree = ""; }; DC24B56A1DA326B900330B48 /* session.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = session.h; path = OSX/authd/session.h; sourceTree = ""; }; - DC24B5701DA3274000330B48 /* breadcrumb_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = breadcrumb_regressions.h; path = OSX/Breadcrumb/breadcrumb_regressions.h; sourceTree = ""; }; DC24B5711DA327A800330B48 /* KDAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KDAppDelegate.h; path = OSX/Keychain/KDAppDelegate.h; sourceTree = SOURCE_ROOT; }; DC24B5721DA327A800330B48 /* KDCirclePeer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KDCirclePeer.h; path = OSX/Keychain/KDCirclePeer.h; sourceTree = SOURCE_ROOT; }; DC24B5731DA327A800330B48 /* KDSecCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KDSecCircle.h; path = OSX/Keychain/KDSecCircle.h; sourceTree = SOURCE_ROOT; }; @@ -13563,6 +13677,8 @@ DC311E782124B8EF002F5EAE /* aks_real_witness.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = aks_real_witness.h; sourceTree = ""; }; DC311E792124B8EF002F5EAE /* aks_real_witness.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = aks_real_witness.c; sourceTree = ""; }; DC340C53208E7BAE004D7EEC /* swift_binary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = swift_binary.xcconfig; path = xcconfig/swift_binary.xcconfig; sourceTree = ""; }; + DC3412E5245780B9008ABD0A /* CKKSOperationDependencies.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSOperationDependencies.h; sourceTree = ""; }; + DC3412E6245780BA008ABD0A /* CKKSOperationDependencies.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSOperationDependencies.m; sourceTree = ""; }; DC3502B51E0208BE00BC0587 /* CKKSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CKKSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DC3502B71E0208BE00BC0587 /* CKKSTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSTests.m; sourceTree = ""; }; DC3502B91E0208BE00BC0587 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -13886,6 +14002,8 @@ DC6ACC401E81DF9400125DC5 /* server_endpoint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = server_endpoint.m; sourceTree = ""; }; DC6DE897213076C000C6B56D /* OTSOSUpgradeOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSOSUpgradeOperation.h; sourceTree = ""; }; DC6DE898213076C000C6B56D /* OTSOSUpgradeOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSOSUpgradeOperation.m; sourceTree = ""; }; + DC6E02122405DDC300C61335 /* OTModifyUserControllableViewStatusOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTModifyUserControllableViewStatusOperation.h; sourceTree = ""; }; + DC6E02132405DDC400C61335 /* OTModifyUserControllableViewStatusOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTModifyUserControllableViewStatusOperation.m; sourceTree = ""; }; DC7181062089172F00B2CB13 /* TrustedPeersHelper-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TrustedPeersHelper-entitlements.plist"; sourceTree = ""; }; DC71D8DD1D94CF3C0065FB93 /* lib_ios_shim.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = lib_ios_shim.xcconfig; path = xcconfig/lib_ios_shim.xcconfig; sourceTree = ""; }; DC72502D229600A800493D88 /* OctagonTests+Reset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+Reset.swift"; sourceTree = ""; }; @@ -13921,8 +14039,10 @@ DC844AEC1E81F315007AAB71 /* client_endpoint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = client_endpoint.m; sourceTree = ""; }; DC85687C2284E7850088D3EF /* OctagonTestMocks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OctagonTestMocks.swift; sourceTree = ""; }; DC85687F2284E79C0088D3EF /* OctagonEscrowRecoverer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OctagonEscrowRecoverer.h; sourceTree = ""; }; + DC86122B2408AC190092E93B /* CKKSTests+ItemSyncChoice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CKKSTests+ItemSyncChoice.m"; sourceTree = ""; }; DC8757F2218D2003000E65F1 /* OTRemovePeersOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTRemovePeersOperation.h; sourceTree = ""; }; DC8757F3218D2003000E65F1 /* OTRemovePeersOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTRemovePeersOperation.m; sourceTree = ""; }; + DC880F67243D4CC00059806D /* CKKSLogging.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSLogging.m; sourceTree = ""; }; DC8834081D8A218F00CE0ACA /* libASN1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libASN1.a; sourceTree = BUILT_PRODUCTS_DIR; }; DC88340A1D8A21AA00CE0ACA /* SecAsn1Coder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAsn1Coder.c; sourceTree = ""; }; DC88340C1D8A21AA00CE0ACA /* SecAsn1Templates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAsn1Templates.c; sourceTree = ""; }; @@ -13995,9 +14115,12 @@ DC90A4C621F279D4001300EB /* SecEscrowPendingRecord.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecEscrowPendingRecord.proto; sourceTree = ""; }; DC93F02722387A010072720A /* OTSOSUpdatePreapprovalsOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSOSUpdatePreapprovalsOperation.h; sourceTree = ""; }; DC93F02822387A010072720A /* OTSOSUpdatePreapprovalsOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSOSUpdatePreapprovalsOperation.m; sourceTree = ""; }; + DC947E812463831E005B8669 /* CKKSCheckKeyHierarchyOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSCheckKeyHierarchyOperation.h; sourceTree = ""; }; + DC947E832463831F005B8669 /* CKKSCheckKeyHierarchyOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSCheckKeyHierarchyOperation.m; sourceTree = ""; }; DC94BCC81F10448600E07CEB /* CloudKitCategories.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CloudKitCategories.h; sourceTree = ""; }; DC94BCC91F10448600E07CEB /* CloudKitCategories.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CloudKitCategories.m; sourceTree = ""; }; DC976C581E3AC5E50012A6DD /* PlatformFeatures.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = PlatformFeatures.xcconfig; path = xcconfig/PlatformFeatures.xcconfig; sourceTree = ""; }; + DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_UserSync.swift; sourceTree = ""; }; DC99B89220EACA470065B73B /* OctagonTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OctagonTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DC99B89320EACA480065B73B /* OctagonTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "OctagonTests-Info.plist"; sourceTree = ""; }; DC9A2C5E1EB3F556008FAC27 /* CKKSTests+Coalesce.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CKKSTests+Coalesce.m"; sourceTree = ""; }; @@ -14021,6 +14144,7 @@ DCA4D1F41E5520550056214F /* CKKSCurrentKeyPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSCurrentKeyPointer.m; sourceTree = ""; }; DCA4D2131E5684220056214F /* CKKSReencryptOutgoingItemsOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSReencryptOutgoingItemsOperation.h; sourceTree = ""; }; DCA4D2141E5684220056214F /* CKKSReencryptOutgoingItemsOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSReencryptOutgoingItemsOperation.m; sourceTree = ""; }; + DCA7F7EE23A44AA200927989 /* OctagonPolicyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OctagonPolicyTests.swift; sourceTree = ""; }; DCA9BC00221B721D00B4EB26 /* CKKSCloudKitClassDependencies.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSCloudKitClassDependencies.h; sourceTree = ""; }; DCA9BC01221B721E00B4EB26 /* CKKSCloudKitClassDependencies.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSCloudKitClassDependencies.m; sourceTree = ""; }; DCA9BC05221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSMockSOSPresentAdapter.h; sourceTree = ""; }; @@ -14228,7 +14352,6 @@ DCB342441D8A32A20054D16E /* SecBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecBase.cpp; sourceTree = ""; }; DCB342451D8A32A20054D16E /* SecBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecBridge.h; sourceTree = ""; }; DCB342461D8A32A20054D16E /* SecCertificate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificate.cpp; sourceTree = ""; }; - DCB342471D8A32A20054D16E /* SecCertificateBundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificateBundle.cpp; sourceTree = ""; }; DCB342491D8A32A20054D16E /* SecIdentity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecIdentity.cpp; sourceTree = ""; }; DCB3424A1D8A32A20054D16E /* SecIdentitySearch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecIdentitySearch.cpp; sourceTree = ""; }; DCB3424B1D8A32A20054D16E /* SecItemConstants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecItemConstants.c; sourceTree = ""; }; @@ -14279,7 +14402,6 @@ DCB342A51D8A32A20054D16E /* PolicyCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolicyCursor.h; sourceTree = ""; }; DCB342A61D8A32A20054D16E /* SecCFTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCFTypes.cpp; sourceTree = ""; }; DCB342A71D8A32A20054D16E /* SecCFTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCFTypes.h; sourceTree = ""; }; - DCB342A81D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainAddIToolsPassword.cpp; sourceTree = ""; }; DCB342AA1D8A32A20054D16E /* StorageManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = StorageManager.cpp; sourceTree = ""; }; DCB342AB1D8A32A20054D16E /* Trust.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Trust.cpp; sourceTree = ""; }; DCB342AC1D8A32A20054D16E /* Trust.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Trust.h; sourceTree = ""; }; @@ -14400,6 +14522,10 @@ DCB344711D8A35270054D16E /* si-33-keychain-backup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "si-33-keychain-backup.c"; path = "regressions/si-33-keychain-backup.c"; sourceTree = ""; }; DCB344721D8A35270054D16E /* si-34-one-true-keychain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "si-34-one-true-keychain.c"; path = "regressions/si-34-one-true-keychain.c"; sourceTree = ""; }; DCB41DF9216C3F8A00F219E0 /* tpctl-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "tpctl-entitlements.plist"; sourceTree = ""; }; + DCB5516A247F3DB50009A859 /* CKKSCreateCKZoneOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSCreateCKZoneOperation.h; sourceTree = ""; }; + DCB5516B247F3DB50009A859 /* CKKSCreateCKZoneOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSCreateCKZoneOperation.m; sourceTree = ""; }; + DCB55173247F48290009A859 /* CKKSDeleteCKZoneOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSDeleteCKZoneOperation.h; sourceTree = ""; }; + DCB55174247F48290009A859 /* CKKSDeleteCKZoneOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSDeleteCKZoneOperation.m; sourceTree = ""; }; DCB5D9391E4A9A3400BE22AB /* CKKSSynchronizeOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSSynchronizeOperation.h; sourceTree = ""; }; DCB5D93A1E4A9A3400BE22AB /* CKKSSynchronizeOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSSynchronizeOperation.m; sourceTree = ""; }; DCB946AD22FCB88400BE4490 /* OTDetermineHSA2AccountStatusOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTDetermineHSA2AccountStatusOperation.h; sourceTree = ""; }; @@ -14409,6 +14535,8 @@ DCB947592127534C00ED9272 /* OctagonTests+SOSUpgrade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+SOSUpgrade.swift"; sourceTree = ""; }; DCB9475B2127562100ED9272 /* OTSOSAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSOSAdapter.h; sourceTree = ""; }; DCB9475C2127562100ED9272 /* OTSOSAdapter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSOSAdapter.m; sourceTree = ""; }; + DCBA6F2824105399009A5187 /* CKKSTests+ForwardCompatibility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CKKSTests+ForwardCompatibility.m"; sourceTree = ""; }; + DCBDA460245A39A300B0938B /* com.apple.TrustedPeersHelper.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.TrustedPeersHelper.sb; sourceTree = ""; }; DCBDB3B01E57C67500B61300 /* CKKSKeychainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSKeychainView.h; sourceTree = ""; }; DCBDB3B11E57C67500B61300 /* CKKSKeychainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSKeychainView.m; sourceTree = ""; }; DCBDB3B91E57CA7A00B61300 /* CKKSViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSViewManager.h; sourceTree = ""; }; @@ -14420,8 +14548,12 @@ DCBF4AE321FFC9A800539F0A /* SecEscrowRequestTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecEscrowRequestTests.m; sourceTree = ""; }; DCBFF830222611A200C5C044 /* OTFetchCKKSKeysOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTFetchCKKSKeysOperation.h; sourceTree = ""; }; DCBFF831222611A200C5C044 /* OTFetchCKKSKeysOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTFetchCKKSKeysOperation.m; sourceTree = ""; }; + DCC03FA223FF521100A4DA3F /* TPSyncingPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TPSyncingPolicy.h; sourceTree = ""; }; + DCC03FA323FF521100A4DA3F /* TPSyncingPolicy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPSyncingPolicy.m; sourceTree = ""; }; DCC0800D1CFF7903005C35C8 /* CSSMOID.exp-in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "CSSMOID.exp-in"; sourceTree = ""; }; DCC1849220EEEC4400F3B26C /* security_framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = security_framework.xcconfig; path = xcconfig/security_framework.xcconfig; sourceTree = ""; }; + DCC40B0F2383786D00402CB9 /* CKKSStates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSStates.h; sourceTree = ""; }; + DCC40B102383786D00402CB9 /* CKKSStates.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSStates.m; sourceTree = ""; }; DCC5417F225C05170095D926 /* OTUploadNewCKKSTLKsOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTUploadNewCKKSTLKsOperation.h; sourceTree = ""; }; DCC54180225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTUploadNewCKKSTLKsOperation.m; sourceTree = ""; }; DCC5860220BF8A98005C7269 /* SecBase.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecBase.c; sourceTree = ""; }; @@ -14690,14 +14822,11 @@ DCC78DBD1D8085FC00865A7C /* si-21-sectrust-asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-21-sectrust-asr.c"; sourceTree = ""; }; DCC78DBE1D8085FC00865A7C /* si-22-sectrust-iap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-22-sectrust-iap.c"; sourceTree = ""; }; DCC78DBF1D8085FC00865A7C /* si-22-sectrust-iap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-22-sectrust-iap.h"; sourceTree = ""; }; - DCC78DC01D8085FC00865A7C /* si-23-sectrust-ocsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-23-sectrust-ocsp.c"; sourceTree = ""; }; DCC78DC11D8085FC00865A7C /* si-24-sectrust-digicert-malaysia.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-digicert-malaysia.c"; sourceTree = ""; }; DCC78DC21D8085FC00865A7C /* si-24-sectrust-diginotar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-diginotar.c"; sourceTree = ""; }; DCC78DC31D8085FC00865A7C /* si-24-sectrust-itms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-itms.c"; sourceTree = ""; }; DCC78DC51D8085FC00865A7C /* si-24-sectrust-passbook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-passbook.c"; sourceTree = ""; }; DCC78DC61D8085FC00865A7C /* si-26-sectrust-copyproperties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-26-sectrust-copyproperties.c"; sourceTree = ""; }; - DCC78DC81D8085FC00865A7C /* si-28-sectrustsettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-28-sectrustsettings.m"; sourceTree = ""; }; - DCC78DC91D8085FC00865A7C /* si-28-sectrustsettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-28-sectrustsettings.h"; sourceTree = ""; }; DCC78DCA1D8085FC00865A7C /* si-30-keychain-upgrade.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-30-keychain-upgrade.c"; sourceTree = ""; }; DCC78DCB1D8085FC00865A7C /* si-31-keychain-bad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-31-keychain-bad.c"; sourceTree = ""; }; DCC78DCC1D8085FC00865A7C /* si-31-keychain-unreadable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-31-keychain-unreadable.c"; sourceTree = ""; }; @@ -14729,24 +14858,12 @@ DCC78DE81D8085FC00865A7C /* si-65-cms-cert-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-65-cms-cert-policy.c"; sourceTree = ""; }; DCC78DE91D8085FC00865A7C /* signed-receipt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "signed-receipt.h"; sourceTree = ""; }; DCC78DEB1D8085FC00865A7C /* si-66-smime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-66-smime.c"; sourceTree = ""; }; - DCC78DEC1D8085FC00865A7C /* Global Trustee.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Global Trustee.cer.h"; sourceTree = ""; }; - DCC78DED1D8085FC00865A7C /* UTN-USERFirst-Hardware.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UTN-USERFirst-Hardware.cer.h"; sourceTree = ""; }; - DCC78DEE1D8085FC00865A7C /* addons.mozilla.org.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = addons.mozilla.org.cer.h; sourceTree = ""; }; - DCC78DEF1D8085FC00865A7C /* login.live.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.live.com.cer.h; sourceTree = ""; }; - DCC78DF01D8085FC00865A7C /* login.skype.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.skype.com.cer.h; sourceTree = ""; }; - DCC78DF11D8085FC00865A7C /* login.yahoo.com.1.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.1.cer.h; sourceTree = ""; }; - DCC78DF21D8085FC00865A7C /* login.yahoo.com.2.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.2.cer.h; sourceTree = ""; }; - DCC78DF31D8085FC00865A7C /* login.yahoo.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.cer.h; sourceTree = ""; }; - DCC78DF41D8085FC00865A7C /* mail.google.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mail.google.com.cer.h; sourceTree = ""; }; - DCC78DF51D8085FC00865A7C /* www.google.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = www.google.com.cer.h; sourceTree = ""; }; - DCC78DF71D8085FC00865A7C /* si-67-sectrust-blocklist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-67-sectrust-blocklist.c"; sourceTree = ""; }; DCC78DF81D8085FC00865A7C /* si-68-secmatchissuer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-68-secmatchissuer.c"; sourceTree = ""; }; DCC78DF91D8085FC00865A7C /* si-69-keydesc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-69-keydesc.c"; sourceTree = ""; }; DCC78DFA1D8085FC00865A7C /* si-70-sectrust-unified.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-70-sectrust-unified.c"; sourceTree = ""; }; DCC78DFB1D8085FC00865A7C /* si-71-mobile-store-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-71-mobile-store-policy.c"; sourceTree = ""; }; DCC78DFC1D8085FC00865A7C /* si-72-syncableitems.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-72-syncableitems.c"; sourceTree = ""; }; DCC78DFD1D8085FC00865A7C /* si-73-secpasswordgenerate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-73-secpasswordgenerate.c"; sourceTree = ""; }; - DCC78DFE1D8085FC00865A7C /* si-74-OTAPKISigner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-74-OTAPKISigner.c"; sourceTree = ""; }; DCC78DFF1D8085FC00865A7C /* si-76-shared-credentials.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-76-shared-credentials.c"; sourceTree = ""; }; DCC78E001D8085FC00865A7C /* si_77_SecAccessControl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = si_77_SecAccessControl.c; sourceTree = ""; }; DCC78E011D8085FC00865A7C /* si-78-query-attrs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-78-query-attrs.c"; sourceTree = ""; }; @@ -15181,6 +15298,7 @@ DCD7DD9D22B868C200161396 /* TPPBDispositionDuplicateMachineID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPPBDispositionDuplicateMachineID.h; sourceTree = ""; }; DCD7EE9B1F4F51D9007D9804 /* ios_tapi_hacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ios_tapi_hacks.h; sourceTree = ""; }; DCD8A1991E09EE0F00E4FA0A /* libSecureObjectSyncFramework.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecureObjectSyncFramework.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DCDACB5724A3F1AA0054080C /* com.apple.security.ckks.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.ckks.plist; sourceTree = ""; }; DCDCC7DD1D9B54DF006487E8 /* secd-202-recoverykey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-202-recoverykey.m"; sourceTree = ""; }; DCDCC7E41D9B551C006487E8 /* SOSAccountSync.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSAccountSync.m; sourceTree = ""; }; DCDCCB8D1DF7B8D4006E840E /* CKKSItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSItem.h; sourceTree = ""; }; @@ -15195,7 +15313,6 @@ DCE405C423A04A7F00C4343B /* OctagonTests+CKKSConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+CKKSConfiguration.swift"; sourceTree = ""; }; DCE4E6A41D7A37FA00AFB96E /* security2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = security2; sourceTree = BUILT_PRODUCTS_DIR; }; DCE4E6A71D7A38C000AFB96E /* security2.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = security2.1; sourceTree = ""; }; - DCE4E6D41D7A41E400AFB96E /* bc-10-knife-on-bread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "bc-10-knife-on-bread.m"; path = "OSX/Breadcrumb/bc-10-knife-on-bread.m"; sourceTree = ""; }; DCE4E6D71D7A420D00AFB96E /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = OSX/SecurityTestsOSX/main.m; sourceTree = ""; }; DCE4E6E71D7A427200AFB96E /* SecurityFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/SecurityFoundation.framework; sourceTree = DEVELOPER_DIR; }; DCE4E72E1D7A436300AFB96E /* si-82-sectrust-ct-logs.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "si-82-sectrust-ct-logs.plist"; path = "OSX/shared_regressions/si-82-sectrust-ct-logs.plist"; sourceTree = SOURCE_ROOT; }; @@ -15268,8 +15385,6 @@ DCEA5D541E2826DB0089CF55 /* CKKSSIV.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSSIV.m; sourceTree = ""; }; DCEA5D831E2F14810089CF55 /* OctagonAPSReceiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OctagonAPSReceiver.h; sourceTree = ""; }; DCEA5D841E2F14810089CF55 /* OctagonAPSReceiver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OctagonAPSReceiver.m; sourceTree = ""; }; - DCEA5D951E3014250089CF55 /* CKKSZone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSZone.h; sourceTree = ""; }; - DCEA5D961E3014250089CF55 /* CKKSZone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSZone.m; sourceTree = ""; }; DCEE1E851D93424D00DC0EB7 /* com.apple.securityd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.securityd.plist; path = OSX/sec/ipc/com.apple.securityd.plist; sourceTree = SOURCE_ROOT; }; DCF12671218A7579000124C6 /* OTLeaveCliqueOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTLeaveCliqueOperation.h; sourceTree = ""; }; DCF12672218A757A000124C6 /* OTLeaveCliqueOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTLeaveCliqueOperation.m; sourceTree = ""; }; @@ -15608,7 +15723,6 @@ DCFABF8D20081E2F001128B5 /* CKKSDeviceStateUploadTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSDeviceStateUploadTests.m; sourceTree = ""; }; DCFAEDC81D999851005187E4 /* SOSAccountGhost.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSAccountGhost.m; sourceTree = ""; }; DCFAEDC91D999851005187E4 /* SOSAccountGhost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSAccountGhost.h; sourceTree = ""; }; - DCFAEDD11D9998DD005187E4 /* secd-668-ghosts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-668-ghosts.m"; sourceTree = ""; }; DCFAEDD51D99A464005187E4 /* secd-36-ks-encrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-36-ks-encrypt.m"; sourceTree = ""; }; DCFB12C31E95A4C000510F5F /* CKKSAccountStateTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSAccountStateTracker.h; sourceTree = ""; }; DCFB12C41E95A4C000510F5F /* CKKSAccountStateTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSAccountStateTracker.m; sourceTree = ""; }; @@ -15704,7 +15818,6 @@ E7F4809D1C74E86D00390FDB /* KCAESGCMTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KCAESGCMTest.m; path = Tests/KCAESGCMTest.m; sourceTree = ""; }; E7F4826F1C74FDD100390FDB /* KCJoiningSessionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KCJoiningSessionTest.m; path = Tests/KCJoiningSessionTest.m; sourceTree = ""; }; E7F482A21C7544E600390FDB /* libctkclient_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkclient_test.a; path = ../../../../../usr/local/lib/libctkclient_test.a; sourceTree = ""; }; - E7F482A51C75453900390FDB /* libcoreauthd_test_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcoreauthd_test_client.a; path = ../../../../../usr/local/lib/libcoreauthd_test_client.a; sourceTree = ""; }; E7F482A91C7554F500390FDB /* NSError+KCCreationHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+KCCreationHelpers.m"; sourceTree = ""; }; E7F482AB1C7558F700390FDB /* KCJoiningAcceptSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KCJoiningAcceptSession.m; sourceTree = ""; }; E7FC30AB1332DE9000802946 /* MobileKeyBag.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileKeyBag.framework; path = System/Library/PrivateFrameworks/MobileKeyBag.framework; sourceTree = SDKROOT; }; @@ -15763,6 +15876,10 @@ EB433A1E1CC3242C00A7EACE /* secitemstresstest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = secitemstresstest.m; path = secitemstresstest/secitemstresstest.m; sourceTree = ""; }; EB433A281CC3243600A7EACE /* secitemstresstest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secitemstresstest; sourceTree = BUILT_PRODUCTS_DIR; }; EB433A2D1CC325E900A7EACE /* secitemstresstest.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = secitemstresstest.entitlements; path = secitemstresstest/secitemstresstest.entitlements; sourceTree = ""; }; + EB45ED2E24749DE9008A1F6F /* gen_test_plist.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gen_test_plist.py; path = tests/TrustTests/gen_test_plist.py; sourceTree = ""; }; + EB45ED3024749E63008A1F6F /* gen_test_plist.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = gen_test_plist.py; sourceTree = ""; }; + EB45ED3124749ECC008A1F6F /* OTTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "OTTests-Info.plist"; sourceTree = ""; }; + EB45ED3224749ECC008A1F6F /* gen_test_plist.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = gen_test_plist.py; sourceTree = ""; }; EB48C19E1E573EDC00EC5E57 /* sos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sos.m; sourceTree = ""; }; EB490153211C0026001E6D6A /* UserManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserManagement.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/System/Library/PrivateFrameworks/UserManagement.framework; sourceTree = DEVELOPER_DIR; }; EB49B2AE202D877F003F34A0 /* secdmockaks.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = secdmockaks.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -15841,8 +15958,6 @@ EB8021411D3D90BB008540C4 /* Security.iOS.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = Security.iOS.modulemap; path = Modules/Security.iOS.modulemap; sourceTree = ""; }; EB8021421D3D90BB008540C4 /* Security.macOS.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = Security.macOS.modulemap; path = Modules/Security.macOS.modulemap; sourceTree = ""; }; EB80DE57219600CF005B10FA /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.Internal.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; }; - EB82A2A41FAFF26900CA64A9 /* SFBehavior.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFBehavior.h; sourceTree = ""; }; - EB82A2A51FAFF26900CA64A9 /* SFBehavior.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFBehavior.m; sourceTree = ""; }; EB89088621F17D3C00F0DDDB /* recovery_securityd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = recovery_securityd; sourceTree = BUILT_PRODUCTS_DIR; }; EB8908BB21F20E0200F0DDDB /* com.apple.recovery_securityd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.recovery_securityd.plist; sourceTree = ""; }; EB89111020E3C15D00DE533F /* UserManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserManagement.framework; path = System/Library/PrivateFrameworks/UserManagement.framework; sourceTree = SDKROOT; }; @@ -15894,21 +16009,24 @@ EBF374721DC055580065D840 /* security-sysdiagnose */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "security-sysdiagnose"; sourceTree = BUILT_PRODUCTS_DIR; }; EBF374741DC055590065D840 /* security-sysdiagnose.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "security-sysdiagnose.m"; sourceTree = ""; }; EBF3747F1DC057FE0065D840 /* security-sysdiagnose.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = "security-sysdiagnose.1"; sourceTree = ""; }; - EBF3749A1DC064200065D840 /* SecADWrapper.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecADWrapper.c; sourceTree = ""; }; - EBF3749B1DC064200065D840 /* SecADWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecADWrapper.h; sourceTree = ""; }; EBF9AE171F536D0300FECBF7 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Version.xcconfig; path = xcconfig/Version.xcconfig; sourceTree = ""; }; F619D71D1ED70BB0005B5F46 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = OSX/authorizationdump/main.m; sourceTree = ""; }; F621D07F1ED6DCE7000EA569 /* authorizationdump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = authorizationdump; sourceTree = BUILT_PRODUCTS_DIR; }; F667EC551E96E94800203D5C /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = OSX/authd/tests/main.m; sourceTree = ""; }; F667EC601E96E9B100203D5C /* authdtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = authdtest; sourceTree = BUILT_PRODUCTS_DIR; }; + F681C3A82386B8B40083F22C /* PreloginUserDb.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PreloginUserDb.m; path = OSX/authd/PreloginUserDb.m; sourceTree = ""; }; + F681C3AA2386B8B40083F22C /* PreloginUserDb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PreloginUserDb.h; path = OSX/authd/PreloginUserDb.h; sourceTree = ""; }; F682C1CE1F4486F600F1B029 /* libctkloginhelper.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkloginhelper.a; path = usr/local/lib/libctkloginhelper.a; sourceTree = SDKROOT; }; F6A0971E1E953A1500B1E7D6 /* authdtestlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = authdtestlist.h; path = OSX/authd/tests/authdtestlist.h; sourceTree = ""; }; F6A0971F1E953ABD00B1E7D6 /* authdtests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = authdtests.m; path = OSX/authd/tests/authdtests.m; sourceTree = ""; }; F6A3CB0D1E7062BA00E7821F /* authd-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "authd-Entitlements.plist"; path = "OSX/authd/authd-Entitlements.plist"; sourceTree = ""; }; + F6B1B48924144B5E00CB3E3F /* libctkloginhelperlite.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkloginhelperlite.a; path = usr/local/lib/libctkloginhelperlite.a; sourceTree = SDKROOT; }; F6D600702166551800F9F7C9 /* AuthorizationTrampolinePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationTrampolinePriv.h; path = OSX/libsecurity_authorization/lib/AuthorizationTrampolinePriv.h; sourceTree = ""; }; F9B458272183E01100F6BCEB /* SignatureEditing.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = SignatureEditing.sh; path = OSX/codesign_tests/SignatureEditing.sh; sourceTree = ""; }; F9F77E96223C2F7B00E5CBF6 /* requirement.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = requirement.c; sourceTree = ""; }; F9F77E97223C2F7C00E5CBF6 /* requirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = requirement.h; sourceTree = ""; }; + FC637229237B5CF800973738 /* SecItemServer+SWC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SecItemServer+SWC.h"; sourceTree = ""; }; + FC63722A237B5CF900973738 /* SecItemServer+SWC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SecItemServer+SWC.m"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -15947,6 +16065,7 @@ 0C0BDB881756A51000BC1A7E /* libsqlite3.dylib in Frameworks */, BE8ABDD81DC2DD9100EC2D58 /* libz.dylib in Frameworks */, 4469FBFF1AA0A4820021AA26 /* libctkclient_test.a in Frameworks */, + DA53FC4523A9C801002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16005,25 +16124,38 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0C3810F123EF6FC4002D7E19 /* OctagonTrust.framework in Frameworks */, 0C84D83D1FCF449700B822E3 /* Security.framework in Frameworks */, 0CE902352395D0A3005E3F8C /* AuthKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 0C9AEEB020783FBB00BF6237 /* Frameworks */ = { + 0CCC226123F357EE00E1FCD0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C9AEEBB20783FF900BF6237 /* Security.framework in Frameworks */, + 0CCC22B323F38B6D00E1FCD0 /* AuthKit.framework in Frameworks */, + 0CCC22B623F38BCD00E1FCD0 /* CoreData.framework in Frameworks */, + 0CCC22C723F3904D00E1FCD0 /* Foundation.framework in Frameworks */, + 0C570B7C23F3A0E3001FEB3B /* IOKit.framework in Frameworks */, + 0CCC22C823F390E400E1FCD0 /* OCMock.framework in Frameworks */, + 0CCC22A423F374EB00E1FCD0 /* OctagonTrust.framework in Frameworks */, + 0CCC22AE23F38B2D00E1FCD0 /* SystemConfiguration.framework in Frameworks */, + 0CCC22A923F38AFD00E1FCD0 /* libSecureObjectSyncServer.a in Frameworks */, + 0CCC22A823F38AD600E1FCD0 /* libsecurityd_ios.a in Frameworks */, + 0CCC22A523F3763C00E1FCD0 /* libutilities.a in Frameworks */, + 0CCC22BD23F38D4B00E1FCD0 /* libbsm.tbd in Frameworks */, + 0CCC22BC23F38D3500E1FCD0 /* libz.tbd in Frameworks */, + 0CCC22B223F38B5B00E1FCD0 /* libsqlite3.0.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 0CF406342072E3E3003D6A7F /* Frameworks */ = { + 0CD743A323C3EC8000FA0EC5 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C5663EF20BE2E220035F362 /* libutilities.a in Frameworks */, - 0C9AEEBE207843D000BF6237 /* Security.framework in Frameworks */, + 0CCC21FF23F3577A00E1FCD0 /* Security.framework in Frameworks */, + 0CD743AF23C3ECEB00FA0EC5 /* ProtocolBuffer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16054,7 +16186,6 @@ 3DD1FFA5201FC59D0086D049 /* libsecurity_ssl.a in Frameworks */, 3DD1FFA4201FC58F0086D049 /* libutilities.a in Frameworks */, 3DD1FFA3201FC5870086D049 /* libDiagnosticMessagesClient.tbd in Frameworks */, - 3DD1FFA2201FC5800086D049 /* SecurityFoundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16069,7 +16200,15 @@ 3DD1FFC6201FDB1D0086D049 /* Foundation.framework in Frameworks */, 3DD1FFC8201FDB1D0086D049 /* libsecurity_ssl.a in Frameworks */, 3DD1FFC9201FDB1D0086D049 /* libutilities.a in Frameworks */, - 3DD1FFCB201FDB1D0086D049 /* SecurityFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E88360B24F068EF00E9F4D6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E88361B24F08DA100E9F4D6 /* Security.framework in Frameworks */, + 3E88360D24F068EF00E9F4D6 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16081,6 +16220,7 @@ 438169E41B4EE13B00C54D58 /* Accounts.framework in Frameworks */, 438169E51B4EE14D00C54D58 /* Security.framework in Frameworks */, 4381690D1B4EDCBD00C54D58 /* Foundation.framework in Frameworks */, + DA2F592723A99F2900C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16111,6 +16251,7 @@ 4718AE23205B39620068EC3F /* IOKit.framework in Frameworks */, 4718AE24205B39620068EC3F /* libaks_acl.a in Frameworks */, 4718AE25205B39620068EC3F /* libsqlite3.dylib in Frameworks */, + DA2F592523A99E8400C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16146,12 +16287,12 @@ 4727FBD51F9920510003AE36 /* ProtocolBuffer.framework in Frameworks */, D4911172209559630066A1E4 /* CoreData.framework in Frameworks */, 4727FBD31F9920290003AE36 /* CloudKit.framework in Frameworks */, - 4727FBD11F991F990003AE36 /* libMobileGestalt.dylib in Frameworks */, 4727FBCE1F991F820003AE36 /* SecurityFoundation.framework in Frameworks */, 4727FBCD1F991F660003AE36 /* libsqlite3.dylib in Frameworks */, 4727FBC91F991E5A0003AE36 /* libutilities.a in Frameworks */, 4727FBC61F991DE90003AE36 /* libsecdRegressions.a in Frameworks */, 4727FBC51F991C470003AE36 /* Foundation.framework in Frameworks */, + DA53FC3E23A9C180002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16181,45 +16322,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 478D427D1FD72A8100CAB645 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - DC4A76AA22126993006F2D8F /* CloudServices.framework in Frameworks */, - 0C6C0FD221F146E700CD5B9E /* CoreCDP.framework in Frameworks */, - EB7732DB21963BC100FCF513 /* libz.tbd in Frameworks */, - 482FE56A2177C7980031C11E /* AuthKit.framework in Frameworks */, - 479231EE2065B32200B2718C /* libsecurityd_ios.a in Frameworks */, - 477A1F5320320E5100ACD81D /* Accounts.framework in Frameworks */, - 478D429F1FD72C8400CAB645 /* AppleSystemInfo.framework in Frameworks */, - 478D429E1FD72C4800CAB645 /* CrashReporterSupport.framework in Frameworks */, - 478D427F1FD72A8100CAB645 /* libprequelite.dylib in Frameworks */, - 478D42801FD72A8100CAB645 /* OCMock.framework in Frameworks */, - 478D42811FD72A8100CAB645 /* libregressionBase.a in Frameworks */, - 478D42821FD72A8100CAB645 /* libACM.a in Frameworks */, - D4911173209559630066A1E4 /* CoreData.framework in Frameworks */, - 478D42831FD72A8100CAB645 /* ApplePushService.framework in Frameworks */, - 478D42841FD72A8100CAB645 /* SharedWebCredentials.framework in Frameworks */, - 478D42851FD72A8100CAB645 /* MobileKeyBag.framework in Frameworks */, - 478D42861FD72A8100CAB645 /* IOKit.framework in Frameworks */, - 478D42871FD72A8100CAB645 /* libaks.a in Frameworks */, - 478D42881FD72A8100CAB645 /* libaks_acl.a in Frameworks */, - 478D42891FD72A8100CAB645 /* WirelessDiagnostics.framework in Frameworks */, - 478D428A1FD72A8100CAB645 /* SystemConfiguration.framework in Frameworks */, - 478D428B1FD72A8100CAB645 /* libSecureObjectSyncServer.a in Frameworks */, - 478D428C1FD72A8100CAB645 /* libSecureObjectSyncFramework.a in Frameworks */, - 478D428D1FD72A8100CAB645 /* ProtocolBuffer.framework in Frameworks */, - 478D428E1FD72A8100CAB645 /* CloudKit.framework in Frameworks */, - DC066DF02102563300694EAF /* Security.framework in Frameworks */, - 478D42901FD72A8100CAB645 /* SecurityFoundation.framework in Frameworks */, - 478D42911FD72A8100CAB645 /* libsqlite3.dylib in Frameworks */, - 478D42931FD72A8100CAB645 /* libutilities.a in Frameworks */, - 478D42951FD72A8100CAB645 /* libsecurity.a in Frameworks */, - 478D42961FD72A8100CAB645 /* libsecdRegressions.a in Frameworks */, - 478D42971FD72A8100CAB645 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 47C2F1802059CB680062DE30 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -16263,6 +16365,7 @@ 438166ED1B4ECF9400C54D58 /* CoreFoundation.framework in Frameworks */, 4CAF67AC0F3A70220064A534 /* IOKit.framework in Frameworks */, 0940F6F82151316500C06F18 /* libACM.a in Frameworks */, + 0C2B32A523C4001900A97B18 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16270,7 +16373,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C9FB40720D872A600864612 /* CoreCDP.framework in Frameworks */, + 0CCC22D623F39B2E00E1FCD0 /* CoreCDP.framework in Frameworks */, 43DB54551BB1F8920083C3F1 /* ProtectedCloudStorage.framework in Frameworks */, 4C8A38C917B93DF10001B4C0 /* CloudServices.framework in Frameworks */, 4381603B1B4DCEFF00C54D58 /* AggregateDictionary.framework in Frameworks */, @@ -16293,9 +16396,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0CC9403023F39E84004B71AA /* CoreCDP.framework in Frameworks */, D47AB2D12356B2FE005A3801 /* Network.framework in Frameworks */, DC4A76AD22126A17006F2D8F /* CloudServices.framework in Frameworks */, - 0C6C0FD621F14D3900CD5B9E /* CoreCDP.framework in Frameworks */, EB80DE5B219600FC005B10FA /* libz.tbd in Frameworks */, 482FE56F2177CF520031C11E /* AuthKit.framework in Frameworks */, D4C6C5CF1FB3B44D007EA57E /* libarchive.2.dylib in Frameworks */, @@ -16328,6 +16431,7 @@ 4C711D6D13AFCD0900FE865D /* Security.framework in Frameworks */, D418CC701E690CAD00330A44 /* MobileAsset.framework in Frameworks */, E71F3E4216EA6A6300FAF9B4 /* SystemConfiguration.framework in Frameworks */, + DA3862AA23AAD959001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16354,11 +16458,11 @@ DC4A76A5221268A6006F2D8F /* CloudServices.framework in Frameworks */, EB7732C221963B0500FCF513 /* libz.tbd in Frameworks */, 482FE56C2177CEEF0031C11E /* AuthKit.framework in Frameworks */, - 0C9FB40920D8735500864612 /* CoreCDP.framework in Frameworks */, 47D13F631E8447FB0063B6E2 /* SecurityFoundation.framework in Frameworks */, EBE9019A1C22852C007308C6 /* AggregateDictionary.framework in Frameworks */, 438168BB1B4ED42300C54D58 /* CoreFoundation.framework in Frameworks */, DC00AB8E1D821D4900513D74 /* libSOSCommands.a in Frameworks */, + 0CCC22D723F39B7200E1FCD0 /* CoreCDP.framework in Frameworks */, 5296CB4F1655B92F009912AF /* libMobileGestalt.dylib in Frameworks */, 4432B0B71A014987000958DC /* libaks_acl.a in Frameworks */, DC65E7361D8CB35E00152EF0 /* libutilities.a in Frameworks */, @@ -16389,6 +16493,7 @@ 52D82BEE16A622370078DFE5 /* Security.framework in Frameworks */, 52D82BDF16A621F70078DFE5 /* Foundation.framework in Frameworks */, E72D462B175FBF3E00F70B9B /* IOKit.framework in Frameworks */, + DA53FC3D23A9BF28002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16425,7 +16530,6 @@ buildActionMask = 2147483647; files = ( DC4A76A02212676D006F2D8F /* CloudServices.framework in Frameworks */, - 0C6C0FCB21F1415B00CD5B9E /* CoreCDP.framework in Frameworks */, EB80DE5D21960C0A005B10FA /* libz.tbd in Frameworks */, 482FE5662177C6E40031C11E /* AuthKit.framework in Frameworks */, 482FE5652177C6D90031C11E /* Accounts.framework in Frameworks */, @@ -16445,6 +16549,17 @@ 5E43C48D1B00D07000E5ECB2 /* CoreFoundation.framework in Frameworks */, 5E43C4961B00D3B500E5ECB2 /* IOKit.framework in Frameworks */, 5E43C49A1B00D4D800E5ECB2 /* Security.framework in Frameworks */, + DA53FC4623A9CB13002D5EA9 /* SoftLinking.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6C2045E72424BA7E00F9461D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6CB0C5F824ACDB5300479FB4 /* Security.framework in Frameworks */, + 6CA9690A24ACC2D100C08B5E /* libutilities.a in Frameworks */, + 6C2045F52424BBDD00F9461D /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16452,7 +16567,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 6C8FF4B3224C1A8D00E5C812 /* TrustedPeers.framework in Frameworks */, 6C540C3922289A3B0032B5BC /* CloudServices.framework in Frameworks */, 6C39235B21F13E4D00D018AD /* libz.dylib in Frameworks */, 6C39235C21F13E4D00D018AD /* AuthKit.framework in Frameworks */, @@ -16478,6 +16592,7 @@ 6C39237221F13E4D00D018AD /* libutilities.a in Frameworks */, 6C39237321F13E4D00D018AD /* libsecdRegressions.a in Frameworks */, 6C39237421F13E4D00D018AD /* Foundation.framework in Frameworks */, + DA53FC3F23A9C26F002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16494,70 +16609,34 @@ D4119E882032A8FA0048587B /* OCMock.framework in Frameworks */, 6C13AE481F8E9FC800F047E3 /* libutilities.a in Frameworks */, 6C4605A51F882B9B001421B6 /* Foundation.framework in Frameworks */, + DA53FC4123A9C3CE002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 6C9808481E788AEB00E70590 /* Frameworks */ = { + 6C7BE2D223C3DD64003BB2CA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DC4A76A822126959006F2D8F /* CloudServices.framework in Frameworks */, - 0C4D96A721F25F2C00617E60 /* CoreCDP.framework in Frameworks */, - 482FE5672177C7260031C11E /* AuthKit.framework in Frameworks */, - 6CAA8CDD1F82EDEF007B6E03 /* Security.framework in Frameworks */, - D46246BC1F9AE82B00D63882 /* libDER.a in Frameworks */, - 6C98084A1E788AEB00E70590 /* libASN1.a in Frameworks */, - 6C98084D1E788AEB00E70590 /* libSecureObjectSyncFramework.a in Frameworks */, - 6C98084E1E788AEB00E70590 /* libSecureObjectSyncServer.a in Frameworks */, - DC93C4C5214713C5008F8362 /* libaks_mock.a in Frameworks */, - DC93C4D021471FD8008F8362 /* libsecurityd_ios.a in Frameworks */, - 6C98084F1E788AEB00E70590 /* libsecurity.a in Frameworks */, - 6C9808501E788AEB00E70590 /* libutilities.a in Frameworks */, - 6C9808511E788AEB00E70590 /* CFNetwork.framework in Frameworks */, - 6C9808521E788AEB00E70590 /* Foundation.framework in Frameworks */, - 6C9808531E788AEB00E70590 /* IOKit.framework in Frameworks */, - 6C9808541E788AEB00E70590 /* OCMock.framework in Frameworks */, - DCB515DE1ED3CF86001F1152 /* SecurityFoundation.framework in Frameworks */, - 6C9808551E788AEB00E70590 /* SystemConfiguration.framework in Frameworks */, - 6C9808561E788AEB00E70590 /* libACM.a in Frameworks */, - 6C9808571E788AEB00E70590 /* libaks_acl.a in Frameworks */, - 6C9808581E788AEB00E70590 /* libbsm.dylib in Frameworks */, - 6C9808591E788AEB00E70590 /* libcoreauthd_client.a in Frameworks */, - 6C98085A1E788AEB00E70590 /* libctkclient_sep.a in Frameworks */, - 6C98085B1E788AEB00E70590 /* libsqlite3.0.dylib in Frameworks */, - 6C98085C1E788AEB00E70590 /* libz.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6C9808841E788AFD00E70590 /* Frameworks */ = { + 6C16258823C5001C0086A0FF /* libSecureObjectSyncServer.a in Frameworks */, + 6C16258723C4FFEC0086A0FF /* libMobileGestalt.tbd in Frameworks */, + 6C7BE2EB23C3DDC3003BB2CA /* libsecurityd_bridge.a in Frameworks */, + 6C7BE2D423C3DD64003BB2CA /* libz.tbd in Frameworks */, + 6C7BE2D723C3DD64003BB2CA /* SecurityFoundation.framework in Frameworks */, + 6C7BE2D823C3DD64003BB2CA /* AggregateDictionary.framework in Frameworks */, + 6C7BE2D923C3DD64003BB2CA /* CoreFoundation.framework in Frameworks */, + 6C7BE2DC23C3DD64003BB2CA /* libaks_acl.a in Frameworks */, + 6C7BE2DD23C3DD64003BB2CA /* libutilities.a in Frameworks */, + 6C7BE2E023C3DD64003BB2CA /* Security.framework in Frameworks */, + 6C7BE2E323C3DD64003BB2CA /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6C96327E242A279B00C53CE2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DC4A76A72212694F006F2D8F /* CloudServices.framework in Frameworks */, - 0C6C0FD021F145F600CD5B9E /* CoreCDP.framework in Frameworks */, - 482FE5682177C73C0031C11E /* AuthKit.framework in Frameworks */, - 6CAA8CEE1F83E417007B6E03 /* Security.framework in Frameworks */, - D46246BD1F9AE83600D63882 /* libDER.a in Frameworks */, - 6C9808861E788AFD00E70590 /* libASN1.a in Frameworks */, - 6C9808891E788AFD00E70590 /* libSecureObjectSyncFramework.a in Frameworks */, - 6C98088A1E788AFD00E70590 /* libSecureObjectSyncServer.a in Frameworks */, - DC93C4CB214713ED008F8362 /* libaks_mock.a in Frameworks */, - DC93C4CA214713E5008F8362 /* libsecurityd_ios.a in Frameworks */, - 6C98088B1E788AFD00E70590 /* libsecurity.a in Frameworks */, - 6C98088C1E788AFD00E70590 /* libutilities.a in Frameworks */, - 6C98088D1E788AFD00E70590 /* CFNetwork.framework in Frameworks */, - 6C98088E1E788AFD00E70590 /* Foundation.framework in Frameworks */, - 6C98088F1E788AFD00E70590 /* IOKit.framework in Frameworks */, - 6C9808901E788AFD00E70590 /* OCMock.framework in Frameworks */, - DCB515DF1ED3CF95001F1152 /* SecurityFoundation.framework in Frameworks */, - 6C9808911E788AFD00E70590 /* SystemConfiguration.framework in Frameworks */, - 6C9808921E788AFD00E70590 /* libACM.a in Frameworks */, - 6C9808931E788AFD00E70590 /* libaks_acl.a in Frameworks */, - 6C9808941E788AFD00E70590 /* libbsm.dylib in Frameworks */, - 6C9808951E788AFD00E70590 /* libcoreauthd_client.a in Frameworks */, - 6C9808961E788AFD00E70590 /* libctkclient_sep.a in Frameworks */, - 6C9808971E788AFD00E70590 /* libsqlite3.0.dylib in Frameworks */, - 6C9808981E788AFD00E70590 /* libz.dylib in Frameworks */, + 6C61D3E9242A2C14008AB9BB /* Security.framework in Frameworks */, + 6C96328A242A284C00C53CE2 /* MobileKeyBag.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16596,19 +16675,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DCCA5E841E539EE7009EE93D /* AppKit.framework in Frameworks */, 6CAB39C71E521BEA00566A79 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 6CF4A0DD1E4549F200ECD7B5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6CE22D701E49206600974785 /* UIKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 790851B40CA9859F0083CC4D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -16628,6 +16698,7 @@ E71F3E3116EA69A900FAF9B4 /* SystemConfiguration.framework in Frameworks */, 4CAF66190F3A6FCD0064A534 /* IOKit.framework in Frameworks */, 4C2215220F3A612C00835155 /* libsqlite3.dylib in Frameworks */, + 0C2B32A423C4000F00A97B18 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16698,6 +16769,7 @@ D401E8B420A26F1F00CD8BB4 /* CoreData.framework in Frameworks */, DC340C54208E828F004D7EEC /* TrustedPeers.framework in Frameworks */, BE9F8D15206C2E0200B53D16 /* libutilities.a in Frameworks */, + DA53FC4923A9CC8D002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16727,7 +16799,6 @@ DC00C92320B3B80500628BEB /* libbsm.tbd in Frameworks */, DC00C92420B3B82600628BEB /* libz.tbd in Frameworks */, DC00C92020B3B7CC00628BEB /* libDER.a in Frameworks */, - DC6013312147220F00863C1A /* libaks_mock.a in Frameworks */, DC60132E2147220600863C1A /* libsecurityd_ios.a in Frameworks */, BE53602D209BBF630027E25A /* libMobileGestalt.tbd in Frameworks */, DC9C06712149E6B900C6F7B8 /* AuthKit.framework in Frameworks */, @@ -16736,10 +16807,9 @@ BED987DF209918A500607A5F /* SecurityFoundation.framework in Frameworks */, BED987D82099145300607A5F /* TrustedPeers.framework in Frameworks */, DC00C93520B48BA800628BEB /* IOKit.framework in Frameworks */, - DC00C91D20B3B79600628BEB /* libsecurity.a in Frameworks */, - BE53601C209BB8970027E25A /* libSecureObjectSyncFramework.a in Frameworks */, BE53601B209BB8390027E25A /* libSecureObjectSyncServer.a in Frameworks */, BE53601A209BB7F80027E25A /* libutilities.a in Frameworks */, + DA3862A723A9CD2E001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16775,6 +16845,7 @@ D41257E21E94138600781F23 /* CoreFoundation.framework in Frameworks */, D41257D01E9410A300781F23 /* Foundation.framework in Frameworks */, D450686A1E948D2200FA7675 /* Security.framework in Frameworks */, + DA53FC3C23A9BDD5002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16796,6 +16867,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D49BD0762476F74B00FC7E1C /* libMobileGestalt.tbd in Frameworks */, D4FD4225217D7BEE002B7EE2 /* libarchive.2.tbd in Frameworks */, D453A4B22122236D00850A26 /* libz.tbd in Frameworks */, D453A4B32122236D00850A26 /* libsqlite3.tbd in Frameworks */, @@ -16810,6 +16882,7 @@ D453A4B92122236D00850A26 /* Foundation.framework in Frameworks */, D453A4BA2122236D00850A26 /* IOKit.framework in Frameworks */, D40B7CA021605BF800AC9A75 /* OCMock.framework in Frameworks */, + DA3862AB23AAE3A8001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16828,6 +16901,7 @@ files = ( D458C512214E20850043D982 /* XCTest.framework in Frameworks */, D458C507214E20540043D982 /* Foundation.framework in Frameworks */, + DA2F592623A99EC900C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -16835,6 +16909,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D49BD0742476F67700FC7E1C /* libMobileGestalt.tbd in Frameworks */, D4FD4224217D7BE4002B7EE2 /* libarchive.2.tbd in Frameworks */, D4B68C62211A80CE009FED69 /* libz.tbd in Frameworks */, D4B68C5F211A80B1009FED69 /* libsqlite3.tbd in Frameworks */, @@ -16847,6 +16922,7 @@ D4B68C60211A80BC009FED69 /* CoreFoundation.framework in Frameworks */, D4B68C61211A80C4009FED69 /* Foundation.framework in Frameworks */, D4B68C63211A80DA009FED69 /* IOKit.framework in Frameworks */, + DA53FC4723A9CBAA002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17092,8 +17168,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D49BD0772476F7C000FC7E1C /* libMobileGestalt.tbd in Frameworks */, 4C47FA9420A51DD800384CB6 /* AppleFSCompression.framework in Frameworks */, DCD22D4B1D8CBF54001C9B81 /* libASN1.a in Frameworks */, + F6B1B48B24144B5F00CB3E3F /* libctkloginhelperlite.a in Frameworks */, DC00AB6F1D821C3400513D74 /* libSecItemShimOSX.a in Frameworks */, DC00AB701D821C3800513D74 /* libSecOtrOSX.a in Frameworks */, DC00AB6B1D821C1A00513D74 /* libSecTrustOSX.a in Frameworks */, @@ -17143,6 +17221,7 @@ DC1789251D7799CD00B50D50 /* CoreFoundation.framework in Frameworks */, DC1789271D7799D400B50D50 /* IOKit.framework in Frameworks */, 0940F6F92151316600C06F18 /* libACM.a in Frameworks */, + DA2F591823A32BC100C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17158,7 +17237,6 @@ buildActionMask = 2147483647; files = ( DCF465742201155000BA6EEA /* CloudServices.framework in Frameworks */, - 0C6C0FD121F1465500CD5B9E /* CoreCDP.framework in Frameworks */, DC391FAE21C1903E00772585 /* libutilities.a in Frameworks */, EBD531772198AF19003A57E6 /* Accounts.framework in Frameworks */, EBD531762198AF0B003A57E6 /* AppleAccount.framework in Frameworks */, @@ -17177,6 +17255,7 @@ DC222C361E02419B00B09171 /* libbsm.dylib in Frameworks */, DC3502CA1E020DC100BC0587 /* libsqlite3.0.dylib in Frameworks */, DC222C321E0240D300B09171 /* libz.dylib in Frameworks */, + DA53FC4023A9C351002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17327,9 +17406,9 @@ DC5AC0C91D8353D100CF422C /* libbsm.dylib in Frameworks */, DCD22D701D8CC733001C9B81 /* libutilities.a in Frameworks */, DC63D70820B3931100D088AD /* libxar.tbd in Frameworks */, - DC5AC0C71D8353C800CF422C /* PCSC.framework in Frameworks */, DC5AC0C51D8353C200CF422C /* Security.framework in Frameworks */, DC5AC0C41D8353BB00CF422C /* System.framework in Frameworks */, + D4E6D8592404EAD40074CB26 /* libDER.a in Frameworks */, DC5AC0C21D83538D00CF422C /* CoreFoundation.framework in Frameworks */, DC5AC0C11D83538800CF422C /* IOKit.framework in Frameworks */, ); @@ -17339,9 +17418,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0C570B8123F3A1EC001FEB3B /* CoreCDP.framework in Frameworks */, D47AB2D62357955F005A3801 /* Network.framework in Frameworks */, DCF46573220114F000BA6EEA /* CloudServices.framework in Frameworks */, - 0C4D96A621F24E5700617E60 /* CoreCDP.framework in Frameworks */, EB80DE56219600C6005B10FA /* libz.tbd in Frameworks */, DC9C066F2149E36900C6F7B8 /* AuthKit.framework in Frameworks */, 47C2F1762059A2300062DE30 /* libprequelite.tbd in Frameworks */, @@ -17350,6 +17429,7 @@ 474B5FC81E662E79007546F8 /* SecurityFoundation.framework in Frameworks */, D43B88721E72298500F86F19 /* MobileAsset.framework in Frameworks */, DC4EA5961E70A237008840B4 /* libsecurity.a in Frameworks */, + D49BD07824770E2D00FC7E1C /* libMobileGestalt.tbd in Frameworks */, 6C5B36BA1E2F9B95008AD443 /* WirelessDiagnostics.framework in Frameworks */, DC610A3D1D78F25C002223DE /* libDiagnosticMessagesClient.dylib in Frameworks */, DC610A3B1D78F234002223DE /* libACM.a in Frameworks */, @@ -17381,6 +17461,7 @@ DCD22D6B1D8CC685001C9B81 /* AppleSystemInfo.framework in Frameworks */, DC610A291D78F129002223DE /* IOKit.framework in Frameworks */, DC610A271D78F129002223DE /* Security.framework in Frameworks */, + DA3862AE23AAE65E001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17433,6 +17514,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0CD5040523F39DEA0036C279 /* CoreCDP.framework in Frameworks */, DCF465762201162800BA6EEA /* CloudServices.framework in Frameworks */, DC3E18C82125015300073D80 /* libsecurityd_ios.a in Frameworks */, DCCFB14E212394EC003D2DA2 /* libaks_mock.a in Frameworks */, @@ -17450,6 +17532,7 @@ DC99B88920EACA470065B73B /* libSecureObjectSyncServer.a in Frameworks */, DC99B88A20EACA470065B73B /* libutilities.a in Frameworks */, DC99B88B20EACA470065B73B /* libASN1.a in Frameworks */, + DA3862A923AAD1FD001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17499,7 +17582,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DCBF4AC121FFC82100539F0A /* CoreCDP.framework in Frameworks */, DCBF4AC221FFC82100539F0A /* libutilities.a in Frameworks */, DCBF4AC321FFC82100539F0A /* Accounts.framework in Frameworks */, DCBF4AC421FFC82100539F0A /* AppleAccount.framework in Frameworks */, @@ -17598,12 +17680,12 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0C570B7B23F3A09A001FEB3B /* CoreCDP.framework in Frameworks */, DC4A76AE22126C49006F2D8F /* CloudServices.framework in Frameworks */, EB80DE38219600A8005B10FA /* libz.tbd in Frameworks */, 482FE5642177C6850031C11E /* libprequelite.tbd in Frameworks */, 482FE5632177C5E80031C11E /* Accounts.framework in Frameworks */, 482FE5602177C5DA0031C11E /* AuthKit.framework in Frameworks */, - 0C4C548020E1A53D00BA61BA /* CoreCDP.framework in Frameworks */, 6C1F93111DD5E41A00585608 /* libDiagnosticMessagesClient.dylib in Frameworks */, DCE4E6AE1D7A3C6A00AFB96E /* AppleSystemInfo.framework in Frameworks */, DCE4E6AD1D7A3B9700AFB96E /* libaks.a in Frameworks */, @@ -17633,6 +17715,7 @@ files = ( D47AB2D02356B2F6005A3801 /* Network.framework in Frameworks */, 09EF431B21A5A8CC0066CF20 /* libaks_acl.a in Frameworks */, + 097CE59F246966A100958AF8 /* libMobileGestalt.dylib in Frameworks */, D4C6C5CD1FB3B423007EA57E /* libarchive.tbd in Frameworks */, D46246B71F9AE76500D63882 /* libDER.a in Frameworks */, DC3A81EC1D99F568000C7419 /* libcoretls.dylib in Frameworks */, @@ -17710,6 +17793,7 @@ DCD504C320CB293700F37D26 /* Security.framework in Frameworks */, DC4DB16A1E26E9F900CD6769 /* ProtocolBuffer.framework in Frameworks */, DCE4E82C1D7A56FF00AFB96E /* AppleSystemInfo.framework in Frameworks */, + DA53FC3923A9BA68002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17724,13 +17808,14 @@ D40B6A9E1E2B6A6F00CD6EE5 /* libtrustd.a in Frameworks */, D40B6A931E2B67E500CD6EE5 /* libutilities.a in Frameworks */, D40B6A831E2B5F5B00CD6EE5 /* libASN1.a in Frameworks */, - D40B6A9D1E2B6A2700CD6EE5 /* login.framework in Frameworks */, + D4981B8F24F723EA004B033B /* IOKit.framework in Frameworks */, D4ADA3311E2B43450031CEA3 /* CFNetwork.framework in Frameworks */, D47AB2CC2356AD7C005A3801 /* Network.framework in Frameworks */, D4ADA3301E2B433B0031CEA3 /* Security.framework in Frameworks */, D4ADA32E1E2B43220031CEA3 /* CoreFoundation.framework in Frameworks */, D4ADA32F1E2B43220031CEA3 /* Foundation.framework in Frameworks */, D4C7CD661E71E92D00139817 /* MobileAsset.framework in Frameworks */, + DA2F592123A9874800C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17741,11 +17826,13 @@ 5E01F5B1227C859200BC884C /* Foundation.framework in Frameworks */, DCE4E8C91D7F356500AFB96E /* libsqlite3.dylib in Frameworks */, DCE4E8C81D7F355F00AFB96E /* libbsm.dylib in Frameworks */, + F6F4105324AC622F00369037 /* libaks.a in Frameworks */, DCE4E8C71D7F355900AFB96E /* Security.framework in Frameworks */, DCE4E8C61D7F354700AFB96E /* CoreFoundation.framework in Frameworks */, DCE4E8C51D7F354300AFB96E /* IOKit.framework in Frameworks */, F6AF96681E646CAF00917214 /* libcoreauthd_client.a in Frameworks */, F682C1D41F4486F700F1B029 /* libctkloginhelper.a in Frameworks */, + DA2F591E23A986A300C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17764,7 +17851,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C4C547620E1A0B400BA61BA /* CoreCDP.framework in Frameworks */, + 0C570B7923F3A015001FEB3B /* CoreCDP.framework in Frameworks */, CD112FC51DDA31AD00C77A07 /* Accounts.framework in Frameworks */, 0CC319241DA46FBF005D42EA /* ProtectedCloudStorage.framework in Frameworks */, DCE4E9401D7F3E4D00AFB96E /* Security.framework in Frameworks */, @@ -17860,9 +17947,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0C147A2823F39CD10034F08B /* CoreCDP.framework in Frameworks */, D47AB2CF2356B2ED005A3801 /* Network.framework in Frameworks */, DC4A76A62212691F006F2D8F /* CloudServices.framework in Frameworks */, - 0C6C0FCF21F1457600CD5B9E /* CoreCDP.framework in Frameworks */, EB80DE5C2196010F005B10FA /* libz.tbd in Frameworks */, 482FE56D2177CF150031C11E /* AuthKit.framework in Frameworks */, D4C6C5D01FB3B45E007EA57E /* libarchive.2.dylib in Frameworks */, @@ -17895,6 +17982,7 @@ E71F3E4116EA6A5100FAF9B4 /* SystemConfiguration.framework in Frameworks */, D418CC711E690CBC00330A44 /* MobileAsset.framework in Frameworks */, 0CFC029C1D41650700E6283B /* libcoretls.dylib in Frameworks */, + DA53FC4423A9C779002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17944,7 +18032,6 @@ DCD22D531D8CC0EF001C9B81 /* libASN1.a in Frameworks */, E7F482A11C7543E500390FDB /* libsqlite3.dylib in Frameworks */, E7F482A31C7544E600390FDB /* libctkclient_test.a in Frameworks */, - E7F482A61C75453900390FDB /* libcoreauthd_test_client.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -17978,8 +18065,6 @@ EB75B48C1E75407C00E469CC /* libutilities.a in Frameworks */, EB75B48D1E75408900E469CC /* libASN1.a in Frameworks */, EB75B48F1E75409A00E469CC /* libsqlite3.dylib in Frameworks */, - EB75B4901E7540AA00E469CC /* libctkclient_test.a in Frameworks */, - EB75B4911E7540BF00E469CC /* libcoreauthd_test_client.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -18024,14 +18109,14 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + DCAAF3362493F9C600D4EB55 /* LocalAuthentication.framework in Frameworks */, + 0CCC22D823F39BCA00E1FCD0 /* CoreCDP.framework in Frameworks */, DC4A76AC221269E4006F2D8F /* CloudServices.framework in Frameworks */, EB49B2BB202D8894003F34A0 /* libsecurityd_ios.a in Frameworks */, - DC3E18EB2125FB8700073D80 /* libaks_mock.a in Frameworks */, EB49B2DD202DF259003F34A0 /* libbsm.tbd in Frameworks */, EB80DE59219600DF005B10FA /* libz.tbd in Frameworks */, EB49B2C2202DF002003F34A0 /* libDER.a in Frameworks */, 482FE5692177C7670031C11E /* AuthKit.framework in Frameworks */, - 0C6C0FD321F1494C00CD5B9E /* CoreCDP.framework in Frameworks */, EB49B2BE202DEF29003F34A0 /* libSecureObjectSyncServer.a in Frameworks */, EB49B2C1202DEF8D003F34A0 /* libASN1.a in Frameworks */, EB49B2C0202DEF7D003F34A0 /* libutilities.a in Frameworks */, @@ -18040,6 +18125,7 @@ EB49B2CD202DF0F9003F34A0 /* SystemConfiguration.framework in Frameworks */, EB49B2C7202DF0E9003F34A0 /* IOKit.framework in Frameworks */, EB49B2BC202DEF14003F34A0 /* libsqlite3.tbd in Frameworks */, + DA53FC4223A9C442002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -18057,6 +18143,7 @@ EB6952B1223B75C300F02C1C /* CoreData.framework in Frameworks */, EB6952B2223B75C300F02C1C /* SystemConfiguration.framework in Frameworks */, EB6952B3223B75C300F02C1C /* libsqlite3.dylib in Frameworks */, + DA2F592823A99F6300C30285 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -18082,6 +18169,7 @@ EB89087921F17D3C00F0DDDB /* Security.framework in Frameworks */, EB89087B21F17D3C00F0DDDB /* SystemConfiguration.framework in Frameworks */, EB89087E21F17D3C00F0DDDB /* libsqlite3.dylib in Frameworks */, + DA3862AC23AAE3D3001E21F1 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -18117,6 +18205,7 @@ EBB8521D22F7948B00424FD0 /* libutilities.a in Frameworks */, EBB8521B22F7945600424FD0 /* XCTest.framework in Frameworks */, EBB852CF22F7A05600424FD0 /* OCMock.framework in Frameworks */, + DA53FC4823A9CC16002D5EA9 /* SoftLinking.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -18160,6 +18249,37 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0C0203DE23A855B8005D0A68 /* proto */ = { + isa = PBXGroup; + children = ( + 0C0203E023A8564E005D0A68 /* OTEscrowRecord.proto */, + 0C0D920523BFEA740070A68C /* OTCDPRecoveryInformation.proto */, + 0C0203E523A85780005D0A68 /* generated_source */, + ); + name = proto; + sourceTree = ""; + }; + 0C0203E523A85780005D0A68 /* generated_source */ = { + isa = PBXGroup; + children = ( + 0C468FEA23C7D4C8006F4582 /* OTCDPRecoveryInformation.h */, + 0C468FEE23C7D4CA006F4582 /* OTCDPRecoveryInformation.m */, + 0C468FE823C7D4C8006F4582 /* OTEscrowAuthenticationInformation.h */, + 0C468FEC23C7D4C9006F4582 /* OTEscrowAuthenticationInformation.m */, + 0C468FDE23C7D471006F4582 /* OTEscrowRecord.h */, + 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */, + 0C468FDA23C7D41D006F4582 /* OTEscrowRecordMetadata.h */, + 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */, + 0C468FDB23C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.h */, + 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */, + 0C468FE723C7D4C7006F4582 /* OTICDPRecordContext.h */, + 0C468FED23C7D4C9006F4582 /* OTICDPRecordContext.m */, + 0C468FE923C7D4C8006F4582 /* OTICDPRecordSilentContext.h */, + 0C468FEB23C7D4C9006F4582 /* OTICDPRecordSilentContext.m */, + ); + name = generated_source; + sourceTree = ""; + }; 0C0BDB30175685B000BC1A7E /* secdtests */ = { isa = PBXGroup; children = ( @@ -18200,14 +18320,6 @@ path = Categories; sourceTree = ""; }; - 0C4C546C20E19CF200BA61BA /* Recovered References */ = { - isa = PBXGroup; - children = ( - 0C9FB40120D8729A00864612 /* CoreCDP.framework */, - ); - name = "Recovered References"; - sourceTree = ""; - }; 0C7382E52386379E004F98CB /* ResetCloudKeychainAccount */ = { isa = PBXGroup; children = ( @@ -18226,16 +18338,7 @@ path = regressions; sourceTree = ""; }; - 0C7CEA391FE9CE3900125C79 /* behavior */ = { - isa = PBXGroup; - children = ( - EB82A2A41FAFF26900CA64A9 /* SFBehavior.h */, - EB82A2A51FAFF26900CA64A9 /* SFBehavior.m */, - ); - path = behavior; - sourceTree = ""; - }; - 0C8BBE831FC9DA1700580909 /* Octagon Trust */ = { + 0C8BBE831FC9DA1700580909 /* OT */ = { isa = PBXGroup; children = ( DCD33D7D220B9D98000A390B /* State Machine Machinery */, @@ -18277,7 +18380,7 @@ BE34059B1FD71BA700933DAC /* Protocol Buffers */, 0C8BBEB11FC9DCAC00580909 /* tests */, ); - name = "Octagon Trust"; + name = OT; path = ot; sourceTree = ""; }; @@ -18285,6 +18388,8 @@ isa = PBXGroup; children = ( DC99B89720EAD4D20065B73B /* Octagon */, + EB45ED3124749ECC008A1F6F /* OTTests-Info.plist */, + EB45ED3224749ECC008A1F6F /* gen_test_plist.py */, ); path = tests; sourceTree = ""; @@ -18336,6 +18441,40 @@ path = generated_source; sourceTree = ""; }; + 0CCC227B23F3586F00E1FCD0 /* ot-tests */ = { + isa = PBXGroup; + children = ( + 0CCC229223F35D4300E1FCD0 /* OctagonTrustTests-Info.plist */, + 0C9A54B7250C290800FF007B /* OctagonTrustTests.h */, + 0CCC229F23F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m */, + 0CCC22A323F36DD300E1FCD0 /* OctagonTrustTests-EscrowTestVectors.h */, + 0C9A54B4250C27F100FF007B /* OctagonTrustTests+Errors.m */, + ); + path = "ot-tests"; + sourceTree = ""; + }; + 0CCC22CB23F3958B00E1FCD0 /* categories */ = { + isa = PBXGroup; + children = ( + 0CCC22CC23F395A100E1FCD0 /* OctagonTrustEscrowRecoverer.h */, + ); + path = categories; + sourceTree = ""; + }; + 0CD743A723C3EC8000FA0EC5 /* OctagonTrust */ = { + isa = PBXGroup; + children = ( + 0C9F65AC23E3ACF700B1A2C5 /* OTEscrowTranslation.h */, + 0C9F65AA23E3ACF700B1A2C5 /* OTEscrowTranslation.m */, + 0CD743A823C3EC8000FA0EC5 /* OctagonTrust.h */, + 0CD743B723C3ED7E00FA0EC5 /* OctagonTrust.m */, + 0CD743A923C3EC8000FA0EC5 /* Info.plist */, + 0CCC22CB23F3958B00E1FCD0 /* categories */, + 0CCC227B23F3586F00E1FCD0 /* ot-tests */, + ); + path = OctagonTrust; + sourceTree = ""; + }; 0CE15E29222DF5FF00B7EAA4 /* RecoveryKey */ = { isa = PBXGroup; children = ( @@ -18351,9 +18490,6 @@ 0CF405FB2072E351003D6A7F /* Resources */, 0CD9E33E235928D1002995DE /* OctagonSignPosts.h */, 0CD9E340235928E9002995DE /* OctagonSignPosts.m */, - 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */, - 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */, - 0C108C4B208A677100E8CF70 /* SFSignInAnalytics+Internal.h */, 0CF405F32072E295003D6A7F /* tests */, ); path = SigninMetrics; @@ -18362,7 +18498,6 @@ 0CF405F32072E295003D6A7F /* tests */ = { isa = PBXGroup; children = ( - 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */, ); path = tests; sourceTree = ""; @@ -18382,6 +18517,7 @@ 0C78F1C816A5E13400654E08 /* regressions */, 107226D00D91DB32003CF14F /* SecTask.c */, 4C7CE56E0DC7DB0A00AE53FC /* SecEntitlements.h */, + 6C54BE0C23F41497004716CB /* SystemEntitlements.h */, ); name = sectask; path = ../../../sectask; @@ -18416,6 +18552,14 @@ path = SecureTransportTests; sourceTree = ""; }; + 3E88361224F0693200E9F4D6 /* secseccodeapitest */ = { + isa = PBXGroup; + children = ( + 3E88361324F0699F00E9F4D6 /* secseccodeapitest.c */, + ); + name = secseccodeapitest; + sourceTree = ""; + }; 4381690E1B4EDCBD00C54D58 /* SOSCCAuthPlugin */ = { isa = PBXGroup; children = ( @@ -18489,6 +18633,7 @@ 4727FBB81F9918590003AE36 /* secdxctests */ = { isa = PBXGroup; children = ( + 6CD8412B23F5D871003DDF34 /* KeychainBackupTests.m */, 477A1FEB2037A0E000ACD81D /* KeychainXCTest.h */, 477A1FEC2037A0E000ACD81D /* KeychainXCTest.m */, 4727FBB91F9918590003AE36 /* KeychainCryptoTests.m */, @@ -18496,7 +18641,9 @@ 47B503C5203B97A000722164 /* SFCredentialStoreTests.m */, 477A1FE1203763A500ACD81D /* KeychainAPITests.m */, 09BFE35A20A32E0E008511E9 /* KeychainEntitlementsTest.m */, + 6C84E3C723ECBC84003C9710 /* KeychainAppClipTests.m */, 4727FBBB1F9918590003AE36 /* Info.plist */, + 6C5D62A5221B6E3F00AF79DC /* secdxctests-entitlements.plist */, ); path = secdxctests; sourceTree = ""; @@ -18566,6 +18713,7 @@ 47922D171FAA65120008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.proto */, 47922D201FAA75FF0008F7E0 /* SecDbKeychainSerializedMetadata.proto */, 47922D2C1FAA77970008F7E0 /* SecDbKeychainSerializedSecretData.proto */, + 6C6AF178221A03930091CE0A /* SecDbKeychainSerializedMetadataKey.proto */, ); path = "SecDbKeychainV7-protobufs"; sourceTree = ""; @@ -18574,6 +18722,7 @@ isa = PBXGroup; children = ( DCE4E80D1D7A4E3A00AFB96E /* com.apple.securityd.plist */, + DCDACB5724A3F1AA0054080C /* com.apple.security.ckks.plist */, EB3FB9B7231C12A800DF52EA /* com.apple.security.trustedpeers.plist */, 48284A041D1DB06E00C76CB7 /* README_os_log_prefs.txt */, ); @@ -18599,6 +18748,8 @@ 4C35DB67094F906D002917C4 = { isa = PBXGroup; children = ( + 3DC5BD58241830D50039ABF4 /* SecureTransportTests_macos.xctestplan */, + 3DC5BD59241845100039ABF4 /* SecureTransportTests_ios.xctestplan */, DC6D2C941DD3B20400BE372D /* keychain */, DC5AC2021D83668700CF422C /* Security.framework */, DC5AC1FD1D83647300CF422C /* SecureObjectSync */, @@ -18619,7 +18770,6 @@ 4CAB97FD1114CC5300EFB38D /* README.keychain */, 4C4CE9070AF81ED80056B01D /* TODO */, EBAC4A512189743D00FBEC43 /* rio.yml */, - 0C4C546C20E19CF200BA61BA /* Recovered References */, ); sourceTree = ""; }; @@ -18739,7 +18889,6 @@ D4ADA3191E2B41670031CEA3 /* libtrustd.a */, 6CCDF7841E3C25FA003F2555 /* KeychainEntitledTestRunner */, 6CF4A0B41E45488B00ECD7B5 /* KeychainEntitledTestApp.app */, - 6CF4A0E01E4549F200ECD7B5 /* KeychainEntitledTestApp.app */, EB27FF111E402CD300EC9E3A /* ckksctl */, 470415CF1E5E14B5001F3D95 /* seckeychainnetworkextensionstest */, 47702B1E1E5F409700B29577 /* seckeychainnetworkextensionsystemdaemontest */, @@ -18747,8 +18896,6 @@ EB108F411E6CE4D2003B0456 /* KCPairingTests.xctest */, F667EC601E96E9B100203D5C /* authdtest */, D41257CF1E9410A300781F23 /* trustd */, - 6C9808611E788AEB00E70590 /* CKKSCloudKitTests.xctest */, - 6C98089D1E788AFD00E70590 /* CKKSCloudKitTests.xctest */, ACBAF6DD1E9417F40007BA2F /* libsecurity_transform_regressions.a */, BEF88C281EAFFC3F00357577 /* TrustedPeers.framework */, BEF88C301EAFFC3F00357577 /* TrustedPeersTests.xctest */, @@ -18756,7 +18903,7 @@ BED208DD1EDF950E00753952 /* manifeststresstest */, 47C51B841EEA657D0032D9E5 /* SecurityUnitTests.xctest */, EB2D54AA1F02A45E00E46890 /* secatomicfile */, - 4727FBB71F9918580003AE36 /* secdxctests_ios.xctest */, + 4727FBB71F9918580003AE36 /* secdxctests.xctest */, 0C85E0031FB38BB6000343A7 /* OTTests.xctest */, 6C9AA79E1F7C1D8F00D08296 /* supdctl */, 6CAA8D201F842FB3007B6E03 /* securityuploadd */, @@ -18765,13 +18912,10 @@ 3DD1FF4D201C07F30086D049 /* SecureTransport_macos_tests.xctest */, 3DD1FFD0201FDB1D0086D049 /* SecureTransport_ios_tests.xctest */, BEAA002B202A832500E51F45 /* TrustedPeersHelper.xpc */, - 478D429C1FD72A8100CAB645 /* secdxctests_mac.xctest */, EB49B2AE202D877F003F34A0 /* secdmockaks.xctest */, 47C2F1832059CB680062DE30 /* KeychainResources.bundle */, 4718AE2D205B39620068EC3F /* securityd */, 4718AEE2205B39C40068EC3F /* libsecurityd_bridge.a */, - 0CF406502072E3E3003D6A7F /* SignInAnalyticsTests_ios.xctest */, - 0C9AEEB720783FBB00BF6237 /* SignInAnalyticsTests_osx.xctest */, DAE40BCE20CF3E47002D5674 /* secitemcanarytest */, DC0EF8EF208697C600AB9E95 /* tpctl */, BED987D32099145300607A5F /* TrustedPeersHelperUnitTests.xctest */, @@ -18802,6 +18946,12 @@ DA41FE0E2241ADC000838FB3 /* otpaird */, EBB851EC22F7912400424FD0 /* SecurityUtilitiesTests.xctest */, 5A442F90233C330F00918373 /* experimentTool */, + 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */, + 6C7BE2E723C3DD64003BB2CA /* securitytool_bridge */, + 0CCC227923F357EE00E1FCD0 /* OctagonTrustTests.xctest */, + 6C2045EA2424BA7E00F9461D /* KeychainStasher */, + 6C963281242A279B00C53CE2 /* stashtester */, + 3E88361124F068EF00E9F4D6 /* secseccodeapitest */, ); name = Products; sourceTree = ""; @@ -19092,6 +19242,17 @@ path = secacltests; sourceTree = ""; }; + 6C0535F422B7043B0064BA50 /* TestHostBinaries */ = { + isa = PBXGroup; + children = ( + 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner.entitlements */, + 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp */, + 6CB5F4771E402D6D00DBF3F0 /* KeychainEntitledTestRunner */, + ); + name = TestHostBinaries; + path = tests/TestHostBinaries; + sourceTree = ""; + }; 6C34464D1E2534C200F9522B /* analytics */ = { isa = PBXGroup; children = ( @@ -19115,6 +19276,14 @@ path = analytics; sourceTree = ""; }; + 6C534E0422C3E52600D4781F /* Discovery Plists */ = { + isa = PBXGroup; + children = ( + ); + name = "Discovery Plists"; + path = "tests/Discovery Plists"; + sourceTree = ""; + }; 6C69517B1F758E1000F68F91 /* supd */ = { isa = PBXGroup; children = ( @@ -19128,6 +19297,7 @@ 6C1260F21F7D5F25001B2EEC /* securityuploadd-osx.plist */, 6C5B10211F9164F5009B091E /* securityuploadd.8 */, 6CDB600E1FA92C1700410924 /* securityuploadd-Entitlements.plist */, + D42D044124733BEA004E7AA2 /* com.apple.securityuploadd.sb */, ); path = supd; sourceTree = ""; @@ -19157,10 +19327,11 @@ 6C7E8F1D21F7BD1C008A2D56 /* SecDbBackupTests */ = { isa = PBXGroup; children = ( - 6C2008EF220BB4B500674B3A /* Entitlements.plist */, - 6C02134F21F7ED45009D5C80 /* Info.plist */, + 6C6579FC2394878700701C8B /* SecDbBackupTestsBase.m */, + 6CD224E7239493E8001B70FD /* SecDbBackupTestsBase.h */, 6C02134D21F7ED16009D5C80 /* SecDbBackupTests.m */, - 6C02134C21F7ED16009D5C80 /* SecDbBackupTests.plist */, + 6C02134F21F7ED45009D5C80 /* Info.plist */, + 6C2008EF220BB4B500674B3A /* SecDbBackupTests-Entitlements.plist */, ); name = SecDbBackupTests; path = tests/SecDbBackupTests; @@ -19183,6 +19354,31 @@ path = generated_source; sourceTree = ""; }; + 6C963282242A279B00C53CE2 /* stashtester */ = { + isa = PBXGroup; + children = ( + 6C963283242A279B00C53CE2 /* main.m */, + 6C963289242A27F300C53CE2 /* stashtester.entitlements */, + ); + name = stashtester; + path = tests/stashtester; + sourceTree = ""; + }; + 6C997868242362EC008C498D /* KeychainStasher */ = { + isa = PBXGroup; + children = ( + 6C997869242362EC008C498D /* KeychainStasherProtocol.h */, + 6C99786A242362EC008C498D /* KeychainStasher.h */, + 6C99786B242362EC008C498D /* KeychainStasher.m */, + 6C99786D242362EC008C498D /* main.m */, + 6C99786F242362EC008C498D /* KeychainStasher-Info.plist */, + 6C48D10D2423A2F3004AF950 /* KeychainStasher.entitlements */, + 6C48D10F2423A3C0004AF950 /* com.apple.security.KeychainStasher.sb */, + 6C2045F92424BCB800F9461D /* com.apple.security.KeychainStasher.plist */, + ); + path = KeychainStasher; + sourceTree = ""; + }; 6C9AA79F1F7C1D9000D08296 /* supdctl */ = { isa = PBXGroup; children = ( @@ -19192,13 +19388,12 @@ path = supdctl; sourceTree = ""; }; - 6CB5F4771E402D6D00DBF3F0 /* testrunner */ = { + 6CB5F4771E402D6D00DBF3F0 /* KeychainEntitledTestRunner */ = { isa = PBXGroup; children = ( - 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner-Entitlements.plist */, 6CB5F47A1E402E5700DBF3F0 /* KeychainEntitledTestRunner.m */, ); - path = testrunner; + path = KeychainEntitledTestRunner; sourceTree = ""; }; 6CB6CBFE2198D40B0080AD6F /* SecDbBackupManager-protobufs */ = { @@ -19210,7 +19405,7 @@ path = "SecDbBackupManager-protobufs"; sourceTree = ""; }; - 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */ = { + 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp */ = { isa = PBXGroup; children = ( 6CF4A0B61E45488B00ECD7B5 /* AppDelegate.h */, @@ -19221,8 +19416,7 @@ 6CF4A0C41E45488B00ECD7B5 /* Info.plist */, 6CF4A0B91E45488B00ECD7B5 /* Supporting Files */, ); - name = KeychainEntitledTestApp_mac; - path = ../../../KeychainEntitledTestApp_mac; + path = KeychainEntitledTestApp; sourceTree = ""; }; 6CF4A0B91E45488B00ECD7B5 /* Supporting Files */ = { @@ -19233,29 +19427,6 @@ name = "Supporting Files"; sourceTree = ""; }; - 6CF4A0E11E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */ = { - isa = PBXGroup; - children = ( - 6CF4A0E51E4549F200ECD7B5 /* AppDelegate.h */, - 6CF4A0E61E4549F300ECD7B5 /* AppDelegate.m */, - 6CF4A0E81E4549F300ECD7B5 /* ViewController.h */, - 6CF4A0E91E4549F300ECD7B5 /* ViewController.m */, - 6CF4A0EE1E4549F300ECD7B5 /* Assets.xcassets */, - 6CF4A0F31E4549F300ECD7B5 /* Info.plist */, - 6CF4A0E21E4549F200ECD7B5 /* Supporting Files */, - ); - name = KeychainEntitledTestApp_ios; - path = ../../../KeychainEntitledTestApp_ios; - sourceTree = ""; - }; - 6CF4A0E21E4549F200ECD7B5 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6CF4A0E31E4549F200ECD7B5 /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; 7908507E0CA87CF00083CC4D /* ipc */ = { isa = PBXGroup; children = ( @@ -19356,6 +19527,11 @@ BE3405A21FD71CDE00933DAC /* generated */ = { isa = PBXGroup; children = ( + 0C3C47C524902D470084B951 /* OTGlobalEnums.h */, + 0C3C47C424902D470084B951 /* OTSupportOctagonMessage.h */, + 0C3C47C024902D450084B951 /* OTSupportOctagonMessage.m */, + 0C3C47C224902D460084B951 /* OTSupportSOSMessage.h */, + 0C3C47C324902D460084B951 /* OTSupportSOSMessage.m */, 0C89BDA121554DD3003F3CC0 /* OTAccountMetadataClassC.h */, 0C89BDA021554DD2003F3CC0 /* OTAccountMetadataClassC.m */, 0C9AE28B214054F5003BFDB5 /* OTApplicantToSponsorRound2M1.h */, @@ -19435,8 +19611,8 @@ BEAA002C202A832500E51F45 /* TrustedPeersHelper */ = { isa = PBXGroup; children = ( - 0CE15E29222DF5FF00B7EAA4 /* RecoveryKey */, DCB0C28F222F5DF80083AECB /* CuttlefishErrors.swift */, + 0CE15E29222DF5FF00B7EAA4 /* RecoveryKey */, 0C3BB3312187EC4D0018FC14 /* Categories */, 0C0C4F80216FB53A00C14C61 /* BottledPeer */, BE9F4F852072D834004A52C2 /* Cuttlefish Client */, @@ -19446,8 +19622,11 @@ BE55C77B2044D0C90045863D /* Client.swift */, BE9F8D0F206C099800B53D16 /* Container.swift */, DC3A9B2523A9D6120073ED06 /* Container_BottledPeers.swift */, - DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.swift */, + 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */, DCAD8F8422C43EAD007C3872 /* Container_MachineIDs.swift */, + 0C3DF8C524789C04009CF03A /* Container_Peers.swift */, + DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.swift */, + DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */, BE9F8D18206C4AD300B53D16 /* ContainerMap.swift */, BE9F8D11206C121400B53D16 /* Decrypter.swift */, BECFA43C20F9493000B11002 /* Policy.swift */, @@ -19462,6 +19641,7 @@ 0CB582BA218915010040C5F2 /* proto */, DC391FA521C04D1500772585 /* OctagonPeerKeys.swift */, DCF6320421C074F30030CCC0 /* CuttlefishAPIHelpers.swift */, + DCBDA460245A39A300B0938B /* com.apple.TrustedPeersHelper.sb */, ); path = TrustedPeersHelper; sourceTree = ""; @@ -19533,6 +19713,8 @@ BEF88C5B1EB0005E00357577 /* TPPolicy.m */, BEF88C5C1EB0005E00357577 /* TPPolicyDocument.h */, BEF88C5D1EB0005E00357577 /* TPPolicyDocument.m */, + DCC03FA223FF521100A4DA3F /* TPSyncingPolicy.h */, + DCC03FA323FF521100A4DA3F /* TPSyncingPolicy.m */, BEF88C5E1EB0005E00357577 /* TPKey.h */, BECFA46320FFB87400B11002 /* TPKey.m */, BEF88C5F1EB0005E00357577 /* TPTypes.h */, @@ -19687,7 +19869,6 @@ D458C4CA214E1A420043D982 /* AppDelegate.m */, D458C4C8214E1A410043D982 /* AppDelegate.h */, D458C4C5214E1A400043D982 /* Assets.xcassets */, - D458C4C7214E1A400043D982 /* Base.lproj */, D458C4CC214E1A420043D982 /* Info.plist */, D458C4C6214E1A400043D982 /* main.m */, D458C4CB214E1A420043D982 /* trusttests_entitlements.plist */, @@ -19710,6 +19891,7 @@ D4A0F8BB211E69CB00443CA1 /* TestMacroConversions.h */, D44282FE22D68556001746B3 /* TrustEvaluationTestHelpers.m */, D4A7946D22D7DD6E00D1B2B7 /* TrustEvaluationTestHelpers.h */, + EB45ED2E24749DE9008A1F6F /* gen_test_plist.py */, ); name = TrustTests; sourceTree = ""; @@ -19720,8 +19902,9 @@ D4EA5CF622B225C000883439 /* LoggingServerTests.m */, D49A370B23877ECC0065719F /* OCSPCacheTests.m */, D4BA4FD22388687A000B9E64 /* OCSPCacheTests_data.h */, - D49A370523873BD30065719F /* TrustDaemonTestCase.m */, - D49A370823873BF10065719F /* TrustDaemonTestCase.h */, + D477CB5B237B6E0E00C02355 /* PersonalizationTests.m */, + D477CB69237CBA2C00C02355 /* TrustDaemonTestCase.m */, + D477CB6D237CBACD00C02355 /* TrustDaemonTestCase.h */, ); name = DaemonTests; sourceTree = ""; @@ -19729,6 +19912,10 @@ D4A0F8BE211E69DF00443CA1 /* EvaluationTests */ = { isa = PBXGroup; children = ( + D477CB8A237F8DBB00C02355 /* AllowlistBlocklistTests.m */, + D477CB8D237F8EB200C02355 /* AllowlistBlocklistTests_data.h */, + D477CB86237F8B2F00C02355 /* CAIssuerTests.m */, + D477CB89237F8CB300C02355 /* CAIssuerTests_data.h */, D458C4AA214E198D0043D982 /* CTTests.m */, D4EF3222215F102F000A31A5 /* CTTests_data.h */, D4AC5766214E195300A32C01 /* ECTests.m */, @@ -19749,12 +19936,16 @@ D4FD421F217D7B27002B7EE2 /* PathScoringTests.m */, D4FD4222217D7B48002B7EE2 /* PathScoringTests_data.h */, D458C513214E27620043D982 /* PolicyTests.m */, + D477CB81237F692400C02355 /* RevocationTests.m */, + D477CB85237F6A0700C02355 /* RevocationTests_data.h */, D458C4B7214E19AF0043D982 /* SignatureAlgorithmTests.m */, D458C4B6214E19AE0043D982 /* SignatureAlgorithmTests_data.h */, + D423114223725F9F000E470A /* SMIMEPolicyTests.m */, D4056A1922712A650026E24E /* SSLPolicyTests.m */, D4056A1C22712AD80026E24E /* SSLPolicyTests_data.h */, - D49A370023873A570065719F /* RevocationTests.m */, - D49A370223873A570065719F /* RevocationTests_data.h */, + D458DAC22375FEA300E5890E /* TrustSettingsTests.m */, + D458DAC52375FEE900E5890E /* TrustSettingsTests_data.h */, + D477CB8E237F975500C02355 /* ValidTests.m */, D4AC5764214E195200A32C01 /* VerifyDateTests.m */, D4AC5765214E195300A32C01 /* VerifyDateTests_data.h */, D4A0F8CB211E6A8200443CA1 /* TrustEvaluationTestCase.h */, @@ -19781,6 +19972,7 @@ D4A0F8C0211E69F500443CA1 /* TestData */ = { isa = PBXGroup; children = ( + D4231147237261F7000E470A /* SMIMEPolicyTests-data */, D4B2966822DBFDB100DCF250 /* TestCopyProperties_ios-data */, D4D92DA72278904F0009A7CF /* nist-certs */, D4AC8BED2132127A006E9871 /* si-18-certificate-parse */, @@ -20418,7 +20610,6 @@ isa = PBXGroup; children = ( DC0BC9DB1D8B827200070CB0 /* CipherSuite.h */, - DC0BC9DC1D8B827200070CB0 /* SecureTransport.h */, ); name = "Public Headers"; path = ../Security; @@ -20428,6 +20619,7 @@ isa = PBXGroup; children = ( DC0BC9DE1D8B827200070CB0 /* sslTypes.h */, + DC0BC9DC1D8B827200070CB0 /* SecureTransport.h */, DC0BC9DF1D8B827200070CB0 /* SecureTransportPriv.h */, ); name = "Private Headers"; @@ -20668,6 +20860,7 @@ DC0BCB191D8B898100070CB0 /* SecTranslocateUtilities.cpp */, DC0BCB1A1D8B898100070CB0 /* SecTranslocateUtilities.hpp */, DC0BCB1B1D8B898100070CB0 /* SecTranslocateInterface.cpp */, + 61BDC97E242932A100A2ABD8 /* SecTranslocateEnumUtils.hpp */, ); path = lib; sourceTree = ""; @@ -20700,8 +20893,6 @@ DC0BCC3B1D8C68CF00070CB0 /* iCloudKeychainTrace.h */, EB3FBBF42320629400DF52EA /* SecABC.h */, EB3FBBF52320629400DF52EA /* SecABC.m */, - EBF3749A1DC064200065D840 /* SecADWrapper.c */, - EBF3749B1DC064200065D840 /* SecADWrapper.h */, DC0BCC3C1D8C68CF00070CB0 /* SecAKSWrappers.c */, DC0BCC3D1D8C68CF00070CB0 /* SecAKSWrappers.h */, DA5B871A2065A8410093F083 /* SecAutorelease.h */, @@ -20735,6 +20926,7 @@ DC0BCC521D8C68CF00070CB0 /* debugging.c */, DC0BCC531D8C68CF00070CB0 /* debugging.h */, DC0BCC541D8C68CF00070CB0 /* debugging_test.h */, + 5F4C21FE2489C68900F0C425 /* simulatecrash_assert.h */, DC0BCC551D8C68CF00070CB0 /* der_array.c */, DC0BCC561D8C68CF00070CB0 /* der_boolean.c */, DC0BCC571D8C68CF00070CB0 /* der_null.c */, @@ -20750,6 +20942,8 @@ DC0BCC611D8C68CF00070CB0 /* der_set.c */, DC0BCC621D8C68CF00070CB0 /* der_set.h */, DC0BCC631D8C68CF00070CB0 /* der_string.c */, + A6BF3B3123EB94A7009AF079 /* entitlements.h */, + A6BF3B3223EB94A7009AF079 /* entitlements.c */, DC0BCC641D8C68CF00070CB0 /* fileIo.c */, DC0BCC651D8C68CF00070CB0 /* fileIo.h */, 7221843E1EC6782A004C7BED /* sec_action.c */, @@ -20763,6 +20957,7 @@ E7C787311DD0FED50087FC34 /* NSURL+SOSPlistStore.m */, DC0BCC6B1D8C68CF00070CB0 /* SecDb.c */, DC0BCC6C1D8C68CF00070CB0 /* SecDb.h */, + 6C915BE3242E14BC00DBDAFB /* SecDbInternal.h */, DC0BCC6D1D8C68CF00070CB0 /* SecFileLocations.c */, DC0BCC6E1D8C68CF00070CB0 /* SecFileLocations.h */, DC0BCC6F1D8C68CF00070CB0 /* SecXPCError.h */, @@ -20786,6 +20981,7 @@ children = ( DCC78E281D8085FC00865A7C /* AppleBaselineEscrowCertificates.h */, D41149A01E7C935D00C078C7 /* AppleiPhoneDeviceCACertificates.h */, + D47A085B2486EC1A000F2C49 /* AppleExternalRootCertificates.h */, DCC78E301D8085FC00865A7C /* SecAccessControl.m */, 443381DA18A3D81400215606 /* SecAccessControlPriv.h */, DCC78E351D8085FC00865A7C /* SecBase64.c */, @@ -20814,6 +21010,9 @@ DC4269031E82EDAC002B7110 /* SecItem.m */, DCC78E5A1D8085FC00865A7C /* SecItemBackup.c */, 4CE7EA561AEAE8D60067F5BD /* SecItemBackup.h */, + 6C513A37244F007B00207D5E /* SecItemRateLimit.h */, + 6CF1B5C5245077E400FD8CC4 /* SecItemRateLimit_tests.h */, + 6C513A38244F007B00207D5E /* SecItemRateLimit.m */, 52AA92881E662A4A004301A6 /* SecBackupKeybagEntry.m */, 52AA92871E662A4A004301A6 /* SecBackupKeybagEntry.h */, DCC78E5C1D8085FC00865A7C /* SecItemConstants.c */, @@ -20862,6 +21061,7 @@ DCC78E8A1D8085FC00865A7C /* SecServerEncryptionSupport.c */, E7676DB519411DF300498DD4 /* SecServerEncryptionSupport.h */, DCC78E8C1D8085FC00865A7C /* SecSharedCredential.c */, + BE7B8E112415579800E1CF4F /* SecSharedCredential.m */, DCC78E8E1D8085FC00865A7C /* SecSignatureVerificationSupport.c */, DCC78E8F1D8085FC00865A7C /* SecSignatureVerificationSupport.h */, DCC78E901D8085FC00865A7C /* SecTrust.c */, @@ -20963,21 +21163,9 @@ name = headers; sourceTree = ""; }; - DC17899F1D779DD600B50D50 /* SecBreadcrumb */ = { - isa = PBXGroup; - children = ( - DC1787731D77915500B50D50 /* SecBreadcrumb.h */, - DC1789A01D779DEE00B50D50 /* SecBreadcrumb.c */, - DC24B5701DA3274000330B48 /* breadcrumb_regressions.h */, - DCE4E6D41D7A41E400AFB96E /* bc-10-knife-on-bread.m */, - ); - name = SecBreadcrumb; - sourceTree = ""; - }; DC1789A31D779E2400B50D50 /* Security.framework macOS */ = { isa = PBXGroup; children = ( - DC17899F1D779DD600B50D50 /* SecBreadcrumb */, DCF783091D88B4B500E694BB /* apple_csp */, DCF785E61D88B96800E694BB /* apple_cspdl */, DCF787341D88C84300E694BB /* apple_file_dl */, @@ -21019,7 +21207,6 @@ D4C263C51F8FF2A9001317EA /* generateErrStrings.pl */, DC178A321D77A1F500B50D50 /* SecDebugErrorMessages.strings */, DC178A331D77A1F500B50D50 /* SecErrorMessages.strings */, - DC178A351D77A1F500B50D50 /* framework.sb */, DC178A381D77A1F500B50D50 /* InfoPlist.strings */, DC178A3A1D77A1F500B50D50 /* TimeStampingPrefs.plist */, DC178A3B1D77A1F500B50D50 /* authorization.dfr.prompts.strings */, @@ -21106,6 +21293,8 @@ DC15F79B1E68EAD5003B9A40 /* CKKSTests+API.m */, DC6593C91ED8DA9200C19462 /* CKKSTests+CurrentPointerAPI.m */, DC9A2C5E1EB3F556008FAC27 /* CKKSTests+Coalesce.m */, + DC86122B2408AC190092E93B /* CKKSTests+ItemSyncChoice.m */, + DCBA6F2824105399009A5187 /* CKKSTests+ForwardCompatibility.m */, DC62DC6E22A8721C000D2D5D /* CKKSTests+MultiZone.h */, DC62DC6B22A87128000D2D5D /* CKKSTests+MultiZone.m */, EBC1023022EBF8AC0083D356 /* CKKSTests+LockStateTracker.m */, @@ -21140,6 +21329,7 @@ DCE7F2081F21726500DDB0F7 /* OctagonAPSReceiverTests.m */, DC9C95951F748D0B000D19E5 /* CKKSServerValidationRecoveryTests.m */, EB0E1AD723576273002B6037 /* CKKSPBFileStorageTests.m */, + EB45ED3024749E63008A1F6F /* gen_test_plist.py */, ); name = "Tests (Local)"; path = tests; @@ -21163,6 +21353,7 @@ DC8506A42097E8CF00C712EC /* iOS Resources */, DCC78E1C1D8085FC00865A7C /* add_internet_password.c */, DC52EA8E1D80CC2A00B0A59C /* builtin_commands.h */, + BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */, DCC78E1E1D8085FC00865A7C /* codesign.c */, D4A3A596217A85CB00F0A8DA /* ct_exceptions.m */, DC52EA8F1D80CC2A00B0A59C /* digest_calc.c */, @@ -21532,6 +21723,8 @@ DC5ABFD11D83511A00CF422C /* notifications.cpp */, DC5ABFD21D83511A00CF422C /* SharedMemoryServer.h */, DC5ABFD31D83511A00CF422C /* SharedMemoryServer.cpp */, + 6C755604242121F000025D78 /* keychainstasherinterface.h */, + 6C755603242121F000025D78 /* keychainstasherinterface.m */, ); name = Support; sourceTree = ""; @@ -21664,6 +21857,8 @@ DC5AC2011D83663C00CF422C /* tests */ = { isa = PBXGroup; children = ( + 6C534E0422C3E52600D4781F /* Discovery Plists */, + 6C0535F422B7043B0064BA50 /* TestHostBinaries */, EBDAF14021C75FC800EAE89F /* SharedMocks */, DC05037721409A4100A8EDB7 /* OCMockUmbrella */, F667EC541E96E8C800203D5C /* authdtests */, @@ -21684,6 +21879,7 @@ EB49B2AF202D8780003F34A0 /* secdmockaks */, 6C7E8F1D21F7BD1C008A2D56 /* SecDbBackupTests */, D4A0F8B9211E69A800443CA1 /* TrustTests */, + 6C963282242A279B00C53CE2 /* stashtester */, ); name = tests; sourceTree = ""; @@ -21754,11 +21950,13 @@ isa = PBXGroup; children = ( 0CDBCD8620AD03FB007F8EA7 /* OTClique.h */, + 0CD743BA23C3EF0D00FA0EC5 /* OTClique+Private.h */, 0C2F336A20DD643B0031A92D /* OTClique.m */, 0C8BBF0B1FCB452200580909 /* OTControl.h */, 0C8BBF0E1FCB452400580909 /* OTControl.m */, EB10A3E320356E2000E84270 /* OTConstants.h */, EB10A3E420356E2000E84270 /* OTConstants.m */, + 0C0203DE23A855B8005D0A68 /* proto */, ); name = Framework; sourceTree = ""; @@ -21873,15 +22071,16 @@ isa = PBXGroup; children = ( 6C34464D1E2534C200F9522B /* analytics */, - 0C7CEA391FE9CE3900125C79 /* behavior */, DCAE1DCF2073FCA400B4F687 /* categories */, EB27FF051E402C3C00EC9E3A /* ckksctl */, + 0CD743A723C3EC8000FA0EC5 /* OctagonTrust */, DC9B7AD31DCBF336004E9385 /* CloudKit Syncing */, 470D96651FCDE45C0065FE90 /* CoreDataKeychain */, 4771D974209A755800BA9772 /* KeychainDataclassOwner */, 47C2F1852059CB680062DE30 /* KeychainResources */, EB74CC182207E48000F1BBAD /* KeychainSettings */, - 0C8BBE831FC9DA1700580909 /* Octagon Trust */, + 6C997868242362EC008C498D /* KeychainStasher */, + 0C8BBE831FC9DA1700580909 /* OT */, 0C8BBEF61FCB402900580909 /* otctl */, DA41FDFC2241A7CD00838FB3 /* otpaird */, DC90A4BD21F275EC001300EB /* escrowrequest */, @@ -22003,14 +22202,6 @@ path = OSX/libsecurity_asn1/lib; sourceTree = ""; }; - DC88467E223742CA00738068 /* View Matching */ = { - isa = PBXGroup; - children = ( - ); - name = "View Matching"; - path = view_matching; - sourceTree = ""; - }; DC90A4BD21F275EC001300EB /* escrowrequest */ = { isa = PBXGroup; children = ( @@ -22047,10 +22238,11 @@ DC99B89720EAD4D20065B73B /* Octagon */ = { isa = PBXGroup; children = ( - DCC0A4C52152C4AB000AF654 /* Pairing */, - DC27C3C820EADD8200F7839C /* OctagonTests-BridgingHeader.h */, + DCEA0FF6213F1E6F0054A328 /* Octagon.plist */, + DC7EB928211E20DF00516452 /* OctagonDataPersistenceTests.swift */, DC85687C2284E7850088D3EF /* OctagonTestMocks.swift */, - DC4CD9822372294D00EF55FC /* OctagonTests+Helpers.swift */, + DC27C3C820EADD8200F7839C /* OctagonTests-BridgingHeader.h */, + DC99B89320EACA480065B73B /* OctagonTests-Info.plist */, DC27C3C020EAD9C300F7839C /* OctagonTests.swift */, DC4415B323610BF40087981C /* OctagonTests+Account.swift */, DC7F79B522EA4ED4001FB69A /* OctagonTests+CKKS.swift */, @@ -22058,21 +22250,23 @@ DC5BEACC2217509A001681F0 /* OctagonTests+CloudKitAccount.swift */, DC5F2BBD2310B941001ADA5D /* OctagonTests+CoreFollowUp.swift */, DC2819B822F8F6FE007829F5 /* OctagonTests+DeviceList.swift */, - DC7F6A7C233D7FAC00DF5769 /* OctagonTests+ForwardCompatibility.swift */, - 0C4CDE6D22922E360050C499 /* OctagonTests+RecoveryKey.swift */, DC07090222936BCC002711B9 /* OctagonTests+ErrorHandling.swift */, + 0CBF883A23AAD9DC00652EDD /* OctagonTests+EscrowRecords.swift */, DCDF03112284E34B008055BA /* OctagonTests+EscrowRecovery.swift */, + DC7F6A7C233D7FAC00DF5769 /* OctagonTests+ForwardCompatibility.swift */, 0C5824A322860001009E8C15 /* OctagonTests+HealthCheck.swift */, + DC4CD9822372294D00EF55FC /* OctagonTests+Helpers.swift */, + 0C4CDE6D22922E360050C499 /* OctagonTests+RecoveryKey.swift */, DC72502D229600A800493D88 /* OctagonTests+Reset.swift */, - DCB947592127534C00ED9272 /* OctagonTests+SOSUpgrade.swift */, 0C87D3E2229368A7007853B5 /* OctagonTests+SOS.swift */, - DC7EB928211E20DF00516452 /* OctagonDataPersistenceTests.swift */, - DC99B89320EACA480065B73B /* OctagonTests-Info.plist */, - DCEA0FF6213F1E6F0054A328 /* Octagon.plist */, - 5A04BAF922973EA9001848A0 /* OTFollowupTests.m */, + DCB947592127534C00ED9272 /* OctagonTests+SOSUpgrade.swift */, + 0CA1D0B223E9023100021038 /* OctagonTests+EscrowTestVectors.swift */, DCFF82702162834C00D54B02 /* OctagonTestsXPCConnections.swift */, + 5A04BAF922973EA9001848A0 /* OTFollowupTests.m */, + DCC0A4C52152C4AB000AF654 /* Pairing */, 0CBEF3422242C9BE00015691 /* TestsObjcTranslation.h */, 0CBEF3412242C9AE00015691 /* TestsObjcTranslation.m */, + DCA7F7EE23A44AA200927989 /* OctagonPolicyTests.swift */, ); name = Octagon; path = octagon; @@ -22081,16 +22275,17 @@ DC9B7AD31DCBF336004E9385 /* CloudKit Syncing */ = { isa = PBXGroup; children = ( - DC88467E223742CA00738068 /* View Matching */, DC9FD3161F857FF800C8AAC8 /* Protocol Buffers */, DCD662F21E3294DE00188186 /* CloudKit Support */, DCFE1C311F17ECC3007640C8 /* dispatch Support */, DCD662EB1E32946000188186 /* Sync Objects */, DCD662F11E32946E00188186 /* Operations */, DC3502B61E0208BE00BC0587 /* Tests (Local) */, - DCA4D2121E5651950056214F /* Tests (Live CloudKit) */, DC1ED8C21DD5538C002BDCFA /* CKKS.h */, DC1ED8C51DD55476002BDCFA /* CKKS.m */, + DC880F67243D4CC00059806D /* CKKSLogging.m */, + DCC40B0F2383786D00402CB9 /* CKKSStates.h */, + DCC40B102383786D00402CB9 /* CKKSStates.m */, DC391F9921BF2F4B00772585 /* CKKSConstants.m */, DCF7A89F1F04502300CABE89 /* CKKSControlProtocol.h */, DCF7A8A21F0450EB00CABE89 /* CKKSControlProtocol.m */, @@ -22143,19 +22338,6 @@ path = generated_source; sourceTree = ""; }; - DCA4D2121E5651950056214F /* Tests (Live CloudKit) */ = { - isa = PBXGroup; - children = ( - 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */, - 6CF4A0E11E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */, - 6CB5F4771E402D6D00DBF3F0 /* testrunner */, - 6CCDF7911E3C2D69003F2555 /* CKKSCloudKitTests.m */, - 6CB5F4751E4025AB00DBF3F0 /* CKKSCloudKitTestsInfo.plist */, - ); - name = "Tests (Live CloudKit)"; - path = tests; - sourceTree = ""; - }; DCA4D2191E569FFE0056214F /* Helpers */ = { isa = PBXGroup; children = ( @@ -22163,6 +22345,8 @@ EB4E0CD51FF36A1900CDCACC /* CKKSReachabilityTracker.m */, DC207EB61ED4EAB600D46873 /* CKKSLockStateTracker.h */, DC207EB71ED4EAB600D46873 /* CKKSLockStateTracker.m */, + DC3412E5245780B9008ABD0A /* CKKSOperationDependencies.h */, + DC3412E6245780BA008ABD0A /* CKKSOperationDependencies.m */, DCCD88E61E42622200F5AA71 /* CKKSGroupOperation.h */, DCCD88E71E42622200F5AA71 /* CKKSGroupOperation.m */, DC1447881F5764C600236DB4 /* CKKSResultOperation.h */, @@ -22462,7 +22646,6 @@ DCB344731D8A35270054D16E /* regressions */, DCB342F81D8A32A20054D16E /* lib */, DC1787281D77903700B50D50 /* SecAccessPriv.h */, - DC1787291D77903700B50D50 /* SecCertificateBundle.h */, DC17872A1D77903700B50D50 /* SecFDERecoveryAsymmetricCrypto.h */, DC17872B1D77903700B50D50 /* SecIdentitySearchPriv.h */, DC17872C1D77903700B50D50 /* SecKeychainItemExtendedAttributes.h */, @@ -22495,7 +22678,6 @@ DCB342441D8A32A20054D16E /* SecBase.cpp */, DCB342451D8A32A20054D16E /* SecBridge.h */, DCB342461D8A32A20054D16E /* SecCertificate.cpp */, - DCB342471D8A32A20054D16E /* SecCertificateBundle.cpp */, DCB342491D8A32A20054D16E /* SecIdentity.cpp */, DCB3424A1D8A32A20054D16E /* SecIdentitySearch.cpp */, DCB3424B1D8A32A20054D16E /* SecItemConstants.c */, @@ -22511,6 +22693,8 @@ DCB342551D8A32A20054D16E /* SecTrust.cpp */, DCB342561D8A32A20054D16E /* SecTrustedApplication.cpp */, DCB342571D8A32A20054D16E /* SecTrustSettings.cpp */, + 6C2D463924C88A700015C3C9 /* LegacyAPICounts.h */, + 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */, ); name = "API Bridge"; sourceTree = ""; @@ -22553,7 +22737,6 @@ DCB342A51D8A32A20054D16E /* PolicyCursor.h */, DCB342A61D8A32A20054D16E /* SecCFTypes.cpp */, DCB342A71D8A32A20054D16E /* SecCFTypes.h */, - DCB342A81D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp */, DCB342AA1D8A32A20054D16E /* StorageManager.cpp */, DCB342AB1D8A32A20054D16E /* Trust.cpp */, DCB342AC1D8A32A20054D16E /* Trust.h */, @@ -22731,64 +22914,68 @@ children = ( 1BB1CAB6232C05BC001D0C71 /* CuttlefishXPCWrapper.h */, 1BB1CAB4232C05BB001D0C71 /* CuttlefishXPCWrapper.m */, - DCB946AD22FCB88400BE4490 /* OTDetermineHSA2AccountStatusOperation.h */, - DCB946AE22FCB88500BE4490 /* OTDetermineHSA2AccountStatusOperation.m */, DCE772642290712F005862B4 /* OctagonCheckTrustStateOperation.h */, DCE772652290712F005862B4 /* OctagonCheckTrustStateOperation.m */, - DC047085218BCEF20078BDAA /* OTOperationDependencies.h */, - DC047086218BCEF20078BDAA /* OTOperationDependencies.m */, - 1B5EAAD92252ABCC008D27E7 /* OTFetchViewsOperation.h */, - 1B5EAADB2252ABCC008D27E7 /* OTFetchViewsOperation.m */, - DCBFF830222611A200C5C044 /* OTFetchCKKSKeysOperation.h */, - DCBFF831222611A200C5C044 /* OTFetchCKKSKeysOperation.m */, - DCF12671218A7579000124C6 /* OTLeaveCliqueOperation.h */, - DCF12672218A757A000124C6 /* OTLeaveCliqueOperation.m */, - DC221BA92267E2A60068DBCF /* OTUpdateTPHOperation.h */, - DC221BAA2267E2A60068DBCF /* OTUpdateTPHOperation.m */, - DCF46C2C214B1E0700319A93 /* OTUpdateTrustedDeviceListOperation.h */, - DCF46C2D214B1E0700319A93 /* OTUpdateTrustedDeviceListOperation.m */, - DC6DE897213076C000C6B56D /* OTSOSUpgradeOperation.h */, - DC6DE898213076C000C6B56D /* OTSOSUpgradeOperation.m */, - DC93F02722387A010072720A /* OTSOSUpdatePreapprovalsOperation.h */, - DC93F02822387A010072720A /* OTSOSUpdatePreapprovalsOperation.m */, - DCC67E2B20DDC07900A70A31 /* OTPrepareOperation.h */, - DCC67E2C20DDC07900A70A31 /* OTPrepareOperation.m */, - 0C4F4DE121153659007F7E20 /* OTEpochOperation.h */, - 0C4F4DDA211535E8007F7E20 /* OTEpochOperation.m */, + 0CA7020B2280D99D0085AC54 /* OTCheckHealthOperation.h */, + 0CA702082280D5600085AC54 /* OTCheckHealthOperation.m */, 0CC8A9002123AA3B005D7F6A /* OTClientVoucherOperation.h */, 0CC8A8FA2123A9EB005D7F6A /* OTClientVoucherOperation.m */, - 0CC8A9052123AF16005D7F6A /* OTJoinWithVoucherOperation.h */, - 0CC8A9012123AEF7005D7F6A /* OTJoinWithVoucherOperation.m */, - 0C66046E2134985100BFBBB8 /* OTEstablishOperation.h */, - 0C6604692134983900BFBBB8 /* OTEstablishOperation.m */, - DC0D15FF2363A1D6007F0951 /* OTSetCDPBitOperation.h */, - DC0D16002363A1D6007F0951 /* OTSetCDPBitOperation.m */, DC0D16042363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.h */, DC0D16052363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.m */, - DCFF82722162876400D54B02 /* OTResetOperation.h */, - DCFF82732162876400D54B02 /* OTResetOperation.m */, - 0C00FC85217A972E00C8BF00 /* OTLocalCuttlefishReset.h */, - 0C00FC81217A971800C8BF00 /* OTLocalCuttlefishReset.m */, + DCB946AD22FCB88400BE4490 /* OTDetermineHSA2AccountStatusOperation.h */, + DCB946AE22FCB88500BE4490 /* OTDetermineHSA2AccountStatusOperation.m */, + 0C87D3DA229326CB007853B5 /* OTEnsureOctagonKeyConsistency.h */, + 0C87D3D6229326A2007853B5 /* OTEnsureOctagonKeyConsistency.m */, + 0C64C07F2485A54100D84A5D /* OTPreloadOctagonKeysOperation.h */, + 0C64C07C2485A53000D84A5D /* OTPreloadOctagonKeysOperation.m */, + 0C4F4DE121153659007F7E20 /* OTEpochOperation.h */, + 0C4F4DDA211535E8007F7E20 /* OTEpochOperation.m */, + 0C66046E2134985100BFBBB8 /* OTEstablishOperation.h */, + 0C6604692134983900BFBBB8 /* OTEstablishOperation.m */, + DCBFF830222611A200C5C044 /* OTFetchCKKSKeysOperation.h */, + DCBFF831222611A200C5C044 /* OTFetchCKKSKeysOperation.m */, + 1B5EAAD92252ABCC008D27E7 /* OTFetchViewsOperation.h */, + 1B5EAADB2252ABCC008D27E7 /* OTFetchViewsOperation.m */, + 0CC8A9052123AF16005D7F6A /* OTJoinWithVoucherOperation.h */, + 0CC8A9012123AEF7005D7F6A /* OTJoinWithVoucherOperation.m */, + DCF12671218A7579000124C6 /* OTLeaveCliqueOperation.h */, + DCF12672218A757A000124C6 /* OTLeaveCliqueOperation.m */, DC7F79B822EA5C72001FB69A /* OTLocalCKKSResetOperation.h */, DC7F79B922EA5C72001FB69A /* OTLocalCKKSResetOperation.m */, + 0C00FC85217A972E00C8BF00 /* OTLocalCuttlefishReset.h */, + 0C00FC81217A971800C8BF00 /* OTLocalCuttlefishReset.m */, + DC6E02122405DDC300C61335 /* OTModifyUserControllableViewStatusOperation.h */, + DC6E02132405DDC400C61335 /* OTModifyUserControllableViewStatusOperation.m */, + DC047085218BCEF20078BDAA /* OTOperationDependencies.h */, + DC047086218BCEF20078BDAA /* OTOperationDependencies.m */, + DCC67E2B20DDC07900A70A31 /* OTPrepareOperation.h */, + DCC67E2C20DDC07900A70A31 /* OTPrepareOperation.m */, DC8757F2218D2003000E65F1 /* OTRemovePeersOperation.h */, DC8757F3218D2003000E65F1 /* OTRemovePeersOperation.m */, - DCC5417F225C05170095D926 /* OTUploadNewCKKSTLKsOperation.h */, - DCC54180225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m */, DC7250352296056000493D88 /* OTResetCKKSZonesLackingTLKsOperation.h */, DC7250362296056000493D88 /* OTResetCKKSZonesLackingTLKsOperation.m */, - 0CB8DC962194B1300021A7C8 /* OTVouchWithBottleOperation.h */, - 0CB8DC992194B1440021A7C8 /* OTVouchWithBottleOperation.m */, - 0C1B8BB3223323710094D5DA /* OTVouchWithRecoveryKeyOperation.h */, - 0C1B8BB52233241E0094D5DA /* OTVouchWithRecoveryKeyOperation.m */, + DCFF82722162876400D54B02 /* OTResetOperation.h */, + DCFF82732162876400D54B02 /* OTResetOperation.m */, + DC0D15FF2363A1D6007F0951 /* OTSetCDPBitOperation.h */, + DC0D16002363A1D6007F0951 /* OTSetCDPBitOperation.m */, 0CD3D518224047B400024755 /* OTSetRecoveryKeyOperation.h */, 0CD3D5152240479600024755 /* OTSetRecoveryKeyOperation.m */, + DC93F02722387A010072720A /* OTSOSUpdatePreapprovalsOperation.h */, + DC93F02822387A010072720A /* OTSOSUpdatePreapprovalsOperation.m */, + DC6DE897213076C000C6B56D /* OTSOSUpgradeOperation.h */, + DC6DE898213076C000C6B56D /* OTSOSUpgradeOperation.m */, 0CDD6F78226E62BC009094C2 /* OTTriggerEscrowUpdateOperation.h */, 0CDD6F76226E62AD009094C2 /* OTTriggerEscrowUpdateOperation.m */, - 0CA7020B2280D99D0085AC54 /* OTCheckHealthOperation.h */, - 0CA702082280D5600085AC54 /* OTCheckHealthOperation.m */, - 0C87D3DA229326CB007853B5 /* OTEnsureOctagonKeyConsistency.h */, - 0C87D3D6229326A2007853B5 /* OTEnsureOctagonKeyConsistency.m */, + DC221BA92267E2A60068DBCF /* OTUpdateTPHOperation.h */, + DC221BAA2267E2A60068DBCF /* OTUpdateTPHOperation.m */, + DCF46C2C214B1E0700319A93 /* OTUpdateTrustedDeviceListOperation.h */, + DCF46C2D214B1E0700319A93 /* OTUpdateTrustedDeviceListOperation.m */, + DCC5417F225C05170095D926 /* OTUploadNewCKKSTLKsOperation.h */, + DCC54180225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m */, + 0CB8DC962194B1300021A7C8 /* OTVouchWithBottleOperation.h */, + 0CB8DC992194B1440021A7C8 /* OTVouchWithBottleOperation.m */, + 0C1B8BB3223323710094D5DA /* OTVouchWithRecoveryKeyOperation.h */, + 0C1B8BB52233241E0094D5DA /* OTVouchWithRecoveryKeyOperation.m */, ); name = Operations; sourceTree = ""; @@ -22840,6 +23027,7 @@ DCC78C5F1D8085D800865A7C /* secd-64-circlereset.m */, 48CC58971DA5FF0B00EBD9DB /* secd-66-account-recovery.m */, 483E79891DC875F2005C0008 /* secd-67-prefixedKeyIDs.m */, + 487A65F3245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m */, DCC78C601D8085D800865A7C /* secd-70-engine.m */, DCC78C611D8085D800865A7C /* secd-70-engine-corrupt.m */, DCC78C621D8085D800865A7C /* secd-70-engine-smash.m */, @@ -22867,7 +23055,6 @@ DCDCC7DD1D9B54DF006487E8 /* secd-202-recoverykey.m */, 7281E08E1DFD0D810021E1B7 /* secd-210-keyinterest.m */, 522B28081E64B48E002B5638 /* secd-230-keybagtable.m */, - DCFAEDD11D9998DD005187E4 /* secd-668-ghosts.m */, DCC78C791D8085D800865A7C /* SOSAccountTesting.h */, DCC78C7A1D8085D800865A7C /* SecdTestKeychainUtilities.c */, DCC78C7B1D8085D800865A7C /* SecdTestKeychainUtilities.h */, @@ -22904,6 +23091,8 @@ DCC78C991D8085D800865A7C /* SecItemSchema.h */, DCC78C9A1D8085D800865A7C /* SecItemServer.c */, DCC78C9B1D8085D800865A7C /* SecItemServer.h */, + FC637229237B5CF800973738 /* SecItemServer+SWC.h */, + FC63722A237B5CF900973738 /* SecItemServer+SWC.m */, DCC78C9C1D8085D800865A7C /* SecItemBackupServer.c */, DCC78C9D1D8085D800865A7C /* SecItemBackupServer.h */, DCC78C9E1D8085D800865A7C /* SecKeybagSupport.c */, @@ -23256,23 +23445,6 @@ path = "si-66-smime"; sourceTree = ""; }; - DCC78DF61D8085FC00865A7C /* si-67-sectrust-blocklist */ = { - isa = PBXGroup; - children = ( - DCC78DEC1D8085FC00865A7C /* Global Trustee.cer.h */, - DCC78DED1D8085FC00865A7C /* UTN-USERFirst-Hardware.cer.h */, - DCC78DEE1D8085FC00865A7C /* addons.mozilla.org.cer.h */, - DCC78DEF1D8085FC00865A7C /* login.live.com.cer.h */, - DCC78DF01D8085FC00865A7C /* login.skype.com.cer.h */, - DCC78DF11D8085FC00865A7C /* login.yahoo.com.1.cer.h */, - DCC78DF21D8085FC00865A7C /* login.yahoo.com.2.cer.h */, - DCC78DF31D8085FC00865A7C /* login.yahoo.com.cer.h */, - DCC78DF41D8085FC00865A7C /* mail.google.com.cer.h */, - DCC78DF51D8085FC00865A7C /* www.google.com.cer.h */, - ); - path = "si-67-sectrust-blocklist"; - sourceTree = ""; - }; DCC78E121D8085FC00865A7C /* secitem */ = { isa = PBXGroup; children = ( @@ -23288,8 +23460,6 @@ DCC78DBD1D8085FC00865A7C /* si-21-sectrust-asr.c */, DCC78DBE1D8085FC00865A7C /* si-22-sectrust-iap.c */, DCC78DBF1D8085FC00865A7C /* si-22-sectrust-iap.h */, - DCC78DC01D8085FC00865A7C /* si-23-sectrust-ocsp.c */, - D46513072097954B005D93FE /* si-23-sectrust-ocsp.h */, DCC78DC11D8085FC00865A7C /* si-24-sectrust-digicert-malaysia.c */, DCC78DC21D8085FC00865A7C /* si-24-sectrust-diginotar.c */, DCC78DC31D8085FC00865A7C /* si-24-sectrust-itms.c */, @@ -23297,8 +23467,6 @@ DC0B62261D90973900D43BCB /* si-25-cms-skid.h */, DC0B62271D90973900D43BCB /* si-25-cms-skid.m */, DCC78DC61D8085FC00865A7C /* si-26-sectrust-copyproperties.c */, - DCC78DC81D8085FC00865A7C /* si-28-sectrustsettings.m */, - DCC78DC91D8085FC00865A7C /* si-28-sectrustsettings.h */, D4AA0D9922FB959600D77FA4 /* si-29-cms-chain-mode.m */, D4AA0D9C22FB962300D77FA4 /* si-29-cms-chain-mode.h */, DCC78DCA1D8085FC00865A7C /* si-30-keychain-upgrade.c */, @@ -23336,23 +23504,18 @@ DCC78DE81D8085FC00865A7C /* si-65-cms-cert-policy.c */, DCC78DEA1D8085FC00865A7C /* si-66-smime */, DCC78DEB1D8085FC00865A7C /* si-66-smime.c */, - DCC78DF61D8085FC00865A7C /* si-67-sectrust-blocklist */, - DCC78DF71D8085FC00865A7C /* si-67-sectrust-blocklist.c */, DCC78DF81D8085FC00865A7C /* si-68-secmatchissuer.c */, DCC78DF91D8085FC00865A7C /* si-69-keydesc.c */, DCC78DFA1D8085FC00865A7C /* si-70-sectrust-unified.c */, DCC78DFB1D8085FC00865A7C /* si-71-mobile-store-policy.c */, DCC78DFC1D8085FC00865A7C /* si-72-syncableitems.c */, DCC78DFD1D8085FC00865A7C /* si-73-secpasswordgenerate.c */, - DCC78DFE1D8085FC00865A7C /* si-74-OTAPKISigner.c */, DCC78DFF1D8085FC00865A7C /* si-76-shared-credentials.c */, DCC78E001D8085FC00865A7C /* si_77_SecAccessControl.c */, DCC78E011D8085FC00865A7C /* si-78-query-attrs.c */, DCC78E021D8085FC00865A7C /* si-80-empty-data.c */, DCC78E051D8085FC00865A7C /* si-82-token-ag.c */, DCC78E061D8085FC00865A7C /* si-83-seccertificate-sighashalg.c */, - BE6215BD1DB6E69100961E15 /* si-84-sectrust-allowlist.m */, - BE9B8B49202BB4A10081EF87 /* si-88-sectrust-valid.m */, DCC78E0B1D8085FC00865A7C /* si-89-cms-hash-agility.m */, DCC78E0D1D8085FC00865A7C /* si-90-emcs.m */, DCC78E0E1D8085FC00865A7C /* si-95-cms-basic.c */, @@ -24046,6 +24209,12 @@ isa = PBXGroup; children = ( DCA4D2191E569FFE0056214F /* Helpers */, + DC947E812463831E005B8669 /* CKKSCheckKeyHierarchyOperation.h */, + DC947E832463831F005B8669 /* CKKSCheckKeyHierarchyOperation.m */, + DCB5516A247F3DB50009A859 /* CKKSCreateCKZoneOperation.h */, + DCB5516B247F3DB50009A859 /* CKKSCreateCKZoneOperation.m */, + DCB55173247F48290009A859 /* CKKSDeleteCKZoneOperation.h */, + DCB55174247F48290009A859 /* CKKSDeleteCKZoneOperation.m */, DC5BB4F01E0C86800010F836 /* CKKSIncomingQueueOperation.h */, DC5BB4F11E0C86800010F836 /* CKKSIncomingQueueOperation.m */, DC5BB4FC1E0C98320010F836 /* CKKSOutgoingQueueOperation.h */, @@ -24056,6 +24225,8 @@ DCD662F41E329B6800188186 /* CKKSNewTLKOperation.m */, DCBF2F831F913EF000ED0CA4 /* CKKSHealTLKSharesOperation.h */, DCBF2F841F913EF000ED0CA4 /* CKKSHealTLKSharesOperation.m */, + DC061A6E246211DD0026ADB3 /* CKKSLocalResetOperation.h */, + DC061A70246211DE0026ADB3 /* CKKSLocalResetOperation.m */, DC7A17EB1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.h */, DC7A17EC1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.m */, DC5F65AC2225C22C0051E9FA /* CKKSProvideKeySetOperation.h */, @@ -24088,8 +24259,6 @@ DC222CA91E08C57400B09171 /* CloudKitDependencies.h */, DCEA5D831E2F14810089CF55 /* OctagonAPSReceiver.h */, DCEA5D841E2F14810089CF55 /* OctagonAPSReceiver.m */, - DCEA5D951E3014250089CF55 /* CKKSZone.h */, - DCEA5D961E3014250089CF55 /* CKKSZone.m */, DC18F76D1E43E116006B8B43 /* CKKSFetchAllRecordZoneChangesOperation.h */, DC18F76E1E43E116006B8B43 /* CKKSFetchAllRecordZoneChangesOperation.m */, DCFB12C31E95A4C000510F5F /* CKKSAccountStateTracker.h */, @@ -24106,23 +24275,23 @@ isa = PBXGroup; children = ( BE7089991F9AAF57001ACC20 /* generated */, - BE7089911F9AA027001ACC20 /* TPPBVoucher.proto */, - BE7089CB1FA3B19A001ACC20 /* TPPBPeerDynamicInfo.proto */, + BEC373A820D810DA00DBDF5B /* TPPBAncientEpoch.proto */, + DC88466922373A4000738068 /* TPPBDictionaryMatchingRule.proto */, BEC3739B20CF2AA200DBDF5B /* TPPBDisposition.proto */, BEC373C120D8224A00DBDF5B /* TPPBDispositionEntry.proto */, - BEC373A820D810DA00DBDF5B /* TPPBAncientEpoch.proto */, - BEC373A620D810D800DBDF5B /* TPPBPolicyProhibits.proto */, - BEC373A720D810D900DBDF5B /* TPPBUnknownMachineID.proto */, - BE7089CC1FA3B332001ACC20 /* TPPBPeerStableInfo.proto */, + BE7089CB1FA3B19A001ACC20 /* TPPBPeerDynamicInfo.proto */, BE7089DB1FA407E4001ACC20 /* TPPBPeerPermanentInfo.proto */, - BE7089D91FA3F0AF001ACC20 /* TPPBPolicySecret.proto */, + BE7089CC1FA3B332001ACC20 /* TPPBPeerStableInfo.proto */, 6C0C807D20EAF86100334E33 /* TPPBPolicyDocument.proto */, 6C0C807F20EAFB9600334E33 /* TPPBPolicyCategoriesByView.proto */, 6C0C808020EAFB9600334E33 /* TPPBPolicyModelToCategory.proto */, 6C0C808320EAFD7A00334E33 /* TPPBPolicyIntroducersByCategory.proto */, - 6C70D8D520EBDE4500AB6FAF /* TPPBPolicyRedaction.proto */, 1B8341B72239AD39002BF18A /* TPPBPolicyKeyViewMapping.proto */, - DC88466922373A4000738068 /* TPPBDictionaryMatchingRule.proto */, + BEC373A620D810D800DBDF5B /* TPPBPolicyProhibits.proto */, + 6C70D8D520EBDE4500AB6FAF /* TPPBPolicyRedaction.proto */, + BE7089D91FA3F0AF001ACC20 /* TPPBPolicySecret.proto */, + BEC373A720D810D900DBDF5B /* TPPBUnknownMachineID.proto */, + BE7089911F9AA027001ACC20 /* TPPBVoucher.proto */, ); path = proto; sourceTree = ""; @@ -24130,6 +24299,8 @@ DCE0777C21ADE96C002662FD /* generated */ = { isa = PBXGroup; children = ( + 6C6AF17D221A06F70091CE0A /* SecDbKeychainSerializedMetadataKey.h */, + 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */, 47922D501FAA7DF60008F7E0 /* SecDbKeychainSerializedItemV7.h */, 47922D511FAA7DF70008F7E0 /* SecDbKeychainSerializedItemV7.m */, 47922D371FAA7C040008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.h */, @@ -24263,6 +24434,7 @@ DC24B5641DA326B900330B48 /* Info.plist */, DC24B5651DA326B900330B48 /* mechanism.h */, DC24B5661DA326B900330B48 /* object.h */, + F681C3AA2386B8B40083F22C /* PreloginUserDb.h */, DC24B5671DA326B900330B48 /* process.h */, DC24B5681DA326B900330B48 /* rule.h */, DC24B5691DA326B900330B48 /* server.h */, @@ -24281,6 +24453,7 @@ DCE4E8AB1D7F353900AFB96E /* main.c */, DCE4E8AC1D7F353900AFB96E /* mechanism.c */, DCE4E8AD1D7F353900AFB96E /* object.c */, + F681C3A82386B8B40083F22C /* PreloginUserDb.m */, DCE4E8AE1D7F353900AFB96E /* process.c */, DCE4E8AF1D7F353900AFB96E /* rule.c */, DCE4E8B01D7F353900AFB96E /* server.c */, @@ -25070,7 +25243,6 @@ 0C0C88771CCEC5BD00617D1B /* si-82-sectrust-ct-data */, DCE4E72E1D7A436300AFB96E /* si-82-sectrust-ct-logs.plist */, D4C6C5C71FB2AD3F007EA57E /* si-87-sectrust-name-constraints */, - BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */, 4C50ACFB1410671D00EE92DE /* DigiNotar */, 79679E241462028800CF997F /* DigicertMalaysia */, E710C74B1331946500F85568 /* Supporting Files */, @@ -25202,6 +25374,13 @@ E7FCBE401314471B000DE34E /* Frameworks */ = { isa = PBXGroup; children = ( + D47A55892466100A0039285D /* MSUDataAccessor.framework */, + 6C99787C242364FB008C498D /* CoreFoundation.framework */, + 6C997879242364E5008C498D /* Foundation.framework */, + F6B1B48924144B5E00CB3E3F /* libctkloginhelperlite.a */, + 0CCC22D523F39B2E00E1FCD0 /* CoreCDP.framework */, + 0CCC22B123F38B5B00E1FCD0 /* libsqlite3.0.tbd */, + DA2F591523A32BB400C30285 /* SoftLinking.framework */, DC89608C2395C75500D339D9 /* CoreServices.framework */, BEC6A9142331992800080069 /* Network.framework */, D47AB2CA2356AD72005A3801 /* Network.framework */, @@ -25219,14 +25398,12 @@ 0C75AC642141F18D0073A2F9 /* KeychainCircle.framework */, D4B68C5C211A7D98009FED69 /* libDER.a */, EB490153211C0026001E6D6A /* UserManagement.framework */, - 472E184F20D9A20D00ECE7C9 /* libcoreauthd_client.a */, 475EDD0720D9A031009D2409 /* LocalAuthenticationPrivateUI.framework */, 475EDD0520D98CE2009D2409 /* LocalAuthentication.framework */, 475EDD0320D98CD0009D2409 /* libctkclient.a */, 475EDD0120D98C81009D2409 /* libaks_acl.a */, 475EDCFF20D98C64009D2409 /* IOKit.framework */, 475EDCFD20D98C53009D2409 /* libaks.a */, - 475EDCFB20D98C3C009D2409 /* libDER.a */, 475EDCF920D98C0D009D2409 /* CryptoTokenKit.framework */, 475EDCF720D98BF6009D2409 /* CoreCDP.framework */, 475EDCF520D98BCF009D2409 /* libACM.a */, @@ -25362,7 +25539,6 @@ EB2CA4D81D2C28C800AB770F /* libaks.a */, 4432AF8C1A01472C000958DC /* libaks_acl.a */, DC1789181D77998C00B50D50 /* libbsm.dylib */, - E7F482A51C75453900390FDB /* libcoreauthd_test_client.a */, 0CFC029B1D41650700E6283B /* libcoretls.dylib */, E7F482A21C7544E600390FDB /* libctkclient_test.a */, EBE54D771BE33227000C4856 /* libmis.dylib */, @@ -25427,14 +25603,12 @@ DC5225091E402D8B0021640A /* PlatformLibraries.xcconfig */, DC976C581E3AC5E50012A6DD /* PlatformFeatures.xcconfig */, EB2CA5561D2C30F700AB770F /* Security.xcconfig */, - D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */, DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */, DC8E04901D7F6780006D80EB /* lib_ios.xcconfig */, DC71D8DD1D94CF3C0065FB93 /* lib_ios_shim.xcconfig */, D47C56AB1DCA831C00E18518 /* lib_ios_x64.xcconfig */, D47C56AF1DCA841D00E18518 /* lib_ios_x64_shim.xcconfig */, DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */, - BE8351D41EC0EEDD00ACD5FD /* framework_requiring_modern_objc_runtime.xcconfig */, EBF9AE171F536D0300FECBF7 /* Version.xcconfig */, DC340C53208E7BAE004D7EEC /* swift_binary.xcconfig */, DCC1849220EEEC4400F3B26C /* security_framework.xcconfig */, @@ -25550,6 +25724,8 @@ EB80211C1D3D9044008540C4 /* Modules */ = { isa = PBXGroup; children = ( + 0CF7613D23F24B5D00A3C3AD /* KeychainCircle.modulemap */, + 0CF7613F23F24B5E00A3C3AD /* OctagonTrust.modulemap */, EB8021411D3D90BB008540C4 /* Security.iOS.modulemap */, EB8021421D3D90BB008540C4 /* Security.macOS.modulemap */, 617570BA22C2D19E00EFBA37 /* Security.macOS.private.modulemap */, @@ -25568,6 +25744,9 @@ EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */ = { isa = PBXGroup; children = ( + 3E88361224F0693200E9F4D6 /* secseccodeapitest */, + 6CF33CA2238714C900D1E75D /* bats_utd_plist.h */, + 6CF33CA4238714C900D1E75D /* PreprocessPlist.sh */, EB9C1DAD1BDFD49400F89272 /* Security.plist */, EBDAA7E320EC46CF003EA6E5 /* SecurityLocalKeychain.plist */, EBE202752092913500B48020 /* SecurityInduceLowDisk.plist */, @@ -25662,6 +25841,22 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 0CD743A123C3EC8000FA0EC5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C468FE323C7D487006F4582 /* OTEscrowRecordMetadata.h in Headers */, + 0C468FF523C7D4D5006F4582 /* OTICDPRecordSilentContext.h in Headers */, + 0CD743AA23C3EC8000FA0EC5 /* OctagonTrust.h in Headers */, + 0C468FF323C7D4D5006F4582 /* OTICDPRecordContext.h in Headers */, + 0C468FE523C7D487006F4582 /* OTEscrowRecordMetadataClientMetadata.h in Headers */, + 0C468FEF23C7D4D5006F4582 /* OTCDPRecoveryInformation.h in Headers */, + 0C468FE123C7D487006F4582 /* OTEscrowRecord.h in Headers */, + 0C468FF123C7D4D5006F4582 /* OTEscrowAuthenticationInformation.h in Headers */, + 0C9F65AD23E3AD2E00B1A2C5 /* OTEscrowTranslation.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 225394B01E3080A600D3CD9B /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -25707,6 +25902,7 @@ 4718AEB5205B39C40068EC3F /* CloudKitCategories.h in Headers */, 4718AEB6205B39C40068EC3F /* CKKSDeviceStateEntry.h in Headers */, 4718AEB8205B39C40068EC3F /* CKKSAccountStateTracker.h in Headers */, + 6C6AF183221A07240091CE0A /* SecDbKeychainSerializedMetadataKey.h in Headers */, 4718AEB9205B39C40068EC3F /* CKKSZoneStateEntry.h in Headers */, DC5A01E921BB428500D87AB9 /* CKKSTLKShare.h in Headers */, 4718AEBA205B39C40068EC3F /* CKKSTLKShareRecord.h in Headers */, @@ -25775,13 +25971,14 @@ DC3C73541D837B1900F6A832 /* SOSCloudCircle.h in Headers */, 524492941AFD6D480043695A /* der_plist.h in Headers */, DC3C73531D837AF800F6A832 /* SOSPeerInfo.h in Headers */, - 5A061198229ED8F3006AF14A /* NSDate+SFAnalytics.h in Headers */, D47079F321128C74005BCFDA /* SecCMS.h in Headers */, + A6BC648824897C5E00A21CD7 /* CSCommonPriv.h in Headers */, 4C12828D0BB4957D00985BB0 /* SecTrustSettingsPriv.h in Headers */, DCD45355209A5B260086CBFC /* si-cms-signing-identity-p12.h in Headers */, 1BE85ED5235CEC250051E1D8 /* sslDeprecated.h in Headers */, CDDE9BD11729ABFA0013B0E8 /* SecPasswordGenerate.h in Headers */, 4C7072860AC9EA4F007CC205 /* SecKey.h in Headers */, + 0CD743BB23C3EF1D00FA0EC5 /* OTClique+Private.h in Headers */, D4B3B1CC2115150D00A43409 /* SecCmsDigestedData.h in Headers */, 476541651F339F6300413F65 /* SecdWatchdog.h in Headers */, D47079FB211355C9005BCFDA /* CMSEncoder.h in Headers */, @@ -25790,10 +25987,10 @@ DCD7EE981F4F4DE9007D9804 /* SecBase64.h in Headers */, 4791B4652118BBFF00977C3F /* OTControlProtocol.h in Headers */, 4C7073CA0ACB2BAD007CC205 /* SecRSAKey.h in Headers */, + A6BC6491248B0AB400A21CD7 /* SecStaticCodePriv.h in Headers */, EB6928C51D9C9C6E00062A18 /* SecRecoveryKey.h in Headers */, 4C0B906E0ACCBD240077CD03 /* SecFramework.h in Headers */, EBF252222155E910000204D6 /* OTJoiningConfiguration.h in Headers */, - EB9B283321C7755700173DC2 /* OTDefines.h in Headers */, 4C7391790B01745000C4CBFA /* vmdh.h in Headers */, 6CDB5FFB1FA78D2C00410924 /* SFAnalyticsMultiSampler.h in Headers */, 4C64E01C0B8FBC71009B306C /* SecIdentity.h in Headers */, @@ -25871,6 +26068,7 @@ 6C8CE6C11FA248DA0032ADF0 /* SFAnalyticsActivityTracker+Internal.h in Headers */, D4707A262113EBC1005BCFDA /* SecCmsDecoder.h in Headers */, DC3C7ABA1D838C9F00F6A832 /* sslTypes.h in Headers */, + 6C06CB902408602900025303 /* SecItemInternal.h in Headers */, 6CE3654B1FA100D00012F6AB /* SFAnalytics.h in Headers */, 5A442FA6233C34FE00918373 /* SecExperimentInternal.h in Headers */, 4AF7000515AFB73800B9D400 /* SecOTRSession.h in Headers */, @@ -25898,7 +26096,6 @@ 22A23B3D1E3AAC9800C41830 /* SecStaticCode.h in Headers */, 22A23B3E1E3AAC9800C41830 /* SecRequirement.h in Headers */, DC9C95BE1F79DC5F000D19E5 /* CKKSControl.h in Headers */, - 0CBFEACC200FCD33009A60E9 /* SFSignInAnalytics.h in Headers */, DC3C7AB61D838C2D00F6A832 /* SecAsn1Types.h in Headers */, 1B2BD397235E050E009A8624 /* Security-tapi.h in Headers */, D43D8B2D20AB8A54005BEEC4 /* Security.apinotes in Headers */, @@ -25937,6 +26134,7 @@ BEC373CB20D822DA00DBDF5B /* TPPBDispositionEntry.h in Headers */, BEF88C7F1EB000BE00357577 /* TPModel.h in Headers */, BE61F5AF1EB0060C00556CCF /* TrustedPeers.h in Headers */, + DCC03FA423FF521100A4DA3F /* TPSyncingPolicy.h in Headers */, BEF88C891EB000BE00357577 /* TPPolicy.h in Headers */, BEF88C871EB000BE00357577 /* TPPeerStableInfo.h in Headers */, BEF88C7B1EB000BE00357577 /* TPDecrypter.h in Headers */, @@ -26141,6 +26339,7 @@ DC0BC7CF1D8B7B7F00070CB0 /* cssmconfig.h in Headers */, DC0BC7DB1D8B7B7F00070CB0 /* oidsbase.h in Headers */, DC0BC7D51D8B7B7F00070CB0 /* cssmspi.h in Headers */, + 6C97434824D1C8CB00A2025C /* LegacyAPICounts.h in Headers */, DC0BC7D01D8B7B7F00070CB0 /* cssmcspi.h in Headers */, DC0BC7AD1D8B773000070CB0 /* modload_static.h in Headers */, DC0BC7D21D8B7B7F00070CB0 /* cssmerr.h in Headers */, @@ -26410,8 +26609,8 @@ DC0BCDB21D8C6A1F00070CB0 /* SecInternalReleasePriv.h in Headers */, DC0BCD831D8C6A1E00070CB0 /* SecCFWrappers.h in Headers */, DC0BCDB01D8C6A1F00070CB0 /* SecAppleAnchorPriv.h in Headers */, + 5F4C22002489C6AB00F0C425 /* simulatecrash_assert.h in Headers */, B61577EC1F201562004A3930 /* SecPaddingConfigurationsPriv.h in Headers */, - EB4B6E261DC0683600AFC494 /* SecADWrapper.h in Headers */, DC36895921235F2A003A3735 /* SecAKSWrappers.h in Headers */, DC0BCDAA1D8C6A1F00070CB0 /* SecXPCError.h in Headers */, 72CDF5131EC679A4002D233B /* sec_action.h in Headers */, @@ -26474,13 +26673,11 @@ DC2671071F3E8A0900816EED /* SecECKey.h in Headers */, DC17877C1D77919500B50D50 /* SecBasePriv.h in Headers */, 5F00F95C230614AD00B832E0 /* SecImportExportPriv.h in Headers */, - DC1787741D77915500B50D50 /* SecBreadcrumb.h in Headers */, 6CB420AB2051FDE000FF2D44 /* LocalKeychainAnalytics.h in Headers */, 1BE85ED0235CEB620051E1D8 /* cms-tapi.h in Headers */, DC1787761D77916600B50D50 /* SecCFAllocator.h in Headers */, DC0C343A21FA7DEB00417D04 /* SecEscrowRequest.h in Headers */, DC17859F1D778C8D00B50D50 /* SecCertificate.h in Headers */, - DC1787361D77903700B50D50 /* SecCertificateBundle.h in Headers */, DC1785501D778ACD00B50D50 /* SecCertificateOIDs.h in Headers */, DC1787821D7791BE00B50D50 /* SecCertificatePriv.h in Headers */, 5A6D1B9E20810EF40057CAC8 /* SecProtocolTypes.h in Headers */, @@ -26492,7 +26689,6 @@ DC1787511D7790A500B50D50 /* SecCodePriv.h in Headers */, DC1787521D7790A500B50D50 /* SecCodeSigner.h in Headers */, DC1785301D778A0100B50D50 /* SecCustomTransform.h in Headers */, - 0CBFEACD200FCD33009A60E9 /* SFSignInAnalytics.h in Headers */, 5A442FA8233C34FF00918373 /* SecExperimentInternal.h in Headers */, DC1787771D77916A00B50D50 /* SecDH.h in Headers */, DC1785311D778A0100B50D50 /* SecDecodeTransform.h in Headers */, @@ -26517,7 +26713,6 @@ DC1787781D77917100B50D50 /* SecItemBackup.h in Headers */, DC17877F1D7791A800B50D50 /* SecItemPriv.h in Headers */, DC17859D1D778C8000B50D50 /* SecKey.h in Headers */, - EB9B283421C7755800173DC2 /* OTDefines.h in Headers */, 6CC952481FB4CB2C0051A823 /* SFAnalytics+Internal.h in Headers */, DC1787801D7791AD00B50D50 /* SecKeyPriv.h in Headers */, DC1785521D778ACD00B50D50 /* SecKeychain.h in Headers */, @@ -26532,6 +26727,7 @@ DCA9D84221FFE62A00B27421 /* EscrowRequestXPCProtocol.h in Headers */, DC1786F91D778F2500B50D50 /* SecNullTransform.h in Headers */, DC17873D1D77903700B50D50 /* SecPassword.h in Headers */, + 6C06CB912408602A00025303 /* SecItemInternal.h in Headers */, DC1787791D77917700B50D50 /* SecPasswordGenerate.h in Headers */, 1BE85ED6235CEC250051E1D8 /* sslDeprecated.h in Headers */, F6EEF77521675EF000FB7F79 /* AuthorizationTrampolinePriv.h in Headers */, @@ -26549,6 +26745,7 @@ DC1785351D778A0100B50D50 /* SecReadTransform.h in Headers */, DC17873F1D77903700B50D50 /* SecRecoveryPassword.h in Headers */, 6CE3654C1FA100D10012F6AB /* SFAnalytics.h in Headers */, + D4593EFF24C131180069F577 /* SecTrustStore.h in Headers */, DC17858B1D778B8000B50D50 /* SecRequirement.h in Headers */, DC1787551D7790A500B50D50 /* SecRequirementPriv.h in Headers */, DC17877A1D77917D00B50D50 /* SecServerEncryptionSupport.h in Headers */, @@ -26633,7 +26830,6 @@ D4B3B1D921151BBF00A43409 /* SecCmsSignedData.h in Headers */, DC17857E1D778B4A00B50D50 /* oidscrl.h in Headers */, DC1787701D77911D00B50D50 /* osKeyTemplates.h in Headers */, - 5A061199229ED8F4006AF14A /* NSDate+SFAnalytics.h in Headers */, D4707A302114C316005BCFDA /* SecCmsDigestContext.h in Headers */, DC2C5F511F0D935300FEBDA7 /* CKKSControlProtocol.h in Headers */, AA7C71B72185429900EB314F /* SecProtocolTypesPriv.h in Headers */, @@ -26648,6 +26844,7 @@ 4723C9C31F152EB60082882F /* SFObjCType.h in Headers */, DCB3323C1F46833E00178C30 /* SecLogging.h in Headers */, DC9C95BD1F79DC5A000D19E5 /* CKKSControl.h in Headers */, + 0CD743BC23C3EF1E00FA0EC5 /* OTClique+Private.h in Headers */, DC3C73561D837B9B00F6A832 /* SOSPeerInfoPriv.h in Headers */, EB6928C61D9C9C6F00062A18 /* SecRecoveryKey.h in Headers */, D4B3B1D0211516A100A43409 /* SecCmsEncryptedData.h in Headers */, @@ -26679,6 +26876,7 @@ DC0FA6B02291F63F00FE01C4 /* OctagonPendingFlag.h in Headers */, 47922D421FAA7C240008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.h in Headers */, DCFE1C341F17ECE5007640C8 /* CKKSCondition.h in Headers */, + DCB55175247F48290009A859 /* CKKSDeleteCKZoneOperation.h in Headers */, DC1E5AB623063A4E00918162 /* CKKSPeerProvider.h in Headers */, DC047081218BB21E0078BDAA /* OTCuttlefishAccountStateHolder.h in Headers */, DC1DA65E1E4554620094CE7F /* CKKSScanLocalItemsOperation.h in Headers */, @@ -26710,6 +26908,7 @@ DC7A17ED1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.h in Headers */, DC52E7E31D80BDA600B0A59C /* SecDbQuery.h in Headers */, 470D96711FCDE55B0065FE90 /* SecCDKeychain.h in Headers */, + DCC40B112383786D00402CB9 /* CKKSStates.h in Headers */, DC378B2D1DEF9DF000A3DAFA /* CKKSMirrorEntry.h in Headers */, DC94BCCA1F10448600E07CEB /* CloudKitCategories.h in Headers */, DCC67E2D20DDC07900A70A31 /* OTPrepareOperation.h in Headers */, @@ -26763,6 +26962,7 @@ DCBF2F851F913EF000ED0CA4 /* CKKSHealTLKSharesOperation.h in Headers */, DCE278E81ED7A5B40083B485 /* CKKSUpdateCurrentItemPointerOperation.h in Headers */, DCEA5D851E2F14810089CF55 /* OctagonAPSReceiver.h in Headers */, + 6C6AF182221A07230091CE0A /* SecDbKeychainSerializedMetadataKey.h in Headers */, DC1447961F5766D200236DB4 /* NSOperationCategories.h in Headers */, DC4DB1501E24692100CD6769 /* CKKSKey.h in Headers */, DCE278DD1ED789EF0083B485 /* CKKSCurrentItemPointer.h in Headers */, @@ -26868,7 +27068,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 0C78827520132074002B7475 /* SFSignInAnalytics.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -27169,6 +27368,7 @@ DCB3439C1D8A32A20054D16E /* SecImportExportOpenSSH.h in Headers */, DCB343A61D8A32A20054D16E /* SecPkcs8Templates.h in Headers */, DCB343461D8A32A20054D16E /* ExtendedAttribute.h in Headers */, + 6C2D463E24C88AA60015C3C9 /* LegacyAPICounts.h in Headers */, DCB343601D8A32A20054D16E /* Trust.h in Headers */, DCB3437B1D8A32A20054D16E /* PrimaryKey.h in Headers */, DCB343911D8A32A20054D16E /* TokenLogin.h in Headers */, @@ -27387,6 +27587,7 @@ DCD06B491D8E0D7D007602F1 /* blob.h in Headers */, DCD06B911D8E0D7D007602F1 /* unix++.h in Headers */, DCD06B9D1D8E0D7D007602F1 /* macho++.h in Headers */, + 5F4C22012489C6AC00F0C425 /* simulatecrash_assert.h in Headers */, DCD06BAA1D8E0D7D007602F1 /* cfmunge.h in Headers */, DCD06B6A1D8E0D7D007602F1 /* seccfobject.h in Headers */, DC2670F21F3E6EC500816EED /* debugging.h in Headers */, @@ -27411,6 +27612,7 @@ DCD06B841D8E0D7D007602F1 /* utility_config.h in Headers */, DCD06B8D1D8E0D7D007602F1 /* pcsc++.h in Headers */, DCD06B9B1D8E0D7D007602F1 /* cfmach++.h in Headers */, + A6BF3B3623EB95F0009AF079 /* entitlements.h in Headers */, DCD06B441D8E0D7D007602F1 /* crc.h in Headers */, DCD06B6D1D8E0D7D007602F1 /* simpleprefs.h in Headers */, DCD06B8B1D8E0D7D007602F1 /* muscle++.h in Headers */, @@ -27988,42 +28190,43 @@ productReference = 0C8BBF081FCB446400580909 /* otctl */; productType = "com.apple.product-type.tool"; }; - 0C9AEEAB20783FBB00BF6237 /* SignInAnalyticsTests_osx */ = { + 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 0C9AEEB420783FBB00BF6237 /* Build configuration list for PBXNativeTarget "SignInAnalyticsTests_osx" */; + buildConfigurationList = 0CCC227623F357EE00E1FCD0 /* Build configuration list for PBXNativeTarget "OctagonTrustTests" */; buildPhases = ( - 0C9AEEAE20783FBB00BF6237 /* Sources */, - 0C9AEEB020783FBB00BF6237 /* Frameworks */, - 0C9AEEB320783FBB00BF6237 /* Embed OCMock */, + 0CCC220B23F357EE00E1FCD0 /* Sources */, + 0CCC226123F357EE00E1FCD0 /* Frameworks */, + 0CCC227423F357EE00E1FCD0 /* Resources */, ); buildRules = ( ); dependencies = ( - 0C9AEEBA20783FE000BF6237 /* PBXTargetDependency */, + 0C7EB14F23F3D1480089097B /* PBXTargetDependency */, + 0C7EB14D23F3D13C0089097B /* PBXTargetDependency */, + 0CCC22AD23F38B0E00E1FCD0 /* PBXTargetDependency */, + 0CCC22AB23F38B0600E1FCD0 /* PBXTargetDependency */, ); - name = SignInAnalyticsTests_osx; - productName = CKKSTests; - productReference = 0C9AEEB720783FBB00BF6237 /* SignInAnalyticsTests_osx.xctest */; + name = OctagonTrustTests; + productName = TrustedPeersHelperUnitTests; + productReference = 0CCC227923F357EE00E1FCD0 /* OctagonTrustTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 0CF406042072E3E3003D6A7F /* SignInAnalyticsTests_ios */ = { + 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */ = { isa = PBXNativeTarget; - buildConfigurationList = 0CF4064D2072E3E3003D6A7F /* Build configuration list for PBXNativeTarget "SignInAnalyticsTests_ios" */; + buildConfigurationList = 0CD743AB23C3EC8000FA0EC5 /* Build configuration list for PBXNativeTarget "OctagonTrust" */; buildPhases = ( - 0CF406112072E3E3003D6A7F /* Sources */, - 0CF406342072E3E3003D6A7F /* Frameworks */, - 0CF4064A2072E3E3003D6A7F /* Embed OCMock */, + 0CD743A123C3EC8000FA0EC5 /* Headers */, + 0CD743A223C3EC8000FA0EC5 /* Sources */, + 0CD743A323C3EC8000FA0EC5 /* Frameworks */, ); buildRules = ( ); dependencies = ( - 0C5663EE20BE2E1A0035F362 /* PBXTargetDependency */, - 0C3E2EA92073F5C400F5B95B /* PBXTargetDependency */, ); - name = SignInAnalyticsTests_ios; - productName = CKKSTests; - productReference = 0CF406502072E3E3003D6A7F /* SignInAnalyticsTests_ios.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; + name = OctagonTrust; + productName = Clique; + productReference = 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */; + productType = "com.apple.product-type.framework"; }; 225394AC1E3080A600D3CD9B /* security_codesigning_ios */ = { isa = PBXNativeTarget; @@ -28102,6 +28305,22 @@ productReference = 3DD1FFD0201FDB1D0086D049 /* SecureTransport_ios_tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 3E88360824F068EF00E9F4D6 /* secseccodeapitest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E88360E24F068EF00E9F4D6 /* Build configuration list for PBXNativeTarget "secseccodeapitest" */; + buildPhases = ( + 3E88360924F068EF00E9F4D6 /* Sources */, + 3E88360B24F068EF00E9F4D6 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = secseccodeapitest; + productName = secbackupntest; + productReference = 3E88361124F068EF00E9F4D6 /* secseccodeapitest */; + productType = "com.apple.product-type.tool"; + }; 4381690B1B4EDCBD00C54D58 /* SOSCCAuthPlugin */ = { isa = PBXNativeTarget; buildConfigurationList = 438169381B4EDCBD00C54D58 /* Build configuration list for PBXNativeTarget "SOSCCAuthPlugin" */; @@ -28179,9 +28398,9 @@ productReference = 4718AEE2205B39C40068EC3F /* libsecurityd_bridge.a */; productType = "com.apple.product-type.library.static"; }; - 4727FBB61F9918580003AE36 /* secdxctests_ios */ = { + 4727FBB61F9918580003AE36 /* secdxctests */ = { isa = PBXNativeTarget; - buildConfigurationList = 4727FBC31F9918590003AE36 /* Build configuration list for PBXNativeTarget "secdxctests_ios" */; + buildConfigurationList = 4727FBC31F9918590003AE36 /* Build configuration list for PBXNativeTarget "secdxctests" */; buildPhases = ( 4727FBB31F9918580003AE36 /* Sources */, 4727FBB41F9918580003AE36 /* Frameworks */, @@ -28190,18 +28409,19 @@ buildRules = ( ); dependencies = ( + 6CE2AEAB22B2C1BE00C96AE7 /* PBXTargetDependency */, + 6CC638EB226695C300E5DB0B /* PBXTargetDependency */, + 6CC638ED226695C300E5DB0B /* PBXTargetDependency */, D4BFFD692227B30700163B4B /* PBXTargetDependency */, EB74CBD622077CC600F1BBAD /* PBXTargetDependency */, - EBD7DF8121FF475B0089F2DF /* PBXTargetDependency */, - EBD7DF8321FF475B0089F2DF /* PBXTargetDependency */, 47A6FC6A206B461700BD6C54 /* PBXTargetDependency */, 47DE88D91FA7ADBB00DD3254 /* PBXTargetDependency */, 47DE88D71FA7ADAC00DD3254 /* PBXTargetDependency */, 47DE88CE1FA7AD6200DD3254 /* PBXTargetDependency */, ); - name = secdxctests_ios; + name = secdxctests; productName = secdxctests; - productReference = 4727FBB71F9918580003AE36 /* secdxctests_ios.xctest */; + productReference = 4727FBB71F9918580003AE36 /* secdxctests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 47702B1D1E5F409700B29577 /* seckeychainnetworkextensionsystemdaemontest */ = { @@ -28255,31 +28475,6 @@ productReference = 4771D972209A755800BA9772 /* KeychainDataclassOwner.bundle */; productType = "com.apple.product-type.bundle"; }; - 478D426C1FD72A8100CAB645 /* secdxctests_mac */ = { - isa = PBXNativeTarget; - buildConfigurationList = 478D42991FD72A8100CAB645 /* Build configuration list for PBXNativeTarget "secdxctests_mac" */; - buildPhases = ( - 478D42751FD72A8100CAB645 /* Sources */, - 478D427D1FD72A8100CAB645 /* Frameworks */, - 090585D020AEF9D300BB7490 /* Install OCMock framework */, - ); - buildRules = ( - ); - dependencies = ( - DC69A5872165298500512BD6 /* PBXTargetDependency */, - 47A6FC6C206B462400BD6C54 /* PBXTargetDependency */, - DC34CD3620326C3B00302481 /* PBXTargetDependency */, - DC34CD3420326C3100302481 /* PBXTargetDependency */, - DC34CD2D20326C2C00302481 /* PBXTargetDependency */, - 478D426D1FD72A8100CAB645 /* PBXTargetDependency */, - 478D426F1FD72A8100CAB645 /* PBXTargetDependency */, - 478D42731FD72A8100CAB645 /* PBXTargetDependency */, - ); - name = secdxctests_mac; - productName = secdxctests; - productReference = 478D429C1FD72A8100CAB645 /* secdxctests_mac.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; 47C2F1822059CB680062DE30 /* KeychainResources */ = { isa = PBXNativeTarget; buildConfigurationList = 47C2F1872059CB690062DE30 /* Build configuration list for PBXNativeTarget "KeychainResources" */; @@ -28550,24 +28745,43 @@ productReference = 5EBE247A1B00CCAE0007DB0E /* secacltests */; productType = "com.apple.product-type.tool"; }; + 6C2045E92424BA7E00F9461D /* KeychainStasher */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6C2045EE2424BA7F00F9461D /* Build configuration list for PBXNativeTarget "KeychainStasher" */; + buildPhases = ( + 6C2045E62424BA7E00F9461D /* Sources */, + 6C2045E72424BA7E00F9461D /* Frameworks */, + 6C2045F32424BBB900F9461D /* Install Sandbox Profile */, + 6C2045FA2424BCC300F9461D /* Install LaunchAgent plist */, + ); + buildRules = ( + ); + dependencies = ( + 6CA9690D24ACC5C100C08B5E /* PBXTargetDependency */, + ); + name = KeychainStasher; + productName = KeychainStasher; + productReference = 6C2045EA2424BA7E00F9461D /* KeychainStasher */; + productType = "com.apple.product-type.tool"; + }; 6C39234421F13E4D00D018AD /* SecDbBackupTests */ = { isa = PBXNativeTarget; buildConfigurationList = 6C39237621F13E4D00D018AD /* Build configuration list for PBXNativeTarget "SecDbBackupTests" */; buildPhases = ( 6C39234D21F13E4D00D018AD /* Sources */, 6C39235A21F13E4D00D018AD /* Frameworks */, - 6C7E8F1F21F7BE64008A2D56 /* Copy BATS Test Discovery Plist */, - 6C7E8F2121F7BE7F008A2D56 /* Chown BATS Test Discovery Plist */, ); buildRules = ( ); dependencies = ( - 6C8FF4B6224C1A9800E5C812 /* PBXTargetDependency */, + 6CC638E7226695B900E5DB0B /* PBXTargetDependency */, + 6CC638E9226695B900E5DB0B /* PBXTargetDependency */, D4BFFD622227578900163B4B /* PBXTargetDependency */, D4BFFD602227576E00163B4B /* PBXTargetDependency */, D4BFFD5E2227575C00163B4B /* PBXTargetDependency */, D4BFFD5C2227574C00163B4B /* PBXTargetDependency */, D4BFFD592227574200163B4B /* PBXTargetDependency */, + 6CE2AEAD22B2C1C300C96AE7 /* PBXTargetDependency */, ); name = SecDbBackupTests; productName = secdxctests; @@ -28592,55 +28806,43 @@ productReference = 6C4605B81F882B9B001421B6 /* KeychainAnalyticsTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 6C98082C1E788AEB00E70590 /* CKKSCloudKitTests_mac */ = { + 6C7BE2A923C3DD64003BB2CA /* securitytool_bridge */ = { isa = PBXNativeTarget; - buildConfigurationList = 6C98085E1E788AEB00E70590 /* Build configuration list for PBXNativeTarget "CKKSCloudKitTests_mac" */; + buildConfigurationList = 6C7BE2E423C3DD64003BB2CA /* Build configuration list for PBXNativeTarget "securitytool_bridge" */; buildPhases = ( - 6C98083D1E788AEB00E70590 /* Sources */, - 6C9808481E788AEB00E70590 /* Frameworks */, - 6C98085D1E788AEB00E70590 /* Resources */, + 6C7BE2B623C3DD64003BB2CA /* Sources */, + 6C7BE2D223C3DD64003BB2CA /* Frameworks */, ); buildRules = ( ); dependencies = ( - DCD6BF5421E919610015F7A8 /* PBXTargetDependency */, - DC93C4C9214713DC008F8362 /* PBXTargetDependency */, - 6C98082F1E788AEB00E70590 /* PBXTargetDependency */, - 6C9808311E788AEB00E70590 /* PBXTargetDependency */, - 6C9808351E788AEB00E70590 /* PBXTargetDependency */, - 6C9808371E788AEB00E70590 /* PBXTargetDependency */, - 6C9808391E788AEB00E70590 /* PBXTargetDependency */, - 6C9808A01E788B9400E70590 /* PBXTargetDependency */, - ); - name = CKKSCloudKitTests_mac; - productName = CKKSTests; - productReference = 6C9808611E788AEB00E70590 /* CKKSCloudKitTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; + 6C16258423C4FFD40086A0FF /* PBXTargetDependency */, + 6C16258623C4FFD40086A0FF /* PBXTargetDependency */, + 6C16258123C4FFC40086A0FF /* PBXTargetDependency */, + 6C14CA0423C4F6830097B572 /* PBXTargetDependency */, + 6C7BE2AA23C3DD64003BB2CA /* PBXTargetDependency */, + 6C7BE2AC23C3DD64003BB2CA /* PBXTargetDependency */, + ); + name = securitytool_bridge; + productName = security; + productReference = 6C7BE2E723C3DD64003BB2CA /* securitytool_bridge */; + productType = "com.apple.product-type.tool"; }; - 6C9808681E788AFD00E70590 /* CKKSCloudKitTests_ios */ = { + 6C963280242A279B00C53CE2 /* stashtester */ = { isa = PBXNativeTarget; - buildConfigurationList = 6C98089A1E788AFD00E70590 /* Build configuration list for PBXNativeTarget "CKKSCloudKitTests_ios" */; + buildConfigurationList = 6C963288242A279B00C53CE2 /* Build configuration list for PBXNativeTarget "stashtester" */; buildPhases = ( - 6C9808791E788AFD00E70590 /* Sources */, - 6C9808841E788AFD00E70590 /* Frameworks */, - 6C9808991E788AFD00E70590 /* Resources */, + 6C96327D242A279B00C53CE2 /* Sources */, + 6C96327E242A279B00C53CE2 /* Frameworks */, ); buildRules = ( ); dependencies = ( - DCD6BF5621E9196E0015F7A8 /* PBXTargetDependency */, - DC93C4CD21471401008F8362 /* PBXTargetDependency */, - 6C9808A41E788CB100E70590 /* PBXTargetDependency */, - 6C98086B1E788AFD00E70590 /* PBXTargetDependency */, - 6C98086D1E788AFD00E70590 /* PBXTargetDependency */, - 6C9808711E788AFD00E70590 /* PBXTargetDependency */, - 6C9808731E788AFD00E70590 /* PBXTargetDependency */, - 6C9808751E788AFD00E70590 /* PBXTargetDependency */, - ); - name = CKKSCloudKitTests_ios; - productName = CKKSTests; - productReference = 6C98089D1E788AFD00E70590 /* CKKSCloudKitTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; + ); + name = stashtester; + productName = stashtester; + productReference = 6C963281242A279B00C53CE2 /* stashtester */; + productType = "com.apple.product-type.tool"; }; 6C9AA79D1F7C1D8F00D08296 /* supdctl */ = { isa = PBXNativeTarget; @@ -28667,6 +28869,7 @@ 6CAA8D1D1F842FB3007B6E03 /* Frameworks */, 6CAA8D1E1F842FB3007B6E03 /* Copy Manpage */, 6CAA8D361F84317F007B6E03 /* Install launchd plist */, + D42D044424734050004E7AA2 /* Install sandbox profile for macOS */, ); buildRules = ( ); @@ -28694,9 +28897,9 @@ productReference = 6CCDF7841E3C25FA003F2555 /* KeychainEntitledTestRunner */; productType = "com.apple.product-type.tool"; }; - 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */ = { + 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp */ = { isa = PBXNativeTarget; - buildConfigurationList = 6CF4A0CC1E45488B00ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp_mac" */; + buildConfigurationList = 6CF4A0CC1E45488B00ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp" */; buildPhases = ( 6CF4A0B01E45488B00ECD7B5 /* Sources */, 6CF4A0B11E45488B00ECD7B5 /* Frameworks */, @@ -28706,28 +28909,11 @@ ); dependencies = ( ); - name = KeychainEntitledTestApp_mac; + name = KeychainEntitledTestApp; productName = KeychainEntitledTestApp_mac; productReference = 6CF4A0B41E45488B00ECD7B5 /* KeychainEntitledTestApp.app */; productType = "com.apple.product-type.application"; }; - 6CF4A0DF1E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6CF4A0F41E4549F300ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp_ios" */; - buildPhases = ( - 6CF4A0DC1E4549F200ECD7B5 /* Sources */, - 6CF4A0DD1E4549F200ECD7B5 /* Frameworks */, - 6CF4A0DE1E4549F200ECD7B5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = KeychainEntitledTestApp_ios; - productName = KeychainEntitledTestApp_ios; - productReference = 6CF4A0E01E4549F200ECD7B5 /* KeychainEntitledTestApp.app */; - productType = "com.apple.product-type.application"; - }; 790851B50CA9859F0083CC4D /* securityd_ios */ = { isa = PBXNativeTarget; buildConfigurationList = 790851C90CA985C10083CC4D /* Build configuration list for PBXNativeTarget "securityd_ios" */; @@ -28836,6 +29022,7 @@ BEAA0029202A832500E51F45 /* Resources */, BEAA0028202A832500E51F45 /* Frameworks */, EB3FB9A3231C125400DF52EA /* Copy Logging Files */, + DC2C884D245B4B3E0040CBEB /* Copy Sandbox Profile (macOS only) */, ); buildRules = ( ); @@ -29058,6 +29245,7 @@ D4707A0221136E69005BCFDA /* Frameworks */, D4707A0321136E69005BCFDA /* Resources */, D4428B432122718400EB8448 /* Generate BATS Plist */, + D428337D24E1D0B10068B2F5 /* Remove Name Constraints Resources from watchOS */, ); buildRules = ( ); @@ -30551,6 +30739,7 @@ DCE4E8541D7A57AE00AFB96E /* Copy LaunchDaemon Files */, BEB463AD1E64F3C1008EB77E /* Copy Sandbox */, D4ADA3111E2B209C0031CEA3 /* Install man8 page */, + D459364124BFBA700066FB43 /* Install Apple Corporate Roots */, ); buildRules = ( ); @@ -31256,9 +31445,12 @@ 4C35DB69094F906D002917C4 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1000; - LastUpgradeCheck = 1120; + LastSwiftUpdateCheck = 1200; + LastUpgradeCheck = 1200; TargetAttributes = { + 0CD743A523C3EC8000FA0EC5 = { + CreatedOnToolsVersion = 12.0; + }; 4381690B1B4EDCBD00C54D58 = { CreatedOnToolsVersion = 7.0; }; @@ -31282,9 +31474,6 @@ CreatedOnToolsVersion = 10.0; ProvisioningStyle = Automatic; }; - 478D426C1FD72A8100CAB645 = { - ProvisioningStyle = Automatic; - }; 47C2F1822059CB680062DE30 = { CreatedOnToolsVersion = 10.0; ProvisioningStyle = Automatic; @@ -31298,14 +31487,14 @@ 5EBE24791B00CCAE0007DB0E = { CreatedOnToolsVersion = 7.0; }; - 6C39234421F13E4D00D018AD = { - ProvisioningStyle = Manual; + 6C2045E92424BA7E00F9461D = { + CreatedOnToolsVersion = 12.0; }; - 6C98082C1E788AEB00E70590 = { - TestTargetID = 6CF4A0B31E45488B00ECD7B5; + 6C39234421F13E4D00D018AD = { + ProvisioningStyle = Automatic; }; - 6C9808681E788AFD00E70590 = { - TestTargetID = 6CF4A0DF1E4549F200ECD7B5; + 6C963280242A279B00C53CE2 = { + CreatedOnToolsVersion = 12.0; }; 6C9AA79D1F7C1D8F00D08296 = { CreatedOnToolsVersion = 9.0; @@ -31323,10 +31512,6 @@ CreatedOnToolsVersion = 8.3; ProvisioningStyle = Automatic; }; - 6CF4A0DF1E4549F200ECD7B5 = { - CreatedOnToolsVersion = 8.3; - ProvisioningStyle = Automatic; - }; BEAA002A202A832500E51F45 = { CreatedOnToolsVersion = 9.3; LastSwiftMigration = 0930; @@ -31561,6 +31746,7 @@ }; DCF216D621ADD5B10029CCC1 = { CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1200; ProvisioningStyle = Automatic; }; DCF7889C1D88CB5200E694BB = { @@ -31644,15 +31830,14 @@ }; buildConfigurationList = 4C35DB6A094F906D002917C4 /* Build configuration list for PBXProject "Security" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, - Japanese, - French, - German, en, Base, + de, + fr, + ja, ); mainGroup = 4C35DB67094F906D002917C4; productRefGroup = 4C35DC36094F9120002917C4 /* Products */; @@ -31704,6 +31889,7 @@ DC1789031D77980500B50D50 /* Security_osx */, E7D847C41C6BE9710025BB44 /* KeychainCircle */, BEF88C271EAFFC3F00357577 /* TrustedPeers */, + 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */, DC8E04911D7F6CED006D80EB /* ======= Daemons ========= */, DCE4E8931D7F34F600AFB96E /* authd */, DCE4E7F51D7A4DA800AFB96E /* secd */, @@ -31720,6 +31906,7 @@ DC0BC5631D8B6E3D00070CB0 /* XPCTimeStampingService */, BEAA002A202A832500E51F45 /* TrustedPeersHelper */, DA41FE0D2241ADC000838FB3 /* otpaird */, + 6C2045E92424BA7E00F9461D /* KeychainStasher */, DC8E04B11D7F6EC9006D80EB /* ======= Libraries ========= */, DCDA5E4F2124B9C5009B11B2 /* aks_support */, DC36895D21235F42003A3735 /* aks_mock */, @@ -31784,6 +31971,7 @@ DC0067921D87876F005AF8DB /* securityd_server_macos */, DC0067C51D878898005AF8DB /* securityd_ucspc */, DC8E04951D7F6D80006D80EB /* ========= CLI =========== */, + 6C7BE2A923C3DD64003BB2CA /* securitytool_bridge */, 4CB740A20A47567C00D641BB /* securitytool_ios */, DC5ABDC41D832DAB00CF422C /* securitytool_macos */, DCE4E68A1D7A37FA00AFB96E /* security2tool_macos */, @@ -31809,9 +31997,8 @@ DCE4E7311D7A43B500AFB96E /* SecurityTestsOSX */, DC3502B41E0208BE00BC0587 /* CKKSTests */, 0C85DFD11FB38BB6000343A7 /* OTTests */, + 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */, DC99B85B20EACA470065B73B /* OctagonTests */, - 0CF406042072E3E3003D6A7F /* SignInAnalyticsTests_ios */, - 0C9AEEAB20783FBB00BF6237 /* SignInAnalyticsTests_osx */, DC610AAD1D7910C3002223DE /* gk_reset_check_macos */, DC610A551D78F9D2002223DE /* codesign_tests_macos */, DC610A461D78F48F002223DE /* SecTaskTest_macos */, @@ -31827,6 +32014,7 @@ EB433A201CC3243600A7EACE /* secitemstresstest */, EBA9AA7D1CE30E58004E2B68 /* secitemnotifications */, DAE40BC520CF3E46002D5674 /* secitemcanarytest */, + 3E88360824F068EF00E9F4D6 /* secseccodeapitest */, DCE4E7CB1D7A4AED00AFB96E /* sectests_macos */, 470415CE1E5E14B5001F3D95 /* seckeychainnetworkextensionstest */, 47702B1D1E5F409700B29577 /* seckeychainnetworkextensionsystemdaemontest */, @@ -31839,15 +32027,11 @@ 4CE5A54C09C796E100D27A3F /* sslViewer */, DC0BC5C51D8B72E700070CB0 /* test-checkpw */, DC0BC5D51D8B73B000070CB0 /* perf-checkpw */, - 6C98082C1E788AEB00E70590 /* CKKSCloudKitTests_mac */, - 6C9808681E788AFD00E70590 /* CKKSCloudKitTests_ios */, - 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */, - 6CF4A0DF1E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */, + 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp */, 6CCDF7831E3C25FA003F2555 /* KeychainEntitledTestRunner */, 6C46056B1F882B9B001421B6 /* KeychainAnalyticsTests */, 47C51B831EEA657D0032D9E5 /* SecurityUnitTests */, - 4727FBB61F9918580003AE36 /* secdxctests_ios */, - 478D426C1FD72A8100CAB645 /* secdxctests_mac */, + 4727FBB61F9918580003AE36 /* secdxctests */, EB49B2AD202D877F003F34A0 /* secdmockaks */, 6C39234421F13E4D00D018AD /* SecDbBackupTests */, 3DD1FEF5201C07F30086D049 /* SecureTransportTests_macos */, @@ -31859,6 +32043,7 @@ D458C4E0214E1DE00043D982 /* TrustTestsRunner_ios */, D4707A0421136E69005BCFDA /* TrustTests_ios */, D453A4A42122236D00850A26 /* TrustTests_macos */, + 6C963280242A279B00C53CE2 /* stashtester */, DC5AC1351D835D9700CF422C /* ===== Source Gen ===== */, DC008B451D90CE53004002A3 /* securityd_macos_mig */, DC6BC26C1D90CFEF00DD57B3 /* securityd_macos_startup */, @@ -31938,6 +32123,13 @@ /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ + 0CCC227423F357EE00E1FCD0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4381690A1B4EDCBD00C54D58 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -31973,6 +32165,7 @@ 4C198F220ACDB4BF00AAB142 /* Certificate.strings in Resources */, 4C198F230ACDB4BF00AAB142 /* OID.strings in Resources */, D479F6E21F980FAB00388D28 /* Trust.strings in Resources */, + 6C5D62A6221B6E3F00AF79DC /* secdxctests-entitlements.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -31982,7 +32175,6 @@ files = ( 52A23EDD161DEC3F00E271E0 /* Default-568h@2x.png in Resources */, D4D886E91CEBDD2A00DC7583 /* nist-certs in Resources */, - BE9B8B4B202BB4D10081EF87 /* si-88-sectrust-valid-data in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -32002,20 +32194,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6C98085D1E788AEB00E70590 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6C9808991E788AFD00E70590 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 6CF4A0B21E45488B00ECD7B5 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -32023,18 +32201,10 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6CF4A0DE1E4549F200ECD7B5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; BE197F2419116FD100BA91D1 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - BE197F61191173F200BA91D1 /* entitlements.plist in Resources */, BE197F2C19116FD100BA91D1 /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -32073,6 +32243,7 @@ files = ( D4B2966B22DBFDD300DCF250 /* TestCopyProperties_ios-data in Resources */, D4D92DA9227890500009A7CF /* nist-certs in Resources */, + D4231149237261F8000E470A /* SMIMEPolicyTests-data in Resources */, D4056A2022712D750026E24E /* ssl-policy-certs in Resources */, D4AC8BEF213212A7006E9871 /* si-18-certificate-parse in Resources */, D458C51A214E2CC80043D982 /* si-20-sectrust-policies-data in Resources */, @@ -32088,7 +32259,6 @@ files = ( D458C51F214E2E0C0043D982 /* Main.storyboard in Resources */, D458C51C214E2DEB0043D982 /* Assets.xcassets in Resources */, - D458C51D214E2DEB0043D982 /* Base.lproj in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -32098,6 +32268,7 @@ files = ( D4B2966A22DBFDC700DCF250 /* TestCopyProperties_ios-data in Resources */, D4D92DA8227890500009A7CF /* nist-certs in Resources */, + D4231148237261F8000E470A /* SMIMEPolicyTests-data in Resources */, D4056A1F22712D750026E24E /* ssl-policy-certs in Resources */, D4AC8BEE21321291006E9871 /* si-18-certificate-parse in Resources */, D458C517214E2C690043D982 /* si-20-sectrust-policies-data in Resources */, @@ -32143,7 +32314,6 @@ DC178A471D77A1F600B50D50 /* InfoPlist.strings in Resources */, DC178A241D77A1E700B50D50 /* cspdl_common.mdsinfo in Resources */, DC178A2B1D77A1E700B50D50 /* cl_primary.mdsinfo in Resources */, - DC178A451D77A1F600B50D50 /* framework.sb in Resources */, DC178A2D1D77A1E700B50D50 /* tp_policyOids.mdsinfo in Resources */, DC178A231D77A1E700B50D50 /* csp_primary.mdsinfo in Resources */, DC178A251D77A1E700B50D50 /* cspdl_csp_capabilities.mdsinfo in Resources */, @@ -32197,8 +32367,6 @@ DC99B88E20EACA470065B73B /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; - files = ( - ); runOnlyForDeploymentPostprocessing = 0; }; DCE4E76B1D7A43B500AFB96E /* Resources */ = { @@ -32206,7 +32374,6 @@ buildActionMask = 2147483647; files = ( DCE4E76D1D7A43B500AFB96E /* nist-certs in Resources */, - BE9B8B4D202BB4F30081EF87 /* si-88-sectrust-valid-data in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -32252,7 +32419,6 @@ files = ( 52A23EDC161DEC3800E271E0 /* Default-568h@2x.png in Resources */, D4D886EA1CEBDE0800DC7583 /* nist-certs in Resources */, - BE9B8B4C202BB4E30081EF87 /* si-88-sectrust-valid-data in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -32297,7 +32463,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 090585D020AEF9D300BB7490 /* Install OCMock framework */ = { + 090585D120AEF9FE00BB7490 /* Install OCMock framework */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; files = ( @@ -32311,21 +32477,20 @@ shellPath = /bin/sh; shellScript = "sh xcscripts/install-test-framework.sh OCMock.framework\n"; }; - 090585D120AEF9FE00BB7490 /* Install OCMock framework */ = { + 0C85DFFF1FB38BB6000343A7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; files = ( ); inputPaths = ( ); - name = "Install OCMock framework"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; - shellScript = "sh xcscripts/install-test-framework.sh OCMock.framework\n"; + shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\n#Disable until this places a plist in this directory\n#chown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n"; }; - 0C85DFFF1FB38BB6000343A7 /* ShellScript */ = { + 3DD1FF49201C07F30086D049 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; files = ( @@ -32336,9 +32501,9 @@ ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; - shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\n#Disable until this places a plist in this directory\n#chown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n"; + shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n"; }; - 3DD1FF49201C07F30086D049 /* ShellScript */ = { + 3DD1FFCC201FDB1D0086D049 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; files = ( @@ -32349,69 +32514,76 @@ ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; - shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n"; + shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist"; }; - 3DD1FFCC201FDB1D0086D049 /* ShellScript */ = { + 6CAA8D361F84317F007B6E03 /* Install launchd plist */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; files = ( ); inputPaths = ( ); + name = "Install launchd plist"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; - shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist"; + shellScript = "mkdir -p \"$LAUNCHD_PLIST_LOCATION\"\nplutil -convert binary1 -o \"$LAUNCHD_PLIST_LOCATION/com.apple.securityuploadd.plist\" \"$LAUNCHD_PLIST\"\n"; }; - 6C7E8F2121F7BE7F008A2D56 /* Chown BATS Test Discovery Plist */ = { + 8E64DB4E1C18A5B80076C9DF /* Install launchd plist */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( + "$(PROJECT_DIR)/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.ios.plist", + "$(PROJECT_DIR)/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist", ); - name = "Chown BATS Test Discovery Plist"; - outputFileListPaths = ( - ); + name = "Install launchd plist"; outputPaths = ( + "$(INSTALL_ROOT)/$(INSTALL_DAEMON_AGENT_DIR)/com.apple.security.cloudkeychainproxy3.plist", ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; - shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\n chown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n"; + shellScript = "PLIST_FILE_NAME=com.apple.security.cloudkeychainproxy3\nFILE_TO_COPY=${PROJECT_DIR}/KVSKeychainSyncingProxy/${PLIST_FILE_NAME}.ios.plist\n\nif [ ${PLATFORM_NAME} = \"macosx\" ]\nthen\nFILE_TO_COPY=${PROJECT_DIR}/KVSKeychainSyncingProxy/${PLIST_FILE_NAME}.osx.plist\nfi\n\ncp ${FILE_TO_COPY} ${INSTALL_ROOT}/${INSTALL_DAEMON_AGENT_DIR}/${PLIST_FILE_NAME}.plist\n"; }; - 6CAA8D361F84317F007B6E03 /* Install launchd plist */ = { + D428337D24E1D0B10068B2F5 /* Remove Name Constraints Resources from watchOS */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( ); - name = "Install launchd plist"; + name = "Remove Name Constraints Resources from watchOS"; + outputFileListPaths = ( + ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; - shellScript = "mkdir -p \"$LAUNCHD_PLIST_LOCATION\"\nplutil -convert binary1 -o \"$LAUNCHD_PLIST_LOCATION/com.apple.securityuploadd.plist\" \"$LAUNCHD_PLIST\"\n"; + shellScript = "# see \nif [ \"${PLATFORM_NAME}\" == \"watchos\" ]; then\n rm -rf \"$DSTROOT/AppleInternal/XCTests/com.apple.security/TrustTests.xctest/si-87-sectrust-name-constraints\"\nfi\n"; }; - 8E64DB4E1C18A5B80076C9DF /* Install launchd plist */ = { + D42D044424734050004E7AA2 /* Install sandbox profile for macOS */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( - "$(PROJECT_DIR)/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.ios.plist", - "$(PROJECT_DIR)/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist", + "$(SRCROOT)/supd/com.apple.securityuploadd.sb", + ); + name = "Install sandbox profile for macOS"; + outputFileListPaths = ( ); - name = "Install launchd plist"; outputPaths = ( - "$(INSTALL_ROOT)/$(INSTALL_DAEMON_AGENT_DIR)/com.apple.security.cloudkeychainproxy3.plist", + "$(DSTROOT)/System/Library/Sandbox/Profiles/com.apple.securityuploadd.sb", ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; - shellScript = "PLIST_FILE_NAME=com.apple.security.cloudkeychainproxy3\nFILE_TO_COPY=${PROJECT_DIR}/KVSKeychainSyncingProxy/${PLIST_FILE_NAME}.ios.plist\n\nif [ ${PLATFORM_NAME} = \"macosx\" ]\nthen\nFILE_TO_COPY=${PROJECT_DIR}/KVSKeychainSyncingProxy/${PLIST_FILE_NAME}.osx.plist\nfi\n\ncp ${FILE_TO_COPY} ${INSTALL_ROOT}/${INSTALL_DAEMON_AGENT_DIR}/${PLIST_FILE_NAME}.plist\n"; + shellScript = "if [ \"${PLATFORM_NAME}\" == \"macosx\" ]; then\n mkdir /System/Library/Sandbox/Profiles\n cp \"$SRCROOT/supd/com.apple.securityuploadd.sb\" \"$DSTROOT/System/Library/Sandbox/Profiles/com.apple.securityuploadd.sb\"\nfi\n"; }; D4428B432122718400EB8448 /* Generate BATS Plist */ = { isa = PBXShellScriptBuildPhase; @@ -32471,6 +32643,28 @@ shellPath = /bin/sh; shellScript = "ditto ${SRCROOT}/trust/trustd/iOS/AppleCorporateRootCA.cer ${DSTROOT}/AppleInternal/Library/Security/\nditto ${SRCROOT}/trust/trustd/iOS/AppleCorporateRootCA2.cer ${DSTROOT}/AppleInternal/Library/Security/\nchown -R root:wheel ${DSTROOT}/AppleInternal/Library/Security/\n"; }; + D459364124BFBA700066FB43 /* Install Apple Corporate Roots */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/trust/trustd/iOS/AppleCorporateRootCA.cer", + "$(SRCROOT)/trust/trustd/iOS/AppleCorporateRootCA2.cer", + ); + name = "Install Apple Corporate Roots"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DSTROOT)/AppleInternal/Library/Security/AppleCorporateRootCA.cer", + "$(DSTROOT)/AppleInternal/Library/Security/AppleCorporateRootCA2.cer", + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "ditto ${SRCROOT}/trust/trustd/iOS/AppleCorporateRootCA.cer ${DSTROOT}/AppleInternal/Library/Security/\nditto ${SRCROOT}/trust/trustd/iOS/AppleCorporateRootCA2.cer ${DSTROOT}/AppleInternal/Library/Security/\nchown -R root:wheel ${DSTROOT}/AppleInternal/Library/Security/\n\n"; + }; D4C263C41F8FEAA8001317EA /* Run Script Generate Error Strings */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -32598,6 +32792,25 @@ shellPath = /bin/sh; shellScript = "if [ ! -h ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/XPCServices ]; then\n ln -s Versions/Current/XPCServices ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/XPCServices\nfi\n\nexit 0\n"; }; + DC2C884D245B4B3E0040CBEB /* Copy Sandbox Profile (macOS only) */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb", + ); + name = "Copy Sandbox Profile (macOS only)"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "if [ \"$PLATFORM_FAMILY_NAME\" = \"macOS\" ]; then\n mkdir -p ${INSTALL_ROOT}/System/Library/Sandbox/Profiles/\n cp ${SRCROOT}/keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb ${INSTALL_ROOT}/System/Library/Sandbox/Profiles/\nfi\n"; + }; DC58C4381D77BE5E003C25A4 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -32988,10 +33201,10 @@ DCDB297E1FD8849D00B5D242 /* SFObjCType.m in Sources */, 5A061197229ED6EB006AF14A /* NSDate+SFAnalytics.m in Sources */, DCDB297C1FD8848A00B5D242 /* SFSQLite.m in Sources */, + A6C737BD23F37AB20009C930 /* entitlements.c in Sources */, 0CA4EBF4202B8DBE002B1D96 /* CloudKitKeychainSyncingTestsBase.m in Sources */, DCDB297D1FD8849A00B5D242 /* SFSQLiteStatement.m in Sources */, DCDB297B1FD8847100B5D242 /* SecTask.c in Sources */, - 0CE751AF20ACC497002B2832 /* SFSignInAnalytics.m in Sources */, 0C1637291FD2066A00210823 /* SecdWatchdog.m in Sources */, DCDB29791FD8844C00B5D242 /* client.c in Sources */, DCDB297A1FD8845600B5D242 /* client_endpoint.m in Sources */, @@ -33015,20 +33228,39 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 0C9AEEAE20783FBB00BF6237 /* Sources */ = { + 0CCC220B23F357EE00E1FCD0 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0C9AEEAF20783FBB00BF6237 /* SFSignInAnalyticsTests.m in Sources */, + 0CCC22A623F3868400E1FCD0 /* OTControl.m in Sources */, + 0CCC22CA23F3933000E1FCD0 /* CloudKitKeychainSyncingMockXCTest.m in Sources */, + 0CCC22C023F38DA100E1FCD0 /* SecdWatchdog.m in Sources */, + 0CCC22B723F38BF500E1FCD0 /* CloudKitMockXCTest.m in Sources */, + 0CCC22BB23F38C8800E1FCD0 /* server_entitlement_helpers.c in Sources */, + 0CCC22C123F38DC100E1FCD0 /* server_security_helpers.m in Sources */, + 0CCC22C923F3932600E1FCD0 /* CloudKitKeychainSyncingTestsBase.m in Sources */, + 0CCC22BF23F38D8E00E1FCD0 /* server_endpoint.m in Sources */, + 0CCC22B823F38C0E00E1FCD0 /* MockCloudKit.m in Sources */, + 0CCC22BE23F38D7C00E1FCD0 /* spi.c in Sources */, + 0CCC22B923F38C3000E1FCD0 /* CKKSMockSOSPresentAdapter.m in Sources */, + 0C9A54B6250C286100FF007B /* OctagonTrustTests+Errors.m in Sources */, + 0CCC22A023F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 0CF406112072E3E3003D6A7F /* Sources */ = { + 0CD743A223C3EC8000FA0EC5 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0C5663EC20BE2DF30035F362 /* SFSignInAnalytics.m in Sources */, - 0CF406522072E422003D6A7F /* SFSignInAnalyticsTests.m in Sources */, + 0C468FF623C7D4D5006F4582 /* OTICDPRecordSilentContext.m in Sources */, + 0C468FF223C7D4D5006F4582 /* OTEscrowAuthenticationInformation.m in Sources */, + 0C468FE423C7D487006F4582 /* OTEscrowRecordMetadata.m in Sources */, + 0C9F65AE23E3AD3200B1A2C5 /* OTEscrowTranslation.m in Sources */, + 0C468FE623C7D487006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */, + 0C79213D23C3F6E100193389 /* OctagonTrust.m in Sources */, + 0C468FF023C7D4D5006F4582 /* OTCDPRecoveryInformation.m in Sources */, + 0C468FE223C7D487006F4582 /* OTEscrowRecord.m in Sources */, + 0C468FF423C7D4D5006F4582 /* OTICDPRecordContext.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -33063,6 +33295,7 @@ 225394CA1E3082D500D3CD9B /* macho++.cpp in Sources */, 225394CB1E30831D00D3CD9B /* machorep.cpp in Sources */, 225394CC1E30832A00D3CD9B /* sigblob.cpp in Sources */, + A6C737B923F37A480009C930 /* entitlements.c in Sources */, 225394CD1E30833400D3CD9B /* resources.cpp in Sources */, 225394CE1E30833F00D3CD9B /* cfmunge.cpp in Sources */, 225394CF1E30835700D3CD9B /* csutilities.cpp in Sources */, @@ -33135,6 +33368,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3E88360924F068EF00E9F4D6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E88361424F0699F00E9F4D6 /* secseccodeapitest.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 438169081B4EDCBD00C54D58 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -33184,6 +33425,7 @@ 4718AE44205B39C40068EC3F /* SFKeychainControlManager.m in Sources */, DC3AF52F2229E770006577E8 /* CKKSListenerCollection.m in Sources */, 0C29BF2523232897003C807E /* OTDefines.m in Sources */, + 6C6AF17F221A07090091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */, 4718AE46205B39C40068EC3F /* CKKSIncomingQueueOperation.m in Sources */, 4718AE47205B39C40068EC3F /* CKKSOutgoingQueueOperation.m in Sources */, 4718AE48205B39C40068EC3F /* CKKSZoneStateEntry.m in Sources */, @@ -33195,6 +33437,7 @@ 4718AE4D205B39C40068EC3F /* CKKSLocalSynchronizeOperation.m in Sources */, 4718AE4E205B39C40068EC3F /* OTManager.m in Sources */, 4718AE50205B39C40068EC3F /* CKKSCurrentKeyPointer.m in Sources */, + DC880F69243D4CE50059806D /* CKKSLogging.m in Sources */, 4718AE51205B39C40068EC3F /* CKKSControlServer.m in Sources */, 4718AE52205B39C40068EC3F /* CKKSUpdateDeviceStateOperation.m in Sources */, 4718AE53205B39C40068EC3F /* SecDbKeychainSerializedMetadata.m in Sources */, @@ -33247,6 +33490,7 @@ 6C4AEF89218A09E80012C5DA /* CheckV12DevEnabled.m in Sources */, 4718AE81205B39C40068EC3F /* SecDbKeychainSerializedSecretData.m in Sources */, 4718AE82205B39C40068EC3F /* CKKSKeychainView.m in Sources */, + FC637231237B5D2200973738 /* SecItemServer+SWC.m in Sources */, 4718AE83205B39C40068EC3F /* SecuritydXPC.c in Sources */, 4718AE84205B39C40068EC3F /* SecDbKeychainSerializedItemV7.m in Sources */, 4718AE86205B39C40068EC3F /* CKKSProcessReceivedKeysOperation.m in Sources */, @@ -33266,7 +33510,6 @@ 4718AE96205B39C40068EC3F /* CKKSZoneChangeFetcher.m in Sources */, 4718AE97205B39C40068EC3F /* CKKSCondition.m in Sources */, EB0E1ACE2353A704002B6037 /* CKKSPBFileStorage.m in Sources */, - 4718AE98205B39C40068EC3F /* CKKSZone.m in Sources */, 4718AE99205B39C40068EC3F /* SFKeychainServer.m in Sources */, 4718AE9B205B39C40068EC3F /* swcagent_client.c in Sources */, DC5A01EB21BB428500D87AB9 /* CKKSTLKShare.m in Sources */, @@ -33284,12 +33527,15 @@ 477A1FED2037A0E000ACD81D /* KeychainXCTest.m in Sources */, 4727FBEB1F99227F0003AE36 /* spi.c in Sources */, 4727FBEC1F99235B0003AE36 /* SecdWatchdog.m in Sources */, + 6CD8412C23F5D871003DDF34 /* KeychainBackupTests.m in Sources */, 4764E9272059D866005497C9 /* KeychainModel.xcdatamodeld in Sources */, + 6C6B3ADF23F1B3E0002827C2 /* KeychainAppClipTests.m in Sources */, 4727FBBA1F9918590003AE36 /* KeychainCryptoTests.m in Sources */, 6C9791C921C2EAB60074C609 /* NSError+UsefulConstructors.m in Sources */, + 6C912AA1227A3E9700671FC6 /* CheckV12DevEnabled.m in Sources */, 477A1FE4203763A500ACD81D /* KeychainAPITests.m in Sources */, 4727FBED1F99249A0003AE36 /* server_endpoint.m in Sources */, - 096C647020AB1BC700D7B7D5 /* KeychainEntitlementsTest.m in Sources */, + 6C6B3AC623F1A820002827C2 /* KeychainEntitlementsTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -33318,25 +33564,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 478D42751FD72A8100CAB645 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 478D42761FD72A8100CAB645 /* server_xpc.m in Sources */, - 4764E92D2059D8BF005497C9 /* KeychainModel.xcdatamodeld in Sources */, - 478D42771FD72A8100CAB645 /* server_security_helpers.m in Sources */, - 478D42781FD72A8100CAB645 /* server_entitlement_helpers.c in Sources */, - 477A1FEE2037A0E000ACD81D /* KeychainXCTest.m in Sources */, - 09BFE35C20A32E0E008511E9 /* KeychainEntitlementsTest.m in Sources */, - 478D42791FD72A8100CAB645 /* spi.c in Sources */, - 478D427A1FD72A8100CAB645 /* SecdWatchdog.m in Sources */, - 6C9791CA21C2EAB70074C609 /* NSError+UsefulConstructors.m in Sources */, - 478D427B1FD72A8100CAB645 /* KeychainCryptoTests.m in Sources */, - 477A1FE5203763A500ACD81D /* KeychainAPITests.m in Sources */, - 478D427C1FD72A8100CAB645 /* server_endpoint.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 47C2F17F2059CB680062DE30 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -33360,10 +33587,8 @@ files = ( 6CAA8CFF1F83E800007B6E03 /* SFSQLite.m in Sources */, 6CDB5FF61FA78D1B00410924 /* SFAnalyticsMultiSampler.m in Sources */, - 0CBFEACB200FCD2D009A60E9 /* SFSignInAnalytics.m in Sources */, 5A06118E229ED5EB006AF14A /* NSDate+SFAnalytics.m in Sources */, 0C8884012154C4E80053224D /* OTJoiningConfiguration.m in Sources */, - 0CBD55B31FE883F200A8CE21 /* SFBehavior.m in Sources */, 6C814A4D2050B4B600CB391B /* LocalKeychainAnalytics.m in Sources */, 220179E91E3BF03200EFB6F3 /* dummy.cpp in Sources */, 5A442FA9233C351000918373 /* SecExperiment.m in Sources */, @@ -33458,6 +33683,7 @@ DC3AA2862097E22A007CA68A /* codesign.c in Sources */, DC8506AC2097EEBA00C712EC /* sos.m in Sources */, E78A9ADA1D34959200006B5B /* NSFileHandle+Formatting.m in Sources */, + BE57B1192509E1000045B7FD /* ca_revocation_additions.m in Sources */, DC3AA28A2097E23B007CA68A /* keychain_find.m in Sources */, DC3AA2782097DF70007CA68A /* readline.c in Sources */, DC3AA2812097E216007CA68A /* add_internet_password.c in Sources */, @@ -33539,10 +33765,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 6C2045E62424BA7E00F9461D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6C2045F12424BAC900F9461D /* main.m in Sources */, + 6C2045F22424BACE00F9461D /* KeychainStasher.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 6C39234D21F13E4D00D018AD /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6CD224E623949132001B70FD /* SecDbBackupTestsBase.m in Sources */, + 6C912AA0227A3E9600671FC6 /* CheckV12DevEnabled.m in Sources */, 6C39237B21F13EB400D018AD /* SecDbBackupManager.m in Sources */, 6C39237C21F13EB400D018AD /* SecDbBackupBag.m in Sources */, 6C39237D21F13EB400D018AD /* SecDbBackupBagIdentity.m in Sources */, @@ -33583,56 +33820,43 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6C98083D1E788AEB00E70590 /* Sources */ = { + 6C7BE2B623C3DD64003BB2CA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6CBF65431FA2257100A68667 /* SFAnalyticsActivityTracker.m in Sources */, - 6CAA8CF71F83E79E007B6E03 /* SFSQLite.m in Sources */, - 476541A41F33EDED00413F65 /* SecdWatchdog.m in Sources */, - 47B011991F17D78D0030B49F /* SFSQLiteStatement.m in Sources */, - DC2D438F1F0EEC2A0005D382 /* MockCloudKit.m in Sources */, - 6CDF8DEF1F96495600140B54 /* SFAnalyticsSampler.m in Sources */, - DCB515E21ED3D134001F1152 /* SecTask.c in Sources */, - DCB515E11ED3D11A001F1152 /* client.c in Sources */, - 6C9808A61E788CD200E70590 /* CKKSCloudKitTests.m in Sources */, - 6C98083E1E788AEB00E70590 /* spi.c in Sources */, - 5A061192229ED6E5006AF14A /* NSDate+SFAnalytics.m in Sources */, - DC2353301ECA658900D7C1BE /* server_security_helpers.m in Sources */, - 6CAA8CF01F83E65E007B6E03 /* SFObjCType.m in Sources */, - 6CAA8D131F83ECD4007B6E03 /* SFAnalytics.m in Sources */, - DC2353321ECA659000D7C1BE /* server_xpc.m in Sources */, - 6CDB5FF91FA78D2400410924 /* SFAnalyticsMultiSampler.m in Sources */, - DC5F35B11EE0F28B00900966 /* server_entitlement_helpers.c in Sources */, - DC2353291ECA658300D7C1BE /* server_endpoint.m in Sources */, - 6CAA8CF91F83E7AA007B6E03 /* SFAnalyticsSQLiteStore.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6C9808791E788AFD00E70590 /* Sources */ = { + 6C7BE2B823C3DD64003BB2CA /* SecurityTool.c in Sources */, + 6C7BE2B923C3DD64003BB2CA /* scep.c in Sources */, + 6C7BE2BA23C3DD64003BB2CA /* trust_update.m in Sources */, + 6C7BE2BB23C3DD64003BB2CA /* keychain_backup.c in Sources */, + 6C7BE2BC23C3DD64003BB2CA /* whoami.m in Sources */, + 6C7BE2BE23C3DD64003BB2CA /* KeychainCheck.m in Sources */, + 6C7BE2BF23C3DD64003BB2CA /* log_control.c in Sources */, + 6C7BE2C023C3DD64003BB2CA /* not_on_this_platorm.c in Sources */, + 6C7BE2C123C3DD64003BB2CA /* keychain_util.c in Sources */, + 6C7BE2C223C3DD64003BB2CA /* security_tool_commands.c in Sources */, + 6C7BE2C323C3DD64003BB2CA /* codesign.c in Sources */, + 6C7BE2C523C3DD64003BB2CA /* NSFileHandle+Formatting.m in Sources */, + 6C7BE2C623C3DD64003BB2CA /* keychain_find.m in Sources */, + 6C7BE2C723C3DD64003BB2CA /* readline.c in Sources */, + 6C7BE2C823C3DD64003BB2CA /* add_internet_password.c in Sources */, + 6C7BE2C923C3DD64003BB2CA /* digest_calc.c in Sources */, + 6C7BE2CA23C3DD64003BB2CA /* leaks.c in Sources */, + 6C7BE2CB23C3DD64003BB2CA /* show_certificates.c in Sources */, + 6C7BE2CC23C3DD64003BB2CA /* spc.c in Sources */, + 6C7BE2CD23C3DD64003BB2CA /* verify_cert.c in Sources */, + 6C7BE2CE23C3DD64003BB2CA /* ct_exceptions.m in Sources */, + BE57B1182509E1000045B7FD /* ca_revocation_additions.m in Sources */, + 6C7BE2CF23C3DD64003BB2CA /* keychain_add.c in Sources */, + 6C7BE2D023C3DD64003BB2CA /* pkcs12_util.c in Sources */, + 6C7BE2D123C3DD64003BB2CA /* print_cert.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6C96327D242A279B00C53CE2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6CAA8CF61F83E79D007B6E03 /* SFSQLite.m in Sources */, - 6CDB5FF81FA78D2300410924 /* SFAnalyticsMultiSampler.m in Sources */, - 5A061193229ED6E6006AF14A /* NSDate+SFAnalytics.m in Sources */, - 476541A51F33EE1E00413F65 /* SecdWatchdog.m in Sources */, - DC2D43951F0EEC300005D382 /* MockCloudKit.m in Sources */, - 6CAA8CF81F83E7A9007B6E03 /* SFAnalyticsSQLiteStore.m in Sources */, - 6C9808A51E788CD100E70590 /* CKKSCloudKitTests.m in Sources */, - 6CBF65441FA2257200A68667 /* SFAnalyticsActivityTracker.m in Sources */, - DCB515E31ED3D135001F1152 /* SecTask.c in Sources */, - 6CAA8CEF1F83E65D007B6E03 /* SFObjCType.m in Sources */, - DCB515E01ED3D111001F1152 /* client.c in Sources */, - DCB515E41ED3D15A001F1152 /* client_endpoint.m in Sources */, - 6CAA8D141F83ECD5007B6E03 /* SFAnalytics.m in Sources */, - 6C98087A1E788AFD00E70590 /* spi.c in Sources */, - 6CAA8D0D1F83EC57007B6E03 /* SFSQLiteStatement.m in Sources */, - DC5F35B21EE0F28C00900966 /* server_entitlement_helpers.c in Sources */, - DC2353311ECA658B00D7C1BE /* server_security_helpers.m in Sources */, - DC2353331ECA659000D7C1BE /* server_xpc.m in Sources */, - DC23532F1ECA658400D7C1BE /* server_endpoint.m in Sources */, - 6CDF8DF01F96495700140B54 /* SFAnalyticsSampler.m in Sources */, + 6C963284242A279B00C53CE2 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -33673,16 +33897,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6CF4A0DC1E4549F200ECD7B5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6CF4A0EA1E4549F300ECD7B5 /* ViewController.m in Sources */, - 6CF4A0E71E4549F300ECD7B5 /* AppDelegate.m in Sources */, - 6CF4A0E41E4549F200ECD7B5 /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 790851B30CA9859F0083CC4D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -33741,6 +33955,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0C468FF823C7D4E3006F4582 /* OTEscrowRecordMetadata.m in Sources */, 0CE15E2F222DF63600B7EAA5 /* SetValueTransformer.swift in Sources */, 0CE15E2C222DF63600B7EAA4 /* RecoveryKey.swift in Sources */, 0CE15E43222DF6A800B7EAA4 /* Recovery.m in Sources */, @@ -33749,6 +33964,7 @@ DC391F8D21BF244000772585 /* CKKSSIV.m in Sources */, 0CE15E30222DF63600B7EAA4 /* RecoverKeySet.swift in Sources */, 0C3BB3582188E18C0018FC14 /* OTPrivateKey+SF.m in Sources */, + 0C468FF723C7D4E3006F4582 /* OTEscrowRecord.m in Sources */, BECFA43D20F9493000B11002 /* Policy.swift in Sources */, 0CB582D1218920090040C5F2 /* OTAuthenticatedCiphertext.m in Sources */, 0CF70BD9218BED1000EC3515 /* CuttlefishExtensionWorkaround.swift in Sources */, @@ -33760,6 +33976,7 @@ DCAA209C23AAF93700DCB594 /* Container_RecoveryKey.swift in Sources */, BE9F8D19206C4AD300B53D16 /* ContainerMap.swift in Sources */, BE9F4F8C2072D881004A52C2 /* Cuttlefish.pb.swift in Sources */, + DC9978B82404AA3200A5EE2F /* Container_UserSync.swift in Sources */, DC391F9D21BF2F8100772585 /* CKKSConstants.m in Sources */, BE9F8D10206C099800B53D16 /* Container.swift in Sources */, 0CB582D3218920090040C5F2 /* OTPrivateKey.m in Sources */, @@ -33769,13 +33986,17 @@ DCAD8F8622C43EC1007C3872 /* Container_MachineIDs.swift in Sources */, DCB0C295222F5EF60083AECB /* CuttlefishErrors.swift in Sources */, 0CB582D021891FF40040C5F2 /* OTBottle.m in Sources */, + DC880F6B243D4D730059806D /* CKKSLogging.m in Sources */, 0C0C4F86216FB73C00C14C61 /* EscrowKeys.swift in Sources */, DCB9475621274A1900ED9272 /* TPHObjcTranslation.m in Sources */, 0C3BB35A2188E18C0018FC14 /* OTAuthenticatedCiphertext+SF.m in Sources */, + 0C468FF923C7D4E3006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */, + 0C0CB73923AD714D0020C6BF /* Container_EscrowRecords.swift in Sources */, 0CE15E3E222DF6A800B7EAA4 /* OTRecovery.m in Sources */, DC391F8E21BF274600772585 /* CKKSPeer.m in Sources */, DC391F8A21BF222500772585 /* CKKSKeychainBackedKey.m in Sources */, 0C0C4F87216FB73F00C14C61 /* BottledPeer.swift in Sources */, + 0C3DF8C824789C3C009CF03A /* Container_Peers.swift in Sources */, 0CB582D2218920090040C5F2 /* OTBottleContents.m in Sources */, DC391F8F21BF284D00772585 /* CKKSSerializedKey.m in Sources */, BEC0A96420B362EC00DBD772 /* Utils.swift in Sources */, @@ -33813,18 +34034,22 @@ 0CA4B4722171410200B17169 /* EscrowKeys.swift in Sources */, BE536030209BC1FD0027E25A /* spi.c in Sources */, BEA8558120B5DC7D00D5AD11 /* FakeCuttlefish.swift in Sources */, + DC9978BB2404B26900A5EE2F /* Container_UserSync.swift in Sources */, 0CB5C678218B803C0044F730 /* OTPrivateKey+SF.m in Sources */, DC05035E214083B200A8EDB7 /* TPHObjcTranslation.m in Sources */, 0CE15E41222DF6A800B7EAA4 /* OTRecovery.m in Sources */, BE536031209BC2F90027E25A /* SecdWatchdog.m in Sources */, 0CB582C82189157F0040C5F2 /* OTAuthenticatedCiphertext.m in Sources */, + 0C468FFC23C7D4EF006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */, BED987E320991C4D00607A5F /* MockCuttlefish.swift in Sources */, BEC373D020D87B4D00DBDF5B /* SecFramework.c in Sources */, 0CB582CA2189157F0040C5F2 /* OTBottleContents.m in Sources */, + 0C3DF8C924789D06009CF03A /* Container_Peers.swift in Sources */, BE536032209BC3250027E25A /* server_endpoint.m in Sources */, BE536034209BC3C40027E25A /* server_security_helpers.m in Sources */, BECFA43E20F9493000B11002 /* Policy.swift in Sources */, 0CA2282F2187A5CA00A1C56C /* BottledPeer.swift in Sources */, + DC880F6A243D4D640059806D /* CKKSLogging.m in Sources */, DC747993222720C8001E0E8C /* MockCloudKit.m in Sources */, 0CB5C677218B803C0044F730 /* OTAuthenticatedCiphertext+SF.m in Sources */, BE727824209CBCA800F0DA77 /* Cuttlefish.pb.swift in Sources */, @@ -33833,12 +34058,15 @@ BE536033209BC3B30027E25A /* server_entitlement_helpers.c in Sources */, DCAA209B23AAF8FD00DCB594 /* Container_RecoveryKey.swift in Sources */, BED987E020991B1100607A5F /* TrustedPeersHelper.xcdatamodeld in Sources */, + 0C468FFA23C7D4EF006F4582 /* OTEscrowRecord.m in Sources */, BED987D62099145300607A5F /* TrustedPeersHelperUnitTests.swift in Sources */, BE4C6AB820CAF4F700EAD6BE /* ContainerSync.swift in Sources */, 0CE15E46222DF6A800B7EAA4 /* Recovery.m in Sources */, 0CE15E33222DF63600B7EAA4 /* RecoverKeySet.swift in Sources */, 0CE15E2F222DF63600B7EAA4 /* RecoveryKey.swift in Sources */, + 0C468FFB23C7D4EF006F4582 /* OTEscrowRecordMetadata.m in Sources */, DCF6320721C075210030CCC0 /* CuttlefishAPIHelpers.swift in Sources */, + 0C0CB73B23AD71650020C6BF /* Container_EscrowRecords.swift in Sources */, BED987DE2099156B00607A5F /* Container.swift in Sources */, DCB0C292222F5E1D0083AECB /* CuttlefishErrors.swift in Sources */, BECFA44320FD0A4B00B11002 /* LocalKeychainAnalytics.m in Sources */, @@ -33887,6 +34115,7 @@ DCE0776A21ADD71C002662FD /* TPPBPeerDynamicInfo.m in Sources */, DCE0776C21ADD71C002662FD /* TPPBPolicySecret.m in Sources */, DCE0776E21ADD71C002662FD /* TPPBPeerStableInfo.m in Sources */, + DCC03FA523FF521100A4DA3F /* TPSyncingPolicy.m in Sources */, DCE0777021ADD71C002662FD /* TPPBVoucher.m in Sources */, DCE0777221ADD71C002662FD /* TPPBPolicyDocument.m in Sources */, DCE0777421ADD71C002662FD /* TPPBPolicyCategoriesByView.m in Sources */, @@ -34007,20 +34236,23 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D49A370723873BD30065719F /* TrustDaemonTestCase.m in Sources */, - D49A370423873A580065719F /* RevocationTests.m in Sources */, + D477CB83237F692400C02355 /* RevocationTests.m in Sources */, D40881F5217573C900180E81 /* SecTrustStatusCodes.c in Sources */, D4FD421D217D789C002B7EE2 /* NameConstraintsTests.m in Sources */, D4FD4221217D7B2E002B7EE2 /* PathScoringTests.m in Sources */, + D477CB88237F8B2F00C02355 /* CAIssuerTests.m in Sources */, D40881F42175738C00180E81 /* SecPolicyLeafCallbacks.c in Sources */, D40881F32175733F00180E81 /* SecPolicy.c in Sources */, D477CB7C237E4BD700C02355 /* ExceptionTests.m in Sources */, D40881F22175733500180E81 /* SecSignatureVerificationSupport.c in Sources */, D40881F12175732E00180E81 /* SecCertificate.c in Sources */, D40881F02175732600180E81 /* SecTrustStore.c in Sources */, + D477CB90237F975500C02355 /* ValidTests.m in Sources */, D40881EF2175731E00180E81 /* SecTrust.c in Sources */, D458C523214E33380043D982 /* KeySizeTests.m in Sources */, + D477CB8C237F8DBC00C02355 /* AllowlistBlocklistTests.m in Sources */, D458C4BD214E19AF0043D982 /* SignatureAlgorithmTests.m in Sources */, + D477CB6B237CBA2C00C02355 /* TrustDaemonTestCase.m in Sources */, D458C4B1214E198F0043D982 /* CTTests.m in Sources */, D458C4B9214E19AF0043D982 /* PathParseTests.m in Sources */, D458C516214E286D0043D982 /* PolicyTests.m in Sources */, @@ -34035,10 +34267,13 @@ D453A4AD2122236D00850A26 /* TrustFrameworkTestCase.m in Sources */, D49A370D23877ECC0065719F /* OCSPCacheTests.m in Sources */, D4EA5CF922B225D100883439 /* LoggingServerTests.m in Sources */, + D458DAC42375FEA300E5890E /* TrustSettingsTests.m in Sources */, D4056A1B22712A650026E24E /* SSLPolicyTests.m in Sources */, D458C4C4214E19FC0043D982 /* TrustInterfaceTests.m in Sources */, D453A4AF2122236D00850A26 /* CertificateInterfaceTests.m in Sources */, D458C4C2214E19FC0043D982 /* TrustSettingsInterfaceTests.m in Sources */, + D423114423725F9F000E470A /* SMIMEPolicyTests.m in Sources */, + D477CB5D237B6E0E00C02355 /* PersonalizationTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -34064,8 +34299,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D477CB6A237CBA2C00C02355 /* TrustDaemonTestCase.m in Sources */, D49A370C23877ECC0065719F /* OCSPCacheTests.m in Sources */, D40881FA217573F800180E81 /* SecPolicy.c in Sources */, + D477CB8B237F8DBC00C02355 /* AllowlistBlocklistTests.m in Sources */, D40881FB217573F800180E81 /* SecPolicyLeafCallbacks.c in Sources */, D40881F9217573EF00180E81 /* SecSignatureVerificationSupport.c in Sources */, D40881F8217573E700180E81 /* SecCertificate.c in Sources */, @@ -34079,19 +34316,23 @@ D4FD4220217D7B2E002B7EE2 /* PathScoringTests.m in Sources */, D458C4BC214E19AF0043D982 /* SignatureAlgorithmTests.m in Sources */, D4FD421C217D789C002B7EE2 /* NameConstraintsTests.m in Sources */, + D477CB5C237B6E0E00C02355 /* PersonalizationTests.m in Sources */, D4A0F8CC211E6A8300443CA1 /* TrustEvaluationTestCase.m in Sources */, + D477CB87237F8B2F00C02355 /* CAIssuerTests.m in Sources */, D4A0F8C7211E6A5800443CA1 /* TrustFrameworkTestCase.m in Sources */, D458C4C3214E19FC0043D982 /* TrustInterfaceTests.m in Sources */, D4AC8BE821320AD0006E9871 /* CertificateParseTests.m in Sources */, D4A0F8C8211E6A5800443CA1 /* CertificateInterfaceTests.m in Sources */, + D423114323725F9F000E470A /* SMIMEPolicyTests.m in Sources */, D458C4B0214E198F0043D982 /* CTTests.m in Sources */, + D477CB8F237F975500C02355 /* ValidTests.m in Sources */, D458C4B2214E198F0043D982 /* EvaluationBasicTests.m in Sources */, - D49A370323873A580065719F /* RevocationTests.m in Sources */, + D477CB82237F692400C02355 /* RevocationTests.m in Sources */, D458C4BA214E19AF0043D982 /* iAPTests.m in Sources */, D458C4B8214E19AF0043D982 /* PathParseTests.m in Sources */, D458C525214E33440043D982 /* VerifyDateTests.m in Sources */, - D49A370623873BD30065719F /* TrustDaemonTestCase.m in Sources */, D458C515214E286C0043D982 /* PolicyTests.m in Sources */, + D458DAC32375FEA300E5890E /* TrustSettingsTests.m in Sources */, D477CB7B237E4BD700C02355 /* ExceptionTests.m in Sources */, D4EF32182156DDEB000A31A5 /* TrustSettingsInterfaceTests.m in Sources */, D44282FF22D68564001746B3 /* TrustEvaluationTestHelpers.m in Sources */, @@ -34296,6 +34537,7 @@ DC0BC7A21D8B773000070CB0 /* cssmcontext.cpp in Sources */, DC0BC7B21D8B773000070CB0 /* oidsalg.c in Sources */, DC0BC7AA1D8B773000070CB0 /* modload_plugin.cpp in Sources */, + 6C97434A24D1C8DE00A2025C /* LegacyAPICounts.m in Sources */, DC0BC7B41D8B773000070CB0 /* oidscrl.cpp in Sources */, DC0BC79B1D8B773000070CB0 /* attachfactory.cpp in Sources */, DC0BC7A51D8B773000070CB0 /* cssmmds.cpp in Sources */, @@ -34523,7 +34765,6 @@ DC0BCD961D8C6A1E00070CB0 /* der_dictionary.c in Sources */, DC0BCD751D8C6A1E00070CB0 /* iCloudKeychainTrace.c in Sources */, DC0BCD821D8C6A1E00070CB0 /* SecCFWrappers.c in Sources */, - EB4B6E201DC0682A00AFC494 /* SecADWrapper.c in Sources */, DC0BCD941D8C6A1E00070CB0 /* der_date.c in Sources */, DC0BCD9F1D8C6A1F00070CB0 /* fileIo.c in Sources */, DC0BCDA81D8C6A1F00070CB0 /* SecFileLocations.c in Sources */, @@ -34592,6 +34833,7 @@ DC74799A222722BC001E0E8C /* CKKSKeychainBackedKey.m in Sources */, DC747999222722B2001E0E8C /* CKKSConstants.m in Sources */, DC7479982227229D001E0E8C /* CKKSTLKShare.m in Sources */, + DC880F6C243D4DC00059806D /* CKKSLogging.m in Sources */, DC0EF8F2208697C600AB9E95 /* main.swift in Sources */, EB7ECF9623467FB400CE2D3C /* Cuttlefish.pb.swift in Sources */, DCD48BFE20BF3D83009A3224 /* tpctl-objc.m in Sources */, @@ -34604,6 +34846,7 @@ buildActionMask = 2147483647; files = ( DC2B757621F2A270003C9356 /* SecEscrowRequest.m in Sources */, + BE7B8E142415579900E1CF4F /* SecSharedCredential.m in Sources */, 0C84D8381FCF43BF00B822E3 /* OTControlProtocol.m in Sources */, DCC585FF20BF8A7E005C7269 /* SecFramework.c in Sources */, DCA85B991E8D980B00BA7241 /* client_endpoint.m in Sources */, @@ -34613,7 +34856,6 @@ 6CDB5FF51FA78D1A00410924 /* SFAnalyticsMultiSampler.m in Sources */, DCA85B941E8D97E400BA7241 /* client.c in Sources */, DCDF0A4F1D81D76F007AF174 /* Security.exp-in in Sources */, - 0CBFEACA200FCD2D009A60E9 /* SFSignInAnalytics.m in Sources */, DC1789A51D779E3B00B50D50 /* dummy.cpp in Sources */, 5A061191229ED6DB006AF14A /* NSDate+SFAnalytics.m in Sources */, EB9B285821C77C8D00173DC2 /* OTDefines.m in Sources */, @@ -34625,6 +34867,7 @@ 6CAA8CFE1F83E800007B6E03 /* SFSQLite.m in Sources */, DC9C95C01F79DC89000D19E5 /* CKKSControl.m in Sources */, 5AF594001FA0EE5300A5C1EC /* SecProtocol.c in Sources */, + BE7B8E152415580D00E1CF4F /* SecSharedCredential.c in Sources */, 5A442FAA233C351100918373 /* SecExperiment.m in Sources */, 0C8884042154C4EA0053224D /* OTJoiningConfiguration.m in Sources */, 0C0E60E020D033E400E654F2 /* OTControl.m in Sources */, @@ -34635,9 +34878,7 @@ 6CE3654D1FA100E50012F6AB /* SFAnalytics.m in Sources */, 5A7E037A22272E0E003DB3A0 /* SecProtocolHelper.m in Sources */, 6CAA8CFD1F83E7EB007B6E03 /* SFObjCType.m in Sources */, - DC1789A21D779DF400B50D50 /* SecBreadcrumb.c in Sources */, 78ADC62C1FA0FACE001EB8B6 /* SecProtocolTypes.m in Sources */, - 0CE079F41FEA15B20040A3F1 /* SFBehavior.m in Sources */, 6CBF65411FA1481100A68667 /* SFAnalyticsActivityTracker.m in Sources */, 0CD9E34623592EA7002995DE /* OctagonSignPosts.m in Sources */, ); @@ -34686,6 +34927,7 @@ DC9C98C722E264F30021E29F /* CKKSFetchTests.m in Sources */, EB0E1ADA2357627F002B6037 /* CKKSPBFileStorageTests.m in Sources */, DC9C75161E4BCE1800F1CA0D /* CKKSOperationTests.m in Sources */, + DC86122C2408AC190092E93B /* CKKSTests+ItemSyncChoice.m in Sources */, DC8D238D2064649400E163C8 /* CKKSAPSHandlingTests.m in Sources */, EBC1024422EBF93E0083D356 /* CKKSTests+LockStateTracker.m in Sources */, DCB221561E8B08BF001598BC /* server_xpc.m in Sources */, @@ -34694,12 +34936,14 @@ DC4268FE1E820371002B7110 /* server_endpoint.m in Sources */, DC752F1921C1B69C00216089 /* SFSQLite.m in Sources */, DCFE1C3D1F17EFB5007640C8 /* CKKSConditionTests.m in Sources */, + DCBA6F2924105399009A5187 /* CKKSTests+ForwardCompatibility.m in Sources */, DCCD33C91E3FE95900AA4AD1 /* spi.c in Sources */, DC5B391720C08B38005B09F6 /* SecFramework.c in Sources */, DC9C95971F748D0B000D19E5 /* CKKSServerValidationRecoveryTests.m in Sources */, DC7341FE1F84642C00AB9BDF /* CKKSTLKSharingEncryptionTests.m in Sources */, DC5F35AC1EE0F27900900966 /* server_entitlement_helpers.c in Sources */, DAEE055C1FAD3FC700DF27F3 /* AutoreleaseTest.c in Sources */, + A6C737BB23F37AB00009C930 /* entitlements.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -34727,6 +34971,7 @@ buildActionMask = 2147483647; files = ( 1BB1CAB7232C05BD001D0C71 /* CuttlefishXPCWrapper.m in Sources */, + DC6E02162405DE3900C61335 /* OTModifyUserControllableViewStatusOperation.m in Sources */, 1BB1CAB8232C05BD001D0C71 /* CuttlefishXPCWrapper.h in Sources */, DCE0778021ADEC4B002662FD /* CKKSSerializedKey.m in Sources */, DCE0777F21ADEC07002662FD /* OTAccountMetadataClassC.m in Sources */, @@ -34735,6 +34980,7 @@ 0C00FC86217A980100C8BF00 /* OTLocalCuttlefishReset.m in Sources */, DCAE1DDD2073FDCC00B4F687 /* NSError+UsefulConstructors.m in Sources */, 6C4AEF88218A09E70012C5DA /* CheckV12DevEnabled.m in Sources */, + DCC40B122383786D00402CB9 /* CKKSStates.m in Sources */, DC797E1A1DD3F9A400CC9E42 /* CKKSSQLDatabaseObject.m in Sources */, 6CC1859F1E24E8EB009657D8 /* CKKSRateLimiter.m in Sources */, DCD33D7C220B99CC000A390B /* EscrowRequestController.m in Sources */, @@ -34751,6 +34997,7 @@ DC54DD0F1EA7D9E700108E92 /* CKKSManifestLeafRecord.m in Sources */, DCDCCB901DF7B8D4006E840E /* CKKSItem.m in Sources */, DC1ED8C11DD5197E002BDCFA /* CKKSItemEncrypter.m in Sources */, + DCB55176247F48290009A859 /* CKKSDeleteCKZoneOperation.m in Sources */, 0CDD6F79226E83F6009094C2 /* OTTriggerEscrowUpdateOperation.m in Sources */, DC0D16072363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.m in Sources */, DC6D2C921DD2835A00BE372D /* CKKSOutgoingQueueEntry.m in Sources */, @@ -34770,10 +35017,12 @@ 6C880FC821C3351400D38D66 /* SecDbBackupBag.m in Sources */, 0C87D3D9229326AA007853B5 /* OTEnsureOctagonKeyConsistency.m in Sources */, 6C588D801EAA20AB00D7E322 /* RateLimiter.m in Sources */, + DCB55177247F483D0009A859 /* CKKSCreateCKZoneOperation.m in Sources */, DC8DF6DC212F8A7C007B3FE8 /* OTSOSAdapter.m in Sources */, 0C66046A2134983900BFBBB8 /* OTEstablishOperation.m in Sources */, DC15F7681E67A6F6003B9A40 /* CKKSHealKeyHierarchyOperation.m in Sources */, DCE278DF1ED789EF0083B485 /* CKKSCurrentItemPointer.m in Sources */, + DC061A722462136F0026ADB3 /* CKKSOperationDependencies.m in Sources */, DC3D748E1FD2217900AC57DA /* CKKSLocalSynchronizeOperation.m in Sources */, DCC67E2F20DDC07900A70A31 /* OTPrepareOperation.m in Sources */, DCB41DFC216D5E5B00F219E0 /* OTAccountMetadataClassC+KeychainSupport.m in Sources */, @@ -34799,14 +35048,17 @@ DC762AA01E57A86A00B03A2C /* CKKSRecordHolder.m in Sources */, DC52E7DF1D80BD8700B0A59C /* SOSChangeTracker.c in Sources */, DCD33D94220CFF8A000A390B /* EscrowRequestPerformEscrowEnrollOperation.m in Sources */, + DC947E8524638320005B8669 /* CKKSCheckKeyHierarchyOperation.m in Sources */, DC1DA6681E4555D80094CE7F /* CKKSScanLocalItemsOperation.m in Sources */, 0CC8A9032123AF06005D7F6A /* OTJoinWithVoucherOperation.m in Sources */, + DC061A71246213660026ADB3 /* CKKSLocalResetOperation.m in Sources */, DC18F7711E43E116006B8B43 /* CKKSFetchAllRecordZoneChangesOperation.m in Sources */, DC45D43E22EB619D00CEB6B7 /* OctagonStateMachineObservers.m in Sources */, DC2C5F601F0EB97E00FEBDA7 /* CKKSNotifier.m in Sources */, DC7250382296056000493D88 /* OTResetCKKSZonesLackingTLKsOperation.m in Sources */, DC221BAC2267E2A70068DBCF /* OTUpdateTPHOperation.m in Sources */, DC93F02A22387A010072720A /* OTSOSUpdatePreapprovalsOperation.m in Sources */, + DC880F68243D4CC00059806D /* CKKSLogging.m in Sources */, 6C4AEF90218A0C170012C5DA /* SecDbBackupManager.m in Sources */, DC5060ED20E2D88300925005 /* OTCuttlefishContext.m in Sources */, DC0FA6B12291F63F00FE01C4 /* OctagonPendingFlag.m in Sources */, @@ -34831,6 +35083,7 @@ DC52E7CB1D80BCD800B0A59C /* SecItemBackupServer.c in Sources */, 0C2F337220DD64930031A92D /* OTRamping.m in Sources */, DCF12674218A757A000124C6 /* OTLeaveCliqueOperation.m in Sources */, + FC63722F237B5D1C00973738 /* SecItemServer+SWC.m in Sources */, DC52E7CD1D80BCE700B0A59C /* SecItemDataSource.c in Sources */, 0C8FD52521483EF20098E3FB /* OT.m in Sources */, DC9C066B2149DFE400C6F7B8 /* OTAuthKitAdapter.m in Sources */, @@ -34866,6 +35119,7 @@ DCB837321ED5045000015C07 /* CKKSLockStateTracker.m in Sources */, EB80DE162195EDA4005B10FA /* SecC2DeviceInfo.m in Sources */, 47922D4C1FAA7C4A0008F7E0 /* SecDbKeychainSerializedSecretData.m in Sources */, + 6C6AF180221A070A0091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */, DCBDB3B71E57C82300B61300 /* CKKSKeychainView.m in Sources */, DC52E7D61D80BD2800B0A59C /* SecuritydXPC.c in Sources */, 0C4F4DE221153E9E007F7E20 /* OTEpochOperation.m in Sources */, @@ -34893,7 +35147,7 @@ 6C4AEF96218A127F0012C5DA /* SecDbKeychainMetadataKeyStore.m in Sources */, DCFE1C361F17ECE5007640C8 /* CKKSCondition.m in Sources */, EB7E91172194847A00B1FA21 /* SecEventMetric.m in Sources */, - DCEA5D971E3015830089CF55 /* CKKSZone.m in Sources */, + 0C64C0802485B2EF00D84A5D /* OTPreloadOctagonKeysOperation.m in Sources */, DCAB17D22200D26900E1DFCF /* SecEscrowPendingRecord.m in Sources */, DC047082218BB21E0078BDAA /* OTCuttlefishAccountStateHolder.m in Sources */, DC047088218BCEF20078BDAA /* OTOperationDependencies.m in Sources */, @@ -35111,7 +35365,6 @@ DC52EDBC1D80D5C500B0A59C /* secd-02-upgrade-while-locked.m in Sources */, DC52EDBD1D80D5C500B0A59C /* secd-20-keychain_upgrade.m in Sources */, DC52EDBE1D80D5C500B0A59C /* secd-21-transmogrify.m in Sources */, - DCFAEDD21D99991F005187E4 /* secd-668-ghosts.m in Sources */, DC52EDBF1D80D5C500B0A59C /* secd-30-keychain-upgrade.m in Sources */, DC52EDC11D80D5C500B0A59C /* secd-31-keychain-unreadable.m in Sources */, 0CCDE7171EEB08220021A946 /* secd-156-timers.m in Sources */, @@ -35139,7 +35392,6 @@ DC52EDD41D80D5C500B0A59C /* secd-60-account-cloud-identity.m in Sources */, DC52EDD51D80D5C500B0A59C /* secd60-account-cloud-exposure.m in Sources */, DC52EDD61D80D5C500B0A59C /* secd-61-account-leave-not-in-kansas-anymore.m in Sources */, - 0C78826F20132069002B7475 /* SFSignInAnalytics.m in Sources */, DC52EDD71D80D5C500B0A59C /* secd-62-account-backup.m in Sources */, DC52EDD91D80D5C500B0A59C /* secd-63-account-resurrection.m in Sources */, DC52EDDA1D80D5C500B0A59C /* secd-65-account-retirement-reset.m in Sources */, @@ -35155,6 +35407,7 @@ DC52EDDF1D80D5C500B0A59C /* secd-70-otr-remote.m in Sources */, DC52EDE21D80D5C500B0A59C /* secd-74-engine-beer-servers.m in Sources */, 7281E0901DFD0E0A0021E1B7 /* CKDKVSProxy.m in Sources */, + 487A65F4245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m in Sources */, DC52EDE31D80D5C500B0A59C /* secd-75-engine-views.m in Sources */, DC52EDE61D80D5C500B0A59C /* secd-80-views-basic.m in Sources */, DC52EDE81D80D5C500B0A59C /* secd-81-item-acl-stress.m in Sources */, @@ -35174,7 +35427,6 @@ buildActionMask = 2147483647; files = ( DC52EE611D80D79E00B0A59C /* si-71-mobile-store-policy.c in Sources */, - DC52EE601D80D79900B0A59C /* si-74-OTAPKISigner.c in Sources */, D4AD87701E452CE000CA1B7F /* si-68-secmatchissuer.c in Sources */, EB6928CA1D9C9E1800062A18 /* rk_01_recoverykey.m in Sources */, D42CDC351DC12FE90090E2C9 /* si-66-smime.c in Sources */, @@ -35182,13 +35434,11 @@ DC0B62291D90974600D43BCB /* si-25-cms-skid.m in Sources */, 09CB49701F2F64E300C8E4DE /* si-44-seckey-fv.m in Sources */, D48BD18D206C45F00075DDC9 /* si-89-cms-hash-agility.m in Sources */, - BE6215BE1DB6E69100961E15 /* si-84-sectrust-allowlist.m in Sources */, D4B6D57C2069D8450099FBEF /* si-34-cms-timestamp.m in Sources */, D4096E031ED5F21C000AC459 /* si-65-cms-cert-policy.c in Sources */, DC52EE441D80D71900B0A59C /* si-21-sectrust-asr.c in Sources */, D4AA0D9A22FB959600D77FA4 /* si-29-cms-chain-mode.m in Sources */, DC52EE451D80D71900B0A59C /* si-22-sectrust-iap.c in Sources */, - DC52EE471D80D71900B0A59C /* si-23-sectrust-ocsp.c in Sources */, D48E4E241E42F0620011B4BA /* si-62-csr.m in Sources */, DC52EE481D80D71900B0A59C /* si-24-sectrust-digicert-malaysia.c in Sources */, DC52EE491D80D71900B0A59C /* si-24-sectrust-diginotar.c in Sources */, @@ -35197,16 +35447,13 @@ DC52EE4C1D80D71900B0A59C /* si-24-sectrust-passbook.c in Sources */, DC52EE4D1D80D71900B0A59C /* si-26-sectrust-copyproperties.c in Sources */, 5E7793751E5F025A0074A2D1 /* si-44-seckey-aks.m in Sources */, - DC52EE4F1D80D71900B0A59C /* si-28-sectrustsettings.m in Sources */, DC52EE531D80D73800B0A59C /* si-44-seckey-gen.m in Sources */, DC52EE541D80D73800B0A59C /* si-44-seckey-rsa.m in Sources */, DC52EE551D80D73800B0A59C /* si-44-seckey-ec.m in Sources */, D4096E011ED5F0B5000AC459 /* si-60-cms.c in Sources */, D4CFAA7E1E660BB3004746AA /* si-32-sectrust-pinning-required.m in Sources */, - BE9B8B4A202BB4A20081EF87 /* si-88-sectrust-valid.m in Sources */, D48BD194206C47530075DDC9 /* si-35-cms-expiration-time.m in Sources */, DC52EE561D80D73800B0A59C /* si-44-seckey-ies.m in Sources */, - DC52EE571D80D73800B0A59C /* si-67-sectrust-blocklist.c in Sources */, D4096E021ED5F207000AC459 /* si-64-ossl-cms.c in Sources */, 478014541FBF577000C4043D /* si-44-seckey-proxy.m in Sources */, DCD45357209A5BA10086CBFC /* si-cms-signing-identity-p12.c in Sources */, @@ -35238,6 +35485,7 @@ DC52EE721D80D86400B0A59C /* SecuritydXPC.c in Sources */, DC52EE711D80D85F00B0A59C /* SecECKey.m in Sources */, DC52EE701D80D84700B0A59C /* SecItemConstants.c in Sources */, + 6C22008A244F0760000A4557 /* SecItemRateLimit.m in Sources */, DC52EE6F1D80D83F00B0A59C /* SecPasswordGenerate.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -35301,6 +35549,7 @@ DC5AC1031D83552000CF422C /* selfServer.cpp in Sources */, DC5AC1041D83552000CF422C /* selfUser.cpp in Sources */, DC5AC0D81D8354CA00CF422C /* main.cpp in Sources */, + 6C75560624212B4400025D78 /* keychainstasherinterface.m in Sources */, DC5AC0D91D8354CA00CF422C /* connection.cpp in Sources */, DC5AC0DA1D8354CA00CF422C /* database.cpp in Sources */, DC5AC0DB1D8354CA00CF422C /* key.cpp in Sources */, @@ -35318,7 +35567,6 @@ DC5AC0E61D8354CA00CF422C /* tokendatabase.cpp in Sources */, DC5AC0E71D8354CA00CF422C /* tokenkey.cpp in Sources */, DC5AC0E81D8354CA00CF422C /* tokenaccess.cpp in Sources */, - DC5AC0E91D8354CA00CF422C /* pcscmonitor.cpp in Sources */, DC5AC0EA1D8354CA00CF422C /* reader.cpp in Sources */, DC5AC0EB1D8354CA00CF422C /* token.cpp in Sources */, DC5AC0EC1D8354CA00CF422C /* tokend.cpp in Sources */, @@ -35447,21 +35695,27 @@ files = ( DCE405C523A04A7F00C4343B /* OctagonTests+CKKSConfiguration.swift in Sources */, 1B8D2D96226E1FA500C94238 /* SetValueTransformer.swift in Sources */, + 0CCC21FC23F33DA900E1FCD0 /* OTICDPRecordContext.m in Sources */, DC5F2BBE2310B941001ADA5D /* OctagonTests+CoreFollowUp.swift in Sources */, DCB468E520EC262C00BA7E5B /* ContainerMap.swift in Sources */, + 0CA1D0B923E9034600021038 /* OctagonTests+EscrowTestVectors.swift in Sources */, 0C4CDE6F22922E550050C499 /* OctagonTests+RecoveryKey.swift in Sources */, EBDE5E0F22BA3DEA00A229C8 /* CKKSMockOctagonAdapter.m in Sources */, DCB468DF20EC25FF00BA7E5B /* Client.swift in Sources */, 0C5824A52286002D009E8C15 /* OctagonTests+HealthCheck.swift in Sources */, + 0C468FFD23C7D4F9006F4582 /* OTEscrowRecord.m in Sources */, DC27C3CE20EAFE9C00F7839C /* CloudKitMockXCTest.m in Sources */, DCB9475821274F9D00ED9272 /* TPHObjcTranslation.m in Sources */, DC27C3CB20EADF3500F7839C /* CloudKitKeychainSyncingMockXCTest.m in Sources */, 0C87D3E4229368BD007853B5 /* OctagonTests+SOS.swift in Sources */, DC27C3C920EADEE700F7839C /* MockCloudKit.m in Sources */, + 0CCC21FD23F33DCE00E1FCD0 /* OTCDPRecoveryInformation.m in Sources */, 0CF70BE0218CF26600EC3515 /* BottledPeer.swift in Sources */, DC99B86B20EACA470065B73B /* spi.c in Sources */, DC4CD9842372294E00EF55FC /* OctagonTests+Helpers.swift in Sources */, + 0C3C47C924902DA50084B951 /* OTSupportOctagonMessage.m in Sources */, DCAA209A23AAF8F600DCB594 /* Container_RecoveryKey.swift in Sources */, + DCA7F7EF23A44AA200927989 /* OctagonPolicyTests.swift in Sources */, DCDF03122284E34B008055BA /* OctagonTests+EscrowRecovery.swift in Sources */, DCFF82712162834D00D54B02 /* OctagonTestsXPCConnections.swift in Sources */, DC5BEACD2217509A001681F0 /* OctagonTests+CloudKitAccount.swift in Sources */, @@ -35469,20 +35723,25 @@ DC07090422936DB2002711B9 /* OctagonTests+ErrorHandling.swift in Sources */, DC99B86C20EACA470065B73B /* FakeCuttlefish.swift in Sources */, 0CBEF3432242CA0600015691 /* TestsObjcTranslation.m in Sources */, + 0C468FFE23C7D4F9006F4582 /* OTEscrowRecordMetadata.m in Sources */, 5A04BB0222982733001848A0 /* OTFollowupTests.m in Sources */, DCB24B45221B901700BE73FE /* CKKSMockSOSPresentAdapter.m in Sources */, DC33D7BE2374FD0A00A68155 /* OTSponsorToApplicantRound2M2.m in Sources */, 0CE15E31222DF63600B7EAA4 /* RecoverKeySet.swift in Sources */, + 0C3C47C824902DA50084B951 /* OTSupportSOSMessage.m in Sources */, + 0C468FFF23C7D4F9006F4582 /* OTEscrowRecordMetadataClientMetadata.m in Sources */, 0CADDF0721545CF100DF8B06 /* OctagonPairingTests.swift in Sources */, DC99B86D20EACA470065B73B /* SecdWatchdog.m in Sources */, DC26666C21CAC97000F19960 /* OTControlCLI.m in Sources */, DC99B86E20EACA470065B73B /* MockCuttlefish.swift in Sources */, 0CF70BE3218CF2AA00EC3515 /* OTBottle.m in Sources */, DC27C3CA20EADF1700F7839C /* CloudKitKeychainSyncingTestsBase.m in Sources */, + 0C3DF8CA24789D0A009CF03A /* Container_Peers.swift in Sources */, 0CF70BE4218CF2AA00EC3515 /* OTBottleContents.m in Sources */, 0C61F1F92194FC82009566D4 /* OTAuthenticatedCiphertext+SF.m in Sources */, DCB0C291222F5E130083AECB /* CuttlefishErrors.swift in Sources */, DC99B86F20EACA470065B73B /* SecFramework.c in Sources */, + 0CBF883D23AAD9F100652EDD /* OctagonTests+EscrowRecords.swift in Sources */, 0C5258BB21BB128000B32C96 /* FakeSOSControl.m in Sources */, DC3A9B2723A9D8BD0073ED06 /* Container_BottledPeers.swift in Sources */, DC99B87020EACA470065B73B /* server_endpoint.m in Sources */, @@ -35510,13 +35769,16 @@ DC99B87320EACA470065B73B /* Decrypter.swift in Sources */, DC99B87420EACA470065B73B /* server_entitlement_helpers.c in Sources */, DC99B87520EACA470065B73B /* TrustedPeersHelper.xcdatamodeld in Sources */, + DC9978B92404AA3200A5EE2F /* Container_UserSync.swift in Sources */, 0CE15E2D222DF63600B7EAA4 /* RecoveryKey.swift in Sources */, DC27C3C120EAD9C300F7839C /* OctagonTests.swift in Sources */, 0CE15E3F222DF6A800B7EAA4 /* OTRecovery.m in Sources */, + 0C0CB73A23AD715A0020C6BF /* Container_EscrowRecords.swift in Sources */, DCB9475A2127534C00ED9272 /* OctagonTests+SOSUpgrade.swift in Sources */, DC7F6A7D233D7FAC00DF5769 /* OctagonTests+ForwardCompatibility.swift in Sources */, DC99B87720EACA470065B73B /* ContainerSync.swift in Sources */, DC33D7BD2374FD0500A68155 /* OTSponsorToApplicantRound1M2.m in Sources */, + 0CCC21FE23F33DD400E1FCD0 /* OTEscrowAuthenticationInformation.m in Sources */, 0C61F1F62194FC79009566D4 /* OTPrivateKey+SF.m in Sources */, DC391FA821C04DAE00772585 /* OctagonPeerKeys.swift in Sources */, DC99B87820EACA470065B73B /* Container.swift in Sources */, @@ -35636,6 +35898,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6C2D463D24C88AA10015C3C9 /* LegacyAPICounts.m in Sources */, DCB3433D1D8A32A20054D16E /* ACL.cpp in Sources */, DCB3433B1D8A32A20054D16E /* Access.cpp in Sources */, DCB3436A1D8A32A20054D16E /* CCallbackMgr.cp in Sources */, @@ -35662,7 +35925,6 @@ DCB342FB1D8A32A20054D16E /* SecBase.cpp in Sources */, DCB3435B1D8A32A20054D16E /* SecCFTypes.cpp in Sources */, DCB342FD1D8A32A20054D16E /* SecCertificate.cpp in Sources */, - DCB342FE1D8A32A20054D16E /* SecCertificateBundle.cpp in Sources */, DCB343921D8A32A20054D16E /* SecExport.cpp in Sources */, DCB343931D8A32A20054D16E /* SecExternalRep.cpp in Sources */, DCB343371D8A32A20054D16E /* SecFDERecoveryAsymmetricCrypto.cpp in Sources */, @@ -35680,7 +35942,6 @@ DCB343021D8A32A20054D16E /* SecItemConstants.c in Sources */, DCB343041D8A32A20054D16E /* SecKey.cpp in Sources */, DCB343051D8A32A20054D16E /* SecKeychain.cpp in Sources */, - DCB3435D1D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp in Sources */, DCB343061D8A32A20054D16E /* SecKeychainItem.cpp in Sources */, DCB343071D8A32A20054D16E /* SecKeychainItemExtendedAttributes.cpp in Sources */, DCB343081D8A32A20054D16E /* SecKeychainSearch.cpp in Sources */, @@ -35780,6 +36041,7 @@ DCAB17CE21FFF75B00E1DFCF /* MockSynchronousEscrowServer.m in Sources */, DCBF4ABB21FFC82100539F0A /* SecFramework.c in Sources */, DCBF4ABE21FFC82100539F0A /* server_entitlement_helpers.c in Sources */, + A6C737C123F37AC00009C930 /* entitlements.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -35795,6 +36057,7 @@ DCC78EE41D808B1B00865A7C /* SecCFAllocator.c in Sources */, DCC78EE31D808B1300865A7C /* SecCMS.c in Sources */, BEEB47D91EA189F5004AA5C6 /* SecTrustStatusCodes.c in Sources */, + 6C220088244F075E000A4557 /* SecItemRateLimit.m in Sources */, DCC78EE21D808B0E00865A7C /* SecCTKKey.m in Sources */, DCC78EE11D808B0900865A7C /* SecCertificate.c in Sources */, DC4269041E82EDAC002B7110 /* SecItem.m in Sources */, @@ -35878,6 +36141,7 @@ DCD068201D8CDF7E007602F1 /* SecRequirement.cpp in Sources */, DCD0681D1D8CDF7E007602F1 /* SecStaticCode.cpp in Sources */, 1F631C5622387FFE005920D8 /* legacydevid.cpp in Sources */, + A6C737BA23F37A4B0009C930 /* entitlements.c in Sources */, DCD0682C1D8CDF7E007602F1 /* StaticCode.cpp in Sources */, DCD0693D1D8CDFFF007602F1 /* String.cpp in Sources */, DCD0693E1D8CDFFF007602F1 /* Token.cpp in Sources */, @@ -36091,6 +36355,7 @@ DC3AA2852097E22A007CA68A /* codesign.c in Sources */, DC8506AD2097EEBC00C712EC /* sos.m in Sources */, DCE4E6931D7A37FA00AFB96E /* NSFileHandle+Formatting.m in Sources */, + BE57B11A2509E1000045B7FD /* ca_revocation_additions.m in Sources */, DC3AA2892097E23A007CA68A /* keychain_find.m in Sources */, DC3AA2792097DF71007CA68A /* readline.c in Sources */, DC3AA2822097E218007CA68A /* add_internet_password.c in Sources */, @@ -36111,7 +36376,6 @@ buildActionMask = 2147483647; files = ( DCE4E7B51D7A43FF00AFB96E /* main.m in Sources */, - DCE4E7B61D7A440A00AFB96E /* bc-10-knife-on-bread.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -36120,7 +36384,6 @@ buildActionMask = 2147483647; files = ( DCE4E7E21D7A4B7F00AFB96E /* main.c in Sources */, - DCE4E7DF1D7A4B4C00AFB96E /* bc-10-knife-on-bread.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -36162,6 +36425,7 @@ DCE4E8C31D7F353900AFB96E /* session.c in Sources */, DCE4E8BC1D7F353900AFB96E /* engine.c in Sources */, DCE4E8C41D7F353900AFB96E /* connection.c in Sources */, + F681C3AB2386B8C30083F22C /* PreloginUserDb.m in Sources */, DCE4E8C11D7F353900AFB96E /* rule.c in Sources */, DCE4E8C01D7F353900AFB96E /* process.c in Sources */, DCE4E8B31D7F353900AFB96E /* agent.c in Sources */, @@ -36209,18 +36473,21 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0C0203E623A857C1005D0A68 /* OTEscrowRecord.proto in Sources */, + BE7B8E132415579900E1CF4F /* SecSharedCredential.m in Sources */, EBDCC002233DD45700806566 /* MockAKSRefKey.proto in Sources */, 0CE15E39222DF67800B7EAA4 /* OTRecovery.proto in Sources */, + 6C6AF17A221A06790091CE0A /* SecDbKeychainSerializedMetadataKey.proto in Sources */, DCE0775621ADD665002662FD /* OTPrivateKey.proto in Sources */, DCE0775321ADD65E002662FD /* OTAuthenticatedCiphertext.proto in Sources */, DCE0775521ADD663002662FD /* OTBottleContents.proto in Sources */, DCE0775421ADD661002662FD /* OTBottle.proto in Sources */, DCF216DE21ADD5F90029CCC1 /* CKKSSerializedKey.proto in Sources */, + DCA992AD2400BB99007959AF /* TPPBAncientEpoch.proto in Sources */, DCF216DF21ADD5FB0029CCC1 /* OTPairingMessage.proto in Sources */, DCF216E121ADD6060029CCC1 /* TPPBVoucher.proto in Sources */, DCF216E021ADD5FD0029CCC1 /* OTAccountMetadataClassC.proto in Sources */, DCE0774721ADD63A002662FD /* TPPBDispositionEntry.proto in Sources */, - DCE0774821ADD63C002662FD /* TPPBAncientEpoch.proto in Sources */, DCE0774621ADD638002662FD /* TPPBDisposition.proto in Sources */, DCE0774921ADD63E002662FD /* TPPBPolicyProhibits.proto in Sources */, DCE0774A21ADD640002662FD /* TPPBUnknownMachineID.proto in Sources */, @@ -36232,6 +36499,7 @@ 5A47FFB3228F5E5500F781B8 /* KCInitialMessageData.proto in Sources */, DCE0775021ADD655002662FD /* TPPBPolicyModelToCategory.proto in Sources */, DCE0775121ADD658002662FD /* TPPBPolicyIntroducersByCategory.proto in Sources */, + 0C0D920C23BFEAB30070A68C /* OTCDPRecoveryInformation.proto in Sources */, DCE0774F21ADD651002662FD /* TPPBPolicyCategoriesByView.proto in Sources */, DC88466B22373A5E00738068 /* TPPBDictionaryMatchingRule.proto in Sources */, DCE0775221ADD65A002662FD /* TPPBPolicyRedaction.proto in Sources */, @@ -36520,6 +36788,7 @@ files = ( EB413B801E663AEB00592085 /* PairingChannel.m in Sources */, 0CB72D9E21E42FCF00D8BC9B /* OTPairingMessage.m in Sources */, + 0C3C47C624902D960084B951 /* OTSupportOctagonMessage.m in Sources */, 0CB72DA121E42FCF00D8BC9B /* OTSponsorToApplicantRound2M2.m in Sources */, E7F480151C73980D00390FDB /* KCJoiningRequestSecretSession.m in Sources */, E7F480331C73FC4C00390FDB /* KCAESGCMDuplexSession.m in Sources */, @@ -36532,6 +36801,7 @@ E7F482AC1C7558F700390FDB /* KCJoiningAcceptSession.m in Sources */, E71454F01C741E0800B5B20B /* KCError.m in Sources */, E772FD471CC15EFA00D63E41 /* NSData+SecRandom.m in Sources */, + 0C3C47C724902D960084B951 /* OTSupportSOSMessage.m in Sources */, 0CB72D9D21E42FCF00D8BC9B /* OTApplicantToSponsorRound2M1.m in Sources */, E7F482AA1C7554FB00390FDB /* NSError+KCCreationHelpers.m in Sources */, E75C0E831C6FC31D00E6953B /* KCSRPContext.m in Sources */, @@ -36613,7 +36883,6 @@ files = ( 6C32BB9920EAE6B00042DF59 /* LocalKeychainAnalytics.m in Sources */, EB1E069D211E16260088F0B1 /* mockaksxcbase.m in Sources */, - 0CC3771320A222BC00B58D2D /* SFSignInAnalytics.m in Sources */, EB49B2DB202DF20F003F34A0 /* spi.c in Sources */, EB49B2D7202DF1F7003F34A0 /* server_endpoint.m in Sources */, EBC73F2020993F8600AE3350 /* SFAnalyticsSQLiteStore.m in Sources */, @@ -36622,6 +36891,7 @@ EB49B2D9202DF1F7003F34A0 /* server_security_helpers.m in Sources */, EBC73F2B2099785900AE3350 /* SFObjCType.m in Sources */, 480ADDB22155A0CE00318FC6 /* SOSAnalytics.m in Sources */, + A6C737C023F37AB90009C930 /* entitlements.c in Sources */, EB49B2E0202DF5D7003F34A0 /* server_entitlement_helpers.c in Sources */, 5A061196229ED6E8006AF14A /* NSDate+SFAnalytics.m in Sources */, EBC73F2A20996AD400AE3350 /* SFSQLiteStatement.m in Sources */, @@ -36664,6 +36934,7 @@ EB6952A4223B75C300F02C1C /* server_xpc.m in Sources */, EB6952A5223B75C300F02C1C /* SecDbKeychainSerializedItemV7.m in Sources */, EB6952A6223B75C300F02C1C /* SecDbQuery.c in Sources */, + 6C2138C4225183FE007DEDD3 /* SecDbKeychainSerializedMetadataKey.m in Sources */, EB6952A7223B75C300F02C1C /* SecuritydXPC.c in Sources */, EB6952A8223B75C300F02C1C /* server_endpoint.m in Sources */, EB6952A9223B75C300F02C1C /* SecDbKeychainItemV7.m in Sources */, @@ -36703,6 +36974,7 @@ EB89086C21F17D3C00F0DDDB /* server_security_helpers.m in Sources */, EB8908B021F18D7B00F0DDDB /* SecDbKeychainSerializedMetadata.m in Sources */, EB89086D21F17D3C00F0DDDB /* server_xpc.m in Sources */, + 6C6AF181221A070C0091CE0A /* SecDbKeychainSerializedMetadataKey.m in Sources */, EB8908B221F18E1400F0DDDB /* SecDbKeychainSerializedItemV7.m in Sources */, EB8908A821F1886100F0DDDB /* SecDbQuery.c in Sources */, EB8908AD21F18CEF00F0DDDB /* SecuritydXPC.c in Sources */, @@ -36791,6 +37063,16 @@ target = DC0BCC211D8C684F00070CB0 /* utilities */; targetProxy = 0C10C93B1DD548BD000602A8 /* PBXContainerItemProxy */; }; + 0C2B36C323C42EBC00000718 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */; + targetProxy = 0C2B36C223C42EBC00000718 /* PBXContainerItemProxy */; + }; + 0C2B36C523C42EC800000718 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */; + targetProxy = 0C2B36C423C42EC800000718 /* PBXContainerItemProxy */; + }; 0C2BCBBC1D0640B200ED7A2F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 0C2BCBA81D06401F00ED7A2F /* dtlsEchoClient */; @@ -36801,15 +37083,15 @@ target = 0C2BCBBD1D0648D100ED7A2F /* dtlsEchoServer */; targetProxy = 0C2BCBD01D0648FA00ED7A2F /* PBXContainerItemProxy */; }; - 0C3E2EA92073F5C400F5B95B /* PBXTargetDependency */ = { + 0C65BB4D23C3F31B0063D2B7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 4C32C0AE0A4975F6002891BD /* Security_ios */; - targetProxy = 0C3E2EA82073F5C400F5B95B /* PBXContainerItemProxy */; + target = 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */; + targetProxy = 0C65BB4C23C3F31B0063D2B7 /* PBXContainerItemProxy */; }; - 0C5663EE20BE2E1A0035F362 /* PBXTargetDependency */ = { + 0C65BB4F23C3F3270063D2B7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DC0BCC211D8C684F00070CB0 /* utilities */; - targetProxy = 0C5663ED20BE2E1A0035F362 /* PBXContainerItemProxy */; + target = 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */; + targetProxy = 0C65BB4E23C3F3270063D2B7 /* PBXContainerItemProxy */; }; 0C78CCE51FCC97E7008B4B24 /* PBXTargetDependency */ = { isa = PBXTargetDependency; @@ -36821,6 +37103,16 @@ target = 0C8BBEFD1FCB446400580909 /* otctl */; targetProxy = 0C78CCE61FCC97F1008B4B24 /* PBXContainerItemProxy */; }; + 0C7EB14D23F3D13C0089097B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; + targetProxy = 0C7EB14C23F3D13C0089097B /* PBXContainerItemProxy */; + }; + 0C7EB14F23F3D1480089097B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC0BCC211D8C684F00070CB0 /* utilities */; + targetProxy = 0C7EB14E23F3D1480089097B /* PBXContainerItemProxy */; + }; 0C85DFD81FB38BB6000343A7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC8834011D8A218F00CE0ACA /* ASN1 */; @@ -36846,11 +37138,6 @@ target = DCC78EA81D8088E200865A7C /* security */; targetProxy = 0C85DFE11FB38BB6000343A7 /* PBXContainerItemProxy */; }; - 0C9AEEBA20783FE000BF6237 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC1789031D77980500B50D50 /* Security_osx */; - targetProxy = 0C9AEEB920783FE000BF6237 /* PBXContainerItemProxy */; - }; 0CA378E923876E0900090B7E /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 0CA378E123876DD100090B7E /* reset_account */; @@ -36866,6 +37153,36 @@ target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; targetProxy = 0CC593F72299EDFC006C34B5 /* PBXContainerItemProxy */; }; + 0CCC22AB23F38B0600E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; + targetProxy = 0CCC22AA23F38B0600E1FCD0 /* PBXContainerItemProxy */; + }; + 0CCC22AD23F38B0E00E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; + targetProxy = 0CCC22AC23F38B0E00E1FCD0 /* PBXContainerItemProxy */; + }; + 0CCC22CE23F39A6300E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */; + targetProxy = 0CCC22CD23F39A6300E1FCD0 /* PBXContainerItemProxy */; + }; + 0CCC22D023F39A6A00E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */; + targetProxy = 0CCC22CF23F39A6A00E1FCD0 /* PBXContainerItemProxy */; + }; + 0CCC22D223F39A7500E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */; + targetProxy = 0CCC22D123F39A7500E1FCD0 /* PBXContainerItemProxy */; + }; + 0CCC22D423F39A7C00E1FCD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CCC220023F357EE00E1FCD0 /* OctagonTrustTests */; + targetProxy = 0CCC22D323F39A7C00E1FCD0 /* PBXContainerItemProxy */; + }; 0CF09210219649DB002B0AEE /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 5346480017331E1100FE9172 /* KeychainSyncAccountNotification */; @@ -36906,6 +37223,11 @@ target = DC0BCC211D8C684F00070CB0 /* utilities */; targetProxy = 3DD258A1204B7DA800F5DA78 /* PBXContainerItemProxy */; }; + 3E88361D24F08F5400E9F4D6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3E88360824F068EF00E9F4D6 /* secseccodeapitest */; + targetProxy = 3E88361C24F08F5400E9F4D6 /* PBXContainerItemProxy */; + }; 438169E71B4EE4B300C54D58 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4381690B1B4EDCBD00C54D58 /* SOSCCAuthPlugin */; @@ -36951,31 +37273,11 @@ target = 4771D971209A755800BA9772 /* KeychainDataclassOwner */; targetProxy = 4771D981209A76B100BA9772 /* PBXContainerItemProxy */; }; - 478D426D1FD72A8100CAB645 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52EDA61D80D58400B0A59C /* secdRegressions */; - targetProxy = 478D426E1FD72A8100CAB645 /* PBXContainerItemProxy */; - }; - 478D426F1FD72A8100CAB645 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC0BCBD91D8C648C00070CB0 /* regressionBase */; - targetProxy = 478D42701FD72A8100CAB645 /* PBXContainerItemProxy */; - }; - 478D42731FD72A8100CAB645 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCC78EA81D8088E200865A7C /* security */; - targetProxy = 478D42741FD72A8100CAB645 /* PBXContainerItemProxy */; - }; 47A6FC6A206B461700BD6C54 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; targetProxy = 47A6FC69206B461700BD6C54 /* PBXContainerItemProxy */; }; - 47A6FC6C206B462400BD6C54 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; - targetProxy = 47A6FC6B206B462400BD6C54 /* PBXContainerItemProxy */; - }; 47C2F18C2059CBEA0062DE30 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 47C2F1822059CB680062DE30 /* KeychainResources */; @@ -37001,11 +37303,6 @@ target = DC1789031D77980500B50D50 /* Security_osx */; targetProxy = 47C51B8A1EEA657D0032D9E5 /* PBXContainerItemProxy */; }; - 47D991D020407F7E0078CAE2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4727FBB61F9918580003AE36 /* secdxctests_ios */; - targetProxy = 47D991CF20407F7E0078CAE2 /* PBXContainerItemProxy */; - }; 47DE88CE1FA7AD6200DD3254 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DCC78EA81D8088E200865A7C /* security */; @@ -37041,81 +37338,81 @@ target = 5346480017331E1100FE9172 /* KeychainSyncAccountNotification */; targetProxy = 5346481A17331ED800FE9172 /* PBXContainerItemProxy */; }; - 6C4AA1AA2228B640006FA945 /* PBXTargetDependency */ = { + 5AAE383623D261CF0025CF9E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */; - targetProxy = 6C4AA1A92228B640006FA945 /* PBXContainerItemProxy */; + target = 5A442F81233C330F00918373 /* experimentTool */; + targetProxy = 5AAE383523D261CF0025CF9E /* PBXContainerItemProxy */; }; - 6C8FF4B6224C1A9800E5C812 /* PBXTargetDependency */ = { + 6C14CA0423C4F6830097B572 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = BEF88C271EAFFC3F00357577 /* TrustedPeers */; - targetProxy = 6C8FF4B5224C1A9800E5C812 /* PBXContainerItemProxy */; - }; - 6C98082F1E788AEB00E70590 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC8834011D8A218F00CE0ACA /* ASN1 */; - targetProxy = 6C9808301E788AEB00E70590 /* PBXContainerItemProxy */; + target = 4718AE2E205B39C40068EC3F /* libsecurityd_bridge */; + targetProxy = 6C14CA0323C4F6830097B572 /* PBXContainerItemProxy */; }; - 6C9808311E788AEB00E70590 /* PBXTargetDependency */ = { + 6C16258123C4FFC40086A0FF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DC0BCC211D8C684F00070CB0 /* utilities */; - targetProxy = 6C9808321E788AEB00E70590 /* PBXContainerItemProxy */; + target = D4ADA3181E2B41670031CEA3 /* libtrustd */; + targetProxy = 6C16258023C4FFC40086A0FF /* PBXContainerItemProxy */; }; - 6C9808351E788AEB00E70590 /* PBXTargetDependency */ = { + 6C16258423C4FFD40086A0FF /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; - targetProxy = 6C9808361E788AEB00E70590 /* PBXContainerItemProxy */; + targetProxy = 6C16258323C4FFD40086A0FF /* PBXContainerItemProxy */; }; - 6C9808371E788AEB00E70590 /* PBXTargetDependency */ = { + 6C16258623C4FFD40086A0FF /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; - targetProxy = 6C9808381E788AEB00E70590 /* PBXContainerItemProxy */; + targetProxy = 6C16258523C4FFD40086A0FF /* PBXContainerItemProxy */; }; - 6C9808391E788AEB00E70590 /* PBXTargetDependency */ = { + 6C2045F82424BC4400F9461D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DCC78EA81D8088E200865A7C /* security */; - targetProxy = 6C98083A1E788AEB00E70590 /* PBXContainerItemProxy */; + target = 6C2045E92424BA7E00F9461D /* KeychainStasher */; + targetProxy = 6C2045F72424BC4400F9461D /* PBXContainerItemProxy */; }; - 6C98086B1E788AFD00E70590 /* PBXTargetDependency */ = { + 6C2D797322C06CEB00C3CE32 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DC8834011D8A218F00CE0ACA /* ASN1 */; - targetProxy = 6C98086C1E788AFD00E70590 /* PBXContainerItemProxy */; + target = 6C39234421F13E4D00D018AD /* SecDbBackupTests */; + targetProxy = 6C2D797222C06CEB00C3CE32 /* PBXContainerItemProxy */; }; - 6C98086D1E788AFD00E70590 /* PBXTargetDependency */ = { + 6C2D797522C06CEF00C3CE32 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DC0BCC211D8C684F00070CB0 /* utilities */; - targetProxy = 6C98086E1E788AFD00E70590 /* PBXContainerItemProxy */; + target = 4727FBB61F9918580003AE36 /* secdxctests */; + targetProxy = 6C2D797422C06CEF00C3CE32 /* PBXContainerItemProxy */; }; - 6C9808711E788AFD00E70590 /* PBXTargetDependency */ = { + 6C4AA1AA2228B640006FA945 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; - targetProxy = 6C9808721E788AFD00E70590 /* PBXContainerItemProxy */; + target = EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */; + targetProxy = 6C4AA1A92228B640006FA945 /* PBXContainerItemProxy */; }; - 6C9808731E788AFD00E70590 /* PBXTargetDependency */ = { + 6C61D3E8242A29BA008AB9BB /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; - targetProxy = 6C9808741E788AFD00E70590 /* PBXContainerItemProxy */; + target = 6C963280242A279B00C53CE2 /* stashtester */; + targetProxy = 6C61D3E7242A29BA008AB9BB /* PBXContainerItemProxy */; }; - 6C9808751E788AFD00E70590 /* PBXTargetDependency */ = { + 6C7BE2AA23C3DD64003BB2CA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = DCC78EA81D8088E200865A7C /* security */; - targetProxy = 6C9808761E788AFD00E70590 /* PBXContainerItemProxy */; + target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; + targetProxy = 6C7BE2AB23C3DD64003BB2CA /* PBXContainerItemProxy */; }; - 6C9808A01E788B9400E70590 /* PBXTargetDependency */ = { + 6C7BE2AC23C3DD64003BB2CA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */; - targetProxy = 6C98089F1E788B9400E70590 /* PBXContainerItemProxy */; + target = DC0BCC211D8C684F00070CB0 /* utilities */; + targetProxy = 6C7BE2AD23C3DD64003BB2CA /* PBXContainerItemProxy */; }; - 6C9808A41E788CB100E70590 /* PBXTargetDependency */ = { + 6C7BE2EA23C3DD9C003BB2CA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 6CF4A0DF1E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */; - targetProxy = 6C9808A31E788CB100E70590 /* PBXContainerItemProxy */; + target = 6C7BE2A923C3DD64003BB2CA /* securitytool_bridge */; + targetProxy = 6C7BE2E923C3DD9C003BB2CA /* PBXContainerItemProxy */; }; 6C9A49B21FAB647D00239D58 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC0BCC211D8C684F00070CB0 /* utilities */; targetProxy = 6C9A49B11FAB647D00239D58 /* PBXContainerItemProxy */; }; + 6CA9690D24ACC5C100C08B5E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC0BCC211D8C684F00070CB0 /* utilities */; + targetProxy = 6CA9690C24ACC5C100C08B5E /* PBXContainerItemProxy */; + }; 6CAA8D3D1F8431BC007B6E03 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 6CAA8D1F1F842FB3007B6E03 /* securityuploadd */; @@ -37126,6 +37423,56 @@ target = 6CAA8D1F1F842FB3007B6E03 /* securityuploadd */; targetProxy = 6CAA8D3E1F8431C9007B6E03 /* PBXContainerItemProxy */; }; + 6CC638E7226695B900E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; + targetProxy = 6CC638E6226695B900E5DB0B /* PBXContainerItemProxy */; + }; + 6CC638E9226695B900E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; + targetProxy = 6CC638E8226695B900E5DB0B /* PBXContainerItemProxy */; + }; + 6CC638EB226695C300E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; + targetProxy = 6CC638EA226695C300E5DB0B /* PBXContainerItemProxy */; + }; + 6CC638ED226695C300E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; + targetProxy = 6CC638EC226695C300E5DB0B /* PBXContainerItemProxy */; + }; + 6CC638FE2266AE0A00E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4727FBB61F9918580003AE36 /* secdxctests */; + targetProxy = 6CC638FD2266AE0A00E5DB0B /* PBXContainerItemProxy */; + }; + 6CC639002266AE0A00E5DB0B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6C39234421F13E4D00D018AD /* SecDbBackupTests */; + targetProxy = 6CC638FF2266AE0A00E5DB0B /* PBXContainerItemProxy */; + }; + 6CE2AEAB22B2C1BE00C96AE7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp */; + targetProxy = 6CE2AEAA22B2C1BE00C96AE7 /* PBXContainerItemProxy */; + }; + 6CE2AEAD22B2C1C300C96AE7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp */; + targetProxy = 6CE2AEAC22B2C1C300C96AE7 /* PBXContainerItemProxy */; + }; + 6CF33CA62387156600D1E75D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4727FBB61F9918580003AE36 /* secdxctests */; + targetProxy = 6CF33CA52387156600D1E75D /* PBXContainerItemProxy */; + }; + 6CF33CA82387157200D1E75D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4727FBB61F9918580003AE36 /* secdxctests */; + targetProxy = 6CF33CA72387157200D1E75D /* PBXContainerItemProxy */; + }; 873C14B221540FED003C9C00 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC0BCC211D8C684F00070CB0 /* utilities */; @@ -37406,11 +37753,6 @@ target = 6CCDF7831E3C25FA003F2555 /* KeychainEntitledTestRunner */; targetProxy = D45D8F812224DBE300D6C124 /* PBXContainerItemProxy */; }; - D45D8F842224DBEF00D6C124 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6C9808681E788AFD00E70590 /* CKKSCloudKitTests_ios */; - targetProxy = D45D8F832224DBEF00D6C124 /* PBXContainerItemProxy */; - }; D45D8F862224DBF800D6C124 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC3502B41E0208BE00BC0587 /* CKKSTests */; @@ -37516,11 +37858,6 @@ target = BEF88C2F1EAFFC3F00357577 /* TrustedPeersTests */; targetProxy = D477EE8021ED48DF00C9AAFF /* PBXContainerItemProxy */; }; - D477EE8321ED48E800C9AAFF /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 478D426C1FD72A8100CAB645 /* secdxctests_mac */; - targetProxy = D477EE8221ED48E800C9AAFF /* PBXContainerItemProxy */; - }; D4794E6B21222E72007C6725 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC8834011D8A218F00CE0ACA /* ASN1 */; @@ -37551,16 +37888,6 @@ target = DC3502B41E0208BE00BC0587 /* CKKSTests */; targetProxy = D4A763D82224BD990063B2B9 /* PBXContainerItemProxy */; }; - D4A763DB2224BDAB0063B2B9 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6C98082C1E788AEB00E70590 /* CKKSCloudKitTests_mac */; - targetProxy = D4A763DA2224BDAB0063B2B9 /* PBXContainerItemProxy */; - }; - D4A763DD2224BDCC0063B2B9 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */; - targetProxy = D4A763DC2224BDCC0063B2B9 /* PBXContainerItemProxy */; - }; D4A763DF2224BDDC0063B2B9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */; @@ -37756,16 +38083,6 @@ target = 47702B2D1E5F492C00B29577 /* seckeychainnetworkextensionunauthorizedaccesstest */; targetProxy = D4E0E9732224DE8200A802E0 /* PBXContainerItemProxy */; }; - D4E0E9762224DE9100A802E0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4727FBB61F9918580003AE36 /* secdxctests_ios */; - targetProxy = D4E0E9752224DE9100A802E0 /* PBXContainerItemProxy */; - }; - D4E0E97A2224DEE600A802E0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6CF4A0DF1E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */; - targetProxy = D4E0E9792224DEE600A802E0 /* PBXContainerItemProxy */; - }; D4E0E97C2224DF0300A802E0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4CB740A20A47567C00D641BB /* securitytool_ios */; @@ -37881,11 +38198,6 @@ target = 47702B2D1E5F492C00B29577 /* seckeychainnetworkextensionunauthorizedaccesstest */; targetProxy = D4E0E9A92224DFDD00A802E0 /* PBXContainerItemProxy */; }; - D4E0E9AC2224DFEB00A802E0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4727FBB61F9918580003AE36 /* secdxctests_ios */; - targetProxy = D4E0E9AB2224DFEB00A802E0 /* PBXContainerItemProxy */; - }; D4E0E9AE2224E00600A802E0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4CB740A20A47567C00D641BB /* securitytool_ios */; @@ -38481,21 +38793,6 @@ target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; targetProxy = DC311E662124A9D2002F5EAE /* PBXContainerItemProxy */; }; - DC34CD2D20326C2C00302481 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; - targetProxy = DC34CD2C20326C2C00302481 /* PBXContainerItemProxy */; - }; - DC34CD3420326C3100302481 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; - targetProxy = DC34CD3320326C3100302481 /* PBXContainerItemProxy */; - }; - DC34CD3620326C3B00302481 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC0BCC211D8C684F00070CB0 /* utilities */; - targetProxy = DC34CD3520326C3B00302481 /* PBXContainerItemProxy */; - }; DC3502C41E020D4D00BC0587 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC8834011D8A218F00CE0ACA /* ASN1 */; @@ -38846,11 +39143,6 @@ target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; targetProxy = DC69A5822165295F00512BD6 /* PBXContainerItemProxy */; }; - DC69A5872165298500512BD6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; - targetProxy = DC69A5862165298500512BD6 /* PBXContainerItemProxy */; - }; DC6BC2741D90D07800DD57B3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC6BC26C1D90CFEF00DD57B3 /* securityd_macos_startup */; @@ -38926,16 +39218,6 @@ target = DC8834011D8A218F00CE0ACA /* ASN1 */; targetProxy = DC89998A1E410DBF00E6E604 /* PBXContainerItemProxy */; }; - DC93C4C9214713DC008F8362 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; - targetProxy = DC93C4C8214713DC008F8362 /* PBXContainerItemProxy */; - }; - DC93C4CD21471401008F8362 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E7731D80BC8000B0A59C /* libsecurityd_ios */; - targetProxy = DC93C4CC21471401008F8362 /* PBXContainerItemProxy */; - }; DC99B85C20EACA470065B73B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DC8834011D8A218F00CE0ACA /* ASN1 */; @@ -39186,16 +39468,6 @@ target = DCD66DC41D8205C400DB1393 /* SecOtrOSX */; targetProxy = DCD66DE51D82061F00DB1393 /* PBXContainerItemProxy */; }; - DCD6BF5421E919610015F7A8 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; - targetProxy = DCD6BF5321E919610015F7A8 /* PBXContainerItemProxy */; - }; - DCD6BF5621E9196E0015F7A8 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; - targetProxy = DCD6BF5521E9196E0015F7A8 /* PBXContainerItemProxy */; - }; DCD6BF5821E919820015F7A8 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; @@ -39291,6 +39563,11 @@ target = DCDA5E4F2124B9C5009B11B2 /* aks_support */; targetProxy = DCDA5E632124BCA9009B11B2 /* PBXContainerItemProxy */; }; + DCE27861245B81BD00381FE8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4771D971209A755800BA9772 /* KeychainDataclassOwner */; + targetProxy = DCE27860245B81BD00381FE8 /* PBXContainerItemProxy */; + }; DCE4E8D81D7F37F200AFB96E /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DCE4E8931D7F34F600AFB96E /* authd */; @@ -39601,16 +39878,6 @@ target = DC0BC5501D8B6D2D00070CB0 /* XPCKeychainSandboxCheck */; targetProxy = EBD31B411E0A18A600FBE9FA /* PBXContainerItemProxy */; }; - EBD7DF8121FF475B0089F2DF /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */; - targetProxy = EBD7DF8021FF475B0089F2DF /* PBXContainerItemProxy */; - }; - EBD7DF8321FF475B0089F2DF /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */; - targetProxy = EBD7DF8221FF475B0089F2DF /* PBXContainerItemProxy */; - }; EBF374821DC058B60065D840 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = EBF374711DC055580065D840 /* security-sysdiagnose */; @@ -39842,6 +40109,7 @@ "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = secdtests; STRIP_STYLE = debugging; @@ -39877,6 +40145,7 @@ "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = secdtests; STRIP_STYLE = debugging; @@ -40121,16 +40390,15 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "keychain/otctl/otctl-Entitlements.plist"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -40141,56 +40409,63 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "keychain/otctl/otctl-Entitlements.plist"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; - 0C9AEEB520783FBB00BF6237 /* Debug */ = { + 0CA378E423876DD100090B7E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 0CA378E523876DD100090B7E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 0CCC227723F357EE00E1FCD0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 725D438D212CAA3B007B49E4 /* xcconfig/swift_binary_shim.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/../../AppleInternal/Library/Frameworks", + ); GCC_PREPROCESSOR_DEFINITIONS = ( "NO_SERVER=1", + "DEBUG=1", "$(inherited)", ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = "keychain/Signin Metrics/Resources/SFTMTests-Info.plist"; + INFOPLIST_FILE = "keychain/OctagonTrust/ot-tests/OctagonTrustTests-Info.plist"; INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", + /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks, ); - "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", + /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks, ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( + LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", + "$(SDKROOT)/usr/local/lib/security_libDER", ); - MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", "$(OTHER_LDFLAGS_PROTOBUF)", "$(OTHER_LDFLAGS_MOBILEGESTALT)", @@ -40198,90 +40473,61 @@ "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", "$(OTHER_LDFLAGS_APS)", "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", "$(OTHER_LDFLAGS_PREQUELITE)", "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", "-ObjC", - "$(OTHER_LDFLAGS_CrashReporterSupport)", "$(OTHER_LDFLAGS_CORECDP)", "$(OTHER_LDFLAGS_IMCORE)", + "$(OTHER_LDFLAGS_FOR_SECURITYD)", "$(OTHER_LDFLAGS_ACCOUNTS)", + "-framework", + Security, + "$(OTHER_LDFLAGS_UserManagement)", + "$(OTHER_LDFLAGS_CLOUDSERVICES)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SFTMTests; + OTHER_SWIFT_FLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.OctagonTrustTests; PRODUCT_NAME = "$(TARGET_NAME)"; - USE_XCTRUNNER = YES; + SKIP_INSTALL = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_INTERFACE_HEADER_NAME = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = ""; }; name = Debug; }; - 0C9AEEB620783FBB00BF6237 /* Release */ = { + 0CCC227823F357EE00E1FCD0 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 725D438D212CAA3B007B49E4 /* xcconfig/swift_binary_shim.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/../../AppleInternal/Library/Frameworks", + ); GCC_PREPROCESSOR_DEFINITIONS = ( "NO_SERVER=1", + "NDEBUG=1", "$(inherited)", ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = "keychain/Signin Metrics/Resources/SFTMTests-Info.plist"; + INFOPLIST_FILE = "keychain/OctagonTrust/ot-tests/OctagonTrustTests-Info.plist"; INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", + /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks, ); - "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", + /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks, ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( + LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", + "$(SDKROOT)/usr/local/lib/security_libDER", ); - MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", "$(OTHER_LDFLAGS_PROTOBUF)", "$(OTHER_LDFLAGS_MOBILEGESTALT)", @@ -40294,177 +40540,114 @@ "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", "-ObjC", - "$(OTHER_LDFLAGS_CrashReporterSupport)", + "$(OTHER_LDFLAGS_CORECDP)", "$(OTHER_LDFLAGS_IMCORE)", + "$(OTHER_LDFLAGS_FOR_SECURITYD)", "$(OTHER_LDFLAGS_ACCOUNTS)", + "-framework", + Security, + "$(OTHER_LDFLAGS_UserManagement)", + "$(OTHER_LDFLAGS_CLOUDSERVICES)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SFTMTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - USE_XCTRUNNER = YES; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 0CA378E423876DD100090B7E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 0CA378E523876DD100090B7E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { + OTHER_SWIFT_FLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.OctagonTrustTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = NO; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_INTERFACE_HEADER_NAME = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = ""; }; name = Release; }; - 0CF4064E2072E3E3003D6A7F /* Debug */ = { + 0CD743AC23C3EC8000FA0EC5 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "$(inherited)", - ); + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "$(INSTALL_PATH)"; + EXPORTED_SYMBOLS_FILE = ""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = "keychain/Signin Metrics/Resources/SFTMTests-Info.plist"; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; + INFOPLIST_FILE = keychain/OctagonTrust/Info.plist; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ""; + MODULEMAP_FILE = Modules/OctagonTrust.modulemap; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_CrashReporterSupport)", - "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", + "$(OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER)", + "$(OTHER_LDFLAGS_UPWARD_FOUNDATION)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SFTMTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - USE_XCTRUNNER = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.octagontrust; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx.internal; + SKIP_INSTALL = NO; + TAPI_VERIFY_MODE = ErrorsAndWarnings; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 0CF4064F2072E3E3003D6A7F /* Release */ = { + 0CD743AD23C3EC8000FA0EC5 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "$(inherited)", - ); + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "$(INSTALL_PATH)"; + ENABLE_NS_ASSERTIONS = NO; + EXPORTED_SYMBOLS_FILE = ""; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = "keychain/Signin Metrics/Resources/SFTMTests-Info.plist"; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); + INFOPLIST_FILE = keychain/OctagonTrust/Info.plist; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ""; + MODULEMAP_FILE = Modules/OctagonTrust.modulemap; MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_CORECDP)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-ObjC", - "$(OTHER_LDFLAGS_CrashReporterSupport)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", + "$(OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER)", + "$(OTHER_LDFLAGS_UPWARD_FOUNDATION)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SFTMTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - USE_XCTRUNNER = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.octagontrust; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx.internal; + SKIP_INSTALL = NO; + TAPI_VERIFY_MODE = ErrorsAndWarnings; + TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Release; }; @@ -40483,7 +40666,6 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -40508,9 +40690,7 @@ "-Wglobal-constructors", "-Wmost", "-Wno-four-char-constants", - "-Wno-unknown-pragmas", "$(inherited)", - "-Wno-error=c++11-narrowing", ); }; name = Debug; @@ -40530,7 +40710,6 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -40555,9 +40734,7 @@ "-Wglobal-constructors", "-Wmost", "-Wno-four-char-constants", - "-Wno-unknown-pragmas", "$(inherited)", - "-Wno-error=c++11-narrowing", ); }; name = Release; @@ -40807,6 +40984,74 @@ }; name = Release; }; + 3E88360F24F068EF00E9F4D6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = ""; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; + }; + name = Debug; + }; + 3E88361024F068EF00E9F4D6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; 438169101B4EDCBD00C54D58 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -40837,13 +41082,11 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionstest/seckeychainnetworkextensionstest.entitlements; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; @@ -40859,14 +41102,12 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionstest/seckeychainnetworkextensionstest.entitlements; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; MTL_ENABLE_DEBUG_INFO = NO; @@ -40924,10 +41165,7 @@ ); PRODUCT_NAME = securityd; STRIP_STYLE = debugging; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -40980,10 +41218,7 @@ ); PRODUCT_NAME = securityd; STRIP_STYLE = debugging; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -41043,7 +41278,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; @@ -41076,6 +41310,11 @@ "$(OTHER_LDFLAGS_AKS_ACL_LIBRARY)", "$(OTHER_LDFLAGS_UserManagement)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", + "$(OTHER_LDFLAGS_COREANALYTICS)", + "$(OTHER_LDFLAGS_MOBILEGESTALT)", + "$(OTHER_LDFLAGS_ACCOUNTS)", + "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", + "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", "$(OTHER_LDFLAGS_CORECDP)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", ); @@ -41091,7 +41330,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; @@ -41124,6 +41362,11 @@ "$(OTHER_LDFLAGS_AKS_ACL_LIBRARY)", "$(OTHER_LDFLAGS_UserManagement)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", + "$(OTHER_LDFLAGS_COREANALYTICS)", + "$(OTHER_LDFLAGS_MOBILEGESTALT)", + "$(OTHER_LDFLAGS_ACCOUNTS)", + "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", + "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", "$(OTHER_LDFLAGS_CORECDP)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", ); @@ -41140,13 +41383,11 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionsystemdaemontest/seckeychainnetworkextensionsystemdaemontest.entitlements; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; @@ -41162,14 +41403,12 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionsystemdaemontest/seckeychainnetworkextensionsystemdaemontest.entitlements; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; MTL_ENABLE_DEBUG_INFO = NO; @@ -41184,13 +41423,11 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionunauthorizedaccesstest/seckeychainnetworkextensionunauthorizedaccesstest.entitlements; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; @@ -41206,14 +41443,12 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = RegressionTests/seckeychainnetworkextensionunauthorizedaccesstest/seckeychainnetworkextensionunauthorizedaccesstest.entitlements; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; MTL_ENABLE_DEBUG_INFO = NO; @@ -41225,33 +41460,20 @@ 4771D976209A755800BA9772 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INFOPLIST_FILE = keychain/KeychainDataclassOwner/Info.plist; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Accounts/DataclassOwners"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = com.apple.KeychainDataclassOwner; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos.internal; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,6"; WRAPPER_EXTENSION = bundle; }; name = Debug; @@ -41259,23 +41481,13 @@ 4771D977209A755800BA9772 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_STYLE = Automatic; ENABLE_NS_ASSERTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INFOPLIST_FILE = keychain/KeychainDataclassOwner/Info.plist; @@ -41283,113 +41495,18 @@ MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = com.apple.KeychainDataclassOwner; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos.internal; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,6"; VALIDATE_PRODUCT = YES; WRAPPER_EXTENSION = bundle; }; name = Release; }; - 478D429A1FD72A8100CAB645 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_MODULES = NO; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_STRICT_PROTOTYPES = NO; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "secdtests/secdtests-entitlements.plist"; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = dwarf; - GCC_DYNAMIC_NO_PIC = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = secdxctests/Info.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_AKS_ACL_LIBRARY)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.secdxctests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 478D429B1FD72A8100CAB645 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_MODULES = NO; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_STRICT_PROTOTYPES = NO; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "secdtests/secdtests-entitlements.plist"; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Automatic; - COPY_PHASE_STRIP = NO; - ENABLE_NS_ASSERTIONS = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = secdxctests/Info.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - "@loader_path/../Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_AKS_ACL_LIBRARY)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.secdxctests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; 47C2F1882059CB690062DE30 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; @@ -41422,7 +41539,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; @@ -41455,7 +41571,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -41488,7 +41603,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -41519,7 +41633,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -41530,7 +41643,6 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = CircleJoinRequested/entitlements.plist; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -41573,7 +41685,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -41585,7 +41696,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = CircleJoinRequested/entitlements.plist; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_UNDECLARED_SELECTOR = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -41661,6 +41771,7 @@ "$(OTHER_LDFLAGS_SECUREKEYVAULT)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = SecurityDevTests; @@ -41703,6 +41814,7 @@ "$(OTHER_LDFLAGS_SECUREKEYVAULT)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = SecurityDevTests; @@ -41769,7 +41881,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -41782,7 +41893,6 @@ COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; @@ -41814,7 +41924,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -41827,7 +41936,6 @@ COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; HEADERMAP_INCLUDES_FRAMEWORK_ENTRIES_FOR_ALL_PRODUCT_TYPES = ""; HEADER_SEARCH_PATHS = ( @@ -41855,7 +41963,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_ARC = YES; @@ -41868,7 +41975,6 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "KeychainSyncAccountNotification/KeychainSyncAccountNotification-Prefix.pch"; @@ -41893,7 +41999,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_ARC = YES; @@ -41907,7 +42012,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "KeychainSyncAccountNotification/KeychainSyncAccountNotification-Prefix.pch"; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -41928,12 +42032,10 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "experiment/tool/experimentTool-Entitlements.plist"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; @@ -41948,14 +42050,12 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "experiment/tool/experimentTool-Entitlements.plist"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = NO; @@ -41967,7 +42067,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -41981,7 +42080,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -42005,7 +42103,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -42020,7 +42117,6 @@ COMBINE_HIDPI_IMAGES = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -42108,7 +42204,7 @@ }; name = Release; }; - 6C39237721F13E4D00D018AD /* Debug */ = { + 6C2045EF2424BA7F00F9461D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -42116,6 +42212,66 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/KeychainStasher/KeychainStasher.entitlements"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + INFOPLIST_FILE = "$(SRCROOT)/keychain/KeychainStasher/KeychainStasher-Info.plist"; + INSTALL_PATH = /usr/libexec; + MACOSX_DEPLOYMENT_TARGET = 10.16; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainStasher; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + }; + name = Debug; + }; + 6C2045F02424BA7F00F9461D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/KeychainStasher/KeychainStasher.entitlements"; + CODE_SIGN_STYLE = Automatic; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + INFOPLIST_FILE = "$(SRCROOT)/keychain/KeychainStasher/KeychainStasher-Info.plist"; + INSTALL_PATH = /usr/libexec; + MACOSX_DEPLOYMENT_TARGET = 10.16; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainStasher; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + }; + name = Release; + }; + 6C39237721F13E4D00D018AD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = NO; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -42125,11 +42281,8 @@ CLANG_WARN_STRICT_PROTOTYPES = NO; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = tests/SecDbBackupTests/Entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_ENTITLEMENTS = "tests/SecDbBackupTests/SecDbBackupTests-Entitlements.plist"; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = ""; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; @@ -42157,8 +42310,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.secdbbackuptests; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - USES_XCTRUNNER = YES; + REEXPORTED_LIBRARY_PATHS = ""; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Debug; }; @@ -42168,7 +42321,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; @@ -42179,11 +42331,8 @@ CLANG_WARN_STRICT_PROTOTYPES = NO; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = tests/SecDbBackupTests/Entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_ENTITLEMENTS = "tests/SecDbBackupTests/SecDbBackupTests-Entitlements.plist"; COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = ""; ENABLE_NS_ASSERTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; @@ -42211,8 +42360,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.secdbbackuptests; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - USES_XCTRUNNER = YES; + REEXPORTED_LIBRARY_PATHS = ""; + TEST_BUILD_STYLE = _APPLEINTERNAL; VALIDATE_PRODUCT = YES; }; name = Release; @@ -42225,7 +42374,6 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INFOPLIST_FILE = "$(SRCROOT)/supd/Tests/Info.plist"; @@ -42263,7 +42411,6 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INFOPLIST_FILE = "$(SRCROOT)/supd/Tests/Info.plist"; @@ -42294,264 +42441,120 @@ }; name = Release; }; - 6C98085F1E788AEB00E70590 /* Debug */ = { + 6C7BE2E523C3DD64003BB2CA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "NO_LIBTRUSTD=1", - "$(inherited)", - ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGN_ENTITLEMENTS = SecurityTool/sharedTool/iOS/entitlements.plist; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = keychain/ckks/tests/CKKSCloudKitTestsInfo.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; + GCC_WARN_SHADOW = NO; + INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "$(OTHER_LDFLAGS_ACM_LIBRARY)", "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "$(OTHER_LDFLAGS_SECURITYFOUNDATION)", "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "-framework", - CrashReporterSupport, - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.CKKSCloudKitTests; - PRODUCT_NAME = CKKSCloudKitTests; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KeychainEntitledTestApp_mac.app/Contents/MacOS/KeychainEntitledTestApp_mac"; + PRODUCT_NAME = "$(TARGET_NAME)"; + REEXPORTED_LIBRARY_PATHS = ""; + STRIP_STYLE = debugging; }; name = Debug; }; - 6C9808601E788AEB00E70590 /* Release */ = { + 6C7BE2E623C3DD64003BB2CA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "NO_LIBTRUSTD=1", - "$(inherited)", - ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGN_ENTITLEMENTS = SecurityTool/sharedTool/iOS/entitlements.plist; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = keychain/ckks/tests/CKKSCloudKitTestsInfo.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = NO; + GCC_WARN_SHADOW = NO; + INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "$(OTHER_LDFLAGS_ACM_LIBRARY)", "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "$(OTHER_LDFLAGS_SECURITYFOUNDATION)", "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_CrashReporterSupport)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.CKKSCloudKitTests; - PRODUCT_NAME = CKKSCloudKitTests; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KeychainEntitledTestApp_mac.app/Contents/MacOS/KeychainEntitledTestApp_mac"; - VALIDATE_PRODUCT = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + REEXPORTED_LIBRARY_PATHS = ""; + STRIP_STYLE = debugging; }; name = Release; }; - 6C98089B1E788AFD00E70590 /* Debug */ = { + 6C963285242A279B00C53CE2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "NO_LIBTRUSTD=1", - "$(inherited)", - ); + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/stashtester/stashtester.entitlements"; + CODE_SIGN_STYLE = Manual; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = keychain/ckks/tests/CKKSCloudKitTestsInfo.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_CrashReporterSupport)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.CKKSCloudKitTests; - PRODUCT_NAME = CKKSCloudKitTests; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KeychainEntitledTestApp_ios.app/KeychainEntitledTestApp_ios"; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MACOSX_DEPLOYMENT_TARGET = 10.16; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx.internal; }; name = Debug; }; - 6C98089C1E788AFD00E70590 /* Release */ = { + 6C963286242A279B00C53CE2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NO_SERVER=1", - "NO_LIBTRUSTD=1", - "$(inherited)", - ); + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/stashtester/stashtester.entitlements"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = keychain/ckks/tests/CKKSCloudKitTestsInfo.plist; - INSTALL_PATH = "$(SECURITY_XCTEST_DIRECTORY)"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MACOSX_DEPLOYMENT_TARGET = 10.16; MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", - "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", - "$(OTHER_LDFLAGS_PROTOBUF)", - "$(OTHER_LDFLAGS_MOBILEGESTALT)", - "$(OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT)", - "$(OTHER_LDFLAGS_APPLESYSTEMINFO)", - "$(OTHER_LDFLAGS_APS)", - "$(OTHER_LDFLAGS_CLOUDKIT)", - "$(OTHER_LDFLAGS_PREQUELITE)", - "$(OTHER_LDFLAGS_WIRELESSDIAGNOSTICS)", - "$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)", - "$(OTHER_LDFLAGS_CrashReporterSupport)", - "$(OTHER_LDFLAGS_IMCORE)", - "$(OTHER_LDFLAGS_ACCOUNTS)", - "$(OTHER_LDFLAGS_UserManagement)", - "$(OTHER_LDFLAGS_FOR_SECURITYD)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.CKKSCloudKitTests; - PRODUCT_NAME = CKKSCloudKitTests; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KeychainEntitledTestApp_ios.app/KeychainEntitledTestApp_ios"; - VALIDATE_PRODUCT = YES; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx.internal; }; name = Release; }; @@ -42561,7 +42564,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -42586,7 +42588,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -42612,7 +42613,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -42647,7 +42647,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -42683,29 +42682,23 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements"; DEBUG_INFORMATION_FORMAT = dwarf; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - "$(PLATFORM_DIR)/Developer/AppleInternal/Library/Frameworks", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; LD_RUNPATH_SEARCH_PATHS = ( /Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Debug; }; @@ -42715,29 +42708,23 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - "$(PLATFORM_DIR)/Developer/AppleInternal/Library/Frameworks", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; LD_RUNPATH_SEARCH_PATHS = ( /Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Release; }; @@ -42748,26 +42735,26 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements"; COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = KeychainEntitledTestApp_mac/Info.plist; - INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + INFOPLIST_FILE = "$(SOURCE_ROOT)/tests/TestHostBinaries/KeychainEntitledTestApp/Info.plist"; + INFOPLIST_PREPROCESS = YES; + INSTALL_PATH = /AppleInternal/Applications; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); MTL_ENABLE_DEBUG_INFO = YES; OTHER_CODE_SIGN_FLAGS = "--deep"; - PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.KeychainEntitledTestApp-mac"; + OTHER_LDFLAGS = "$(OTHER_LDFLAGS_AppFrameworks)"; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainEntitledTestApp; PRODUCT_NAME = KeychainEntitledTestApp; }; name = Debug; @@ -42779,92 +42766,28 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; + CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - INFOPLIST_FILE = KeychainEntitledTestApp_mac/Info.plist; - INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + INSTALL_PATH = /AppleInternal/Applications; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); MTL_ENABLE_DEBUG_INFO = NO; OTHER_CODE_SIGN_FLAGS = "--deep"; - PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.KeychainEntitledTestApp-mac"; + OTHER_LDFLAGS = "$(OTHER_LDFLAGS_AppFrameworks)"; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainEntitledTestApp; PRODUCT_NAME = KeychainEntitledTestApp; }; name = Release; }; - 6CF4A0F51E4549F300ECD7B5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; - DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - INFOPLIST_FILE = KeychainEntitledTestApp_ios/Info.plist; - INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_CODE_SIGN_FLAGS = "--deep"; - PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.KeychainEntitledTestApp-ios"; - PRODUCT_NAME = KeychainEntitledTestApp; - VALIDATE_PRODUCT = NO; - }; - name = Debug; - }; - 6CF4A0F61E4549F300ECD7B5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist"; - COPY_PHASE_STRIP = NO; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - INFOPLIST_FILE = KeychainEntitledTestApp_ios/Info.plist; - INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_CODE_SIGN_FLAGS = "--deep"; - PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.KeychainEntitledTestApp-ios"; - PRODUCT_NAME = KeychainEntitledTestApp; - VALIDATE_PRODUCT = NO; - }; - name = Release; - }; 7913B20D0D172B3900601FE9 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -42920,6 +42843,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = DCC1849220EEEC4400F3B26C /* security_framework.xcconfig */; buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; @@ -42951,6 +42875,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = DCC1849220EEEC4400F3B26C /* security_framework.xcconfig */; buildSettings = { + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; @@ -43123,10 +43048,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -43174,10 +43096,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -43201,7 +43120,6 @@ buildSettings = { APPLY_RULES_IN_COPY_FILES = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_STATIC_ANALYZER_MODE = shallow; @@ -43210,7 +43128,7 @@ CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -43219,6 +43137,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -43232,7 +43151,6 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; EXCLUDED_INSTALLSRC_SUBDIRECTORY_PATTERNS = "$(SRCROOT)/sslViewer/ecc-secp256r1-client.pfx"; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -43240,7 +43158,7 @@ "$(inherited)", ); GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; @@ -43262,9 +43180,10 @@ HEADERMAP_INCLUDES_FRAMEWORK_ENTRIES_FOR_ALL_PRODUCT_TYPES = NO; INSTALL_DAEMON_AGENT_DIR = "$(SYSTEM_LIBRARY_DIR)/LaunchDaemons"; "INSTALL_DAEMON_AGENT_DIR[sdk=macosx*]" = "$(SYSTEM_LIBRARY_DIR)/LaunchAgents"; - LLVM_LTO = YES_THIN; + LLVM_LTO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; + RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx.internal; SECURITY_FRAMEWORK_RESOURCES_DIR = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/"; "SECURITY_FRAMEWORK_RESOURCES_DIR[sdk=macosx*]" = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; @@ -43273,7 +43192,7 @@ SERVICETYPE_USER_OR_SYSTEM = System; "SERVICETYPE_USER_OR_SYSTEM[sdk=macosx*]" = User; STRIP_INSTALLED_PRODUCT = NO; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchos macosx appletvos appletvsimulator watchsimulator"; + SUPPORTED_PLATFORMS = "bridgeos iphoneos iphonesimulator macosx appletvos appletvsimulator watchos watchsimulator"; SUPPORTS_TEXT_BASED_API = YES; Sim_Name = ""; "Sim_Name[sdk=embeddedsimulator*][arch=*]" = _sim; @@ -43288,7 +43207,6 @@ buildSettings = { APPLY_RULES_IN_COPY_FILES = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_STATIC_ANALYZER_MODE = shallow; @@ -43297,7 +43215,7 @@ CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -43306,6 +43224,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -43318,7 +43237,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; EXCLUDED_INSTALLSRC_SUBDIRECTORY_PATTERNS = "$(SRCROOT)/sslViewer/ecc-secp256r1-client.pfx"; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = s; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -43326,7 +43244,7 @@ "$(inherited)", ); GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; @@ -43350,6 +43268,7 @@ "INSTALL_DAEMON_AGENT_DIR[sdk=macosx*]" = "$(SYSTEM_LIBRARY_DIR)/LaunchAgents"; LLVM_LTO = YES; OTHER_LDFLAGS = ""; + RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx.internal; SECURITY_FRAMEWORK_RESOURCES_DIR = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/"; "SECURITY_FRAMEWORK_RESOURCES_DIR[sdk=macosx*]" = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; @@ -43357,7 +43276,7 @@ "SECURITY_FRAMEWORK_XPCSERVICES_DIR[sdk=macosx*]" = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/XPCServices"; SERVICETYPE_USER_OR_SYSTEM = System; "SERVICETYPE_USER_OR_SYSTEM[sdk=macosx*]" = User; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchos macosx appletvos appletvsimulator watchsimulator"; + SUPPORTED_PLATFORMS = "bridgeos iphoneos iphonesimulator macosx appletvos appletvsimulator watchos watchsimulator"; SUPPORTS_TEXT_BASED_API = YES; SWIFT_COMPILATION_MODE = wholemodule; Sim_Name = ""; @@ -43372,9 +43291,7 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_SUSPICIOUS_MOVES = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREPROCESSOR_DEFINITIONS = ( COM_APPLE_SECURITY_SANE_INCLUDES, "$(inherited)", @@ -43390,9 +43307,7 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_SUSPICIOUS_MOVES = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREPROCESSOR_DEFINITIONS = ( COM_APPLE_SECURITY_SANE_INCLUDES, "$(inherited)", @@ -43411,7 +43326,6 @@ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; AXLE_ENABLE_DEBUG_INFO = YES; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_ASSIGN_ENUM = YES; @@ -43426,7 +43340,6 @@ CODE_SIGN_ENTITLEMENTS = "$(TARGET_NAME)/entitlements.plist"; "CODE_SIGN_IDENTITY[sdk=embedded*]" = "-"; COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(TARGET_NAME)/$(TARGET_NAME)-Prefix.pch"; @@ -43435,7 +43348,7 @@ "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_ABOUT_MISSING_NEWLINE = NO; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -43460,7 +43373,6 @@ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; AXLE_ENABLE_DEBUG_INFO = NO; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_ASSIGN_ENUM = YES; @@ -43476,10 +43388,9 @@ "CODE_SIGN_IDENTITY[sdk=embedded*]" = "-"; COMBINE_HIDPI_IMAGES = YES; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(TARGET_NAME)/$(TARGET_NAME)-Prefix.pch"; - GCC_WARN_ABOUT_MISSING_NEWLINE = NO; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -43714,7 +43625,6 @@ "$(SDKROOT)/usr/local/lib/security_libDER", ); OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", "$(OTHER_LDFLAGS_PROTOBUF)", "$(OTHER_LDFLAGS_MOBILEGESTALT)", @@ -43734,6 +43644,7 @@ "$(OTHER_LDFLAGS_FOR_SECURITYD)", "-framework", Security, + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustedPeersHelperUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -43765,7 +43676,6 @@ "$(SDKROOT)/usr/local/lib/security_libDER", ); OTHER_LDFLAGS = ( - "$(OTHER_LDFLAGS_AKS_LIBRARY)", "$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)", "$(OTHER_LDFLAGS_PROTOBUF)", "$(OTHER_LDFLAGS_MOBILEGESTALT)", @@ -43785,6 +43695,7 @@ "$(OTHER_LDFLAGS_FOR_SECURITYD)", "-framework", Security, + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustedPeersHelperUnitTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -43796,7 +43707,6 @@ }; BEF88C391EAFFC4000357577 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BE8351D41EC0EEDD00ACD5FD /* framework_requiring_modern_objc_runtime.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -43831,7 +43741,6 @@ }; BEF88C3A1EAFFC4000357577 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BE8351D41EC0EEDD00ACD5FD /* framework_requiring_modern_objc_runtime.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -43910,6 +43819,7 @@ OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = trustd; STRIP_STYLE = debugging; @@ -43935,6 +43845,7 @@ OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = trustd; STRIP_STYLE = debugging; @@ -44065,6 +43976,7 @@ OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests; PRODUCT_NAME = TrustTests; @@ -44105,6 +44017,7 @@ OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests; PRODUCT_NAME = TrustTests; @@ -44119,7 +44032,6 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -44134,6 +44046,8 @@ LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", + /Developer/Library/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -44151,7 +44065,6 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -44165,6 +44078,8 @@ LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", + /Developer/Library/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; @@ -44181,7 +44096,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -44190,24 +44104,21 @@ CODE_SIGN_ENTITLEMENTS = tests/TrustTests/TestRunners/trusttests_entitlements.plist; CODE_SIGN_STYLE = Automatic; DEBUG_INFORMATION_FORMAT = dwarf; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - "$(PLATFORM_DIR)/Developer/AppleInternal/Library/Frameworks", - ); + ENABLE_TESTING_SEARCH_PATHS = YES; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INFOPLIST_FILE = tests/TrustTests/TestRunners/Info.plist; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; LD_RUNPATH_SEARCH_PATHS = ( /Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Debug; }; @@ -44217,7 +44128,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -44226,23 +44136,20 @@ CODE_SIGN_ENTITLEMENTS = tests/TrustTests/TestRunners/trusttests_entitlements.plist; CODE_SIGN_STYLE = Automatic; ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - "$(PLATFORM_DIR)/Developer/AppleInternal/Library/Frameworks", - ); + ENABLE_TESTING_SEARCH_PATHS = YES; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INFOPLIST_FILE = tests/TrustTests/TestRunners/Info.plist; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; LD_RUNPATH_SEARCH_PATHS = ( /Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks, - /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework/Frameworks, + /AppleInternal/Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; + TEST_BUILD_STYLE = _APPLEINTERNAL; VALIDATE_PRODUCT = YES; }; name = Release; @@ -44277,6 +44184,7 @@ "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_OCMOCK)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests; PRODUCT_NAME = TrustTests; @@ -44313,6 +44221,7 @@ "$(OTHER_LDFLAGS_MOBILEASSET)", "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_OCMOCK)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests; PRODUCT_NAME = TrustTests; @@ -44794,7 +44703,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -44810,7 +44718,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -44832,7 +44739,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -44849,7 +44755,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -45360,7 +45265,7 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -45373,7 +45278,7 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -45481,7 +45386,6 @@ }; DC0BC9CD1D8B824700070CB0 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_ENUM_CONVERSION = NO; @@ -45506,7 +45410,6 @@ }; DC0BC9CE1D8B824700070CB0 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_ENUM_CONVERSION = NO; @@ -45542,7 +45445,6 @@ SKIP_INSTALL = YES; WARNING_CFLAGS = ( "$(inherited)", - "-Wno-int-to-void-pointer-cast", "-Wno-sign-compare", ); }; @@ -45561,7 +45463,6 @@ SKIP_INSTALL = YES; WARNING_CFLAGS = ( "$(inherited)", - "-Wno-int-to-void-pointer-cast", "-Wno-sign-compare", ); }; @@ -45572,10 +45473,8 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_SUSPICIOUS_MOVES = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREPROCESSOR_DEFINITIONS = ( COM_APPLE_SECURITY_SANE_INCLUDES, "$(inherited)", @@ -45591,10 +45490,8 @@ baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_DOCUMENTATION_COMMENTS = NO; CLANG_WARN_SUSPICIOUS_MOVES = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; GCC_PREPROCESSOR_DEFINITIONS = ( COM_APPLE_SECURITY_SANE_INCLUDES, "$(inherited)", @@ -45679,7 +45576,6 @@ }; DC0BCC341D8C684F00070CB0 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -45698,21 +45594,17 @@ GCC_WARN_SHADOW = NO; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; STRIP_INSTALLED_PRODUCT = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-unused-function", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; DC0BCC351D8C684F00070CB0 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -45731,15 +45623,12 @@ GCC_WARN_SHADOW = NO; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; STRIP_INSTALLED_PRODUCT = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-unused-function", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -45760,14 +45649,13 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; WARNING_CFLAGS = ( "$(inherited)", "-Wno-sign-compare", - "-Wno-unused-function", ); }; name = Debug; @@ -45789,14 +45677,13 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; WARNING_CFLAGS = ( "$(inherited)", "-Wno-sign-compare", - "-Wno-unused-function", ); }; name = Release; @@ -46820,7 +46707,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++98"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -46856,7 +46742,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++98"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -46921,10 +46806,7 @@ INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = YES; ORDER_FILE = securityd/src/securityd.order; - OTHER_CPLUSPLUSFLAGS = ( - "$(OTHER_CFLAGS)", - "-Wno-deprecated-register", - ); + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; PRODUCT_NAME = securityd; SUPPORTED_PLATFORMS = macosx; }; @@ -46965,10 +46847,7 @@ INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = NO; ORDER_FILE = securityd/src/securityd.order; - OTHER_CPLUSPLUSFLAGS = ( - "$(OTHER_CFLAGS)", - "-Wno-deprecated-register", - ); + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; PRODUCT_NAME = securityd; SUPPORTED_PLATFORMS = macosx; }; @@ -46979,7 +46858,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -46996,7 +46874,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47020,7 +46897,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47038,7 +46914,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47068,6 +46943,8 @@ "$(OTHER_LDFLAGS_IMCORE)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = secdtests; STRIP_STYLE = debugging; @@ -47092,6 +46969,8 @@ "$(OTHER_LDFLAGS_IMCORE)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_NAME = secdtests; STRIP_STYLE = debugging; @@ -47460,7 +47339,6 @@ }; DC8834061D8A218F00CE0ACA /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_MODULES = NO; @@ -47481,7 +47359,6 @@ }; DC8834071D8A218F00CE0ACA /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_MODULES = NO; @@ -47505,7 +47382,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47522,7 +47398,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47546,7 +47421,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47564,7 +47438,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47581,7 +47454,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47598,7 +47470,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47622,7 +47493,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47640,7 +47510,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47657,7 +47526,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47674,7 +47542,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47698,7 +47565,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47716,7 +47582,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47733,7 +47598,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47750,7 +47614,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47774,7 +47637,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47792,7 +47654,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47809,7 +47670,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47826,7 +47686,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47850,7 +47709,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47868,7 +47726,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47885,7 +47742,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47902,7 +47758,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -47926,7 +47781,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47944,7 +47798,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -47961,7 +47814,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -47978,7 +47830,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -48002,7 +47853,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -48020,7 +47870,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -48037,7 +47886,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -48054,7 +47902,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -48078,7 +47925,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -48096,7 +47942,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -48113,7 +47958,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -48130,7 +47974,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -48154,7 +47997,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -48172,7 +48014,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -48401,10 +48242,7 @@ GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-switch", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -48418,10 +48256,7 @@ GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-switch", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -48638,7 +48473,7 @@ APPLY_RULES_IN_COPY_FILES = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = NO; - CLANG_WARN_ENUM_CONVERSION = NO; + CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; HEADER_SEARCH_PATHS = ( @@ -48650,10 +48485,7 @@ MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=c++11-narrowing", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -48664,7 +48496,7 @@ APPLY_RULES_IN_COPY_FILES = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = NO; - CLANG_WARN_ENUM_CONVERSION = NO; + CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; HEADER_SEARCH_PATHS = ( @@ -48676,10 +48508,7 @@ MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = NO; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=c++11-narrowing", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -48702,7 +48531,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -48719,7 +48547,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -48743,7 +48570,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -48761,7 +48587,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -48930,7 +48755,6 @@ WARNING_CFLAGS = ( "$(inherited)", "-Wno-sign-compare", - "-Wno-deprecated-register", ); }; name = Debug; @@ -48961,7 +48785,6 @@ WARNING_CFLAGS = ( "$(inherited)", "-Wno-sign-compare", - "-Wno-deprecated-register", ); }; name = Release; @@ -49338,10 +49161,7 @@ "$(OTHER_LDFLAGS_FOR_SECURITYD)", ); PRODUCT_NAME = "$(TARGET_NAME)"; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -49392,10 +49212,7 @@ "$(OTHER_LDFLAGS_FOR_SECURITYD)", ); PRODUCT_NAME = "$(TARGET_NAME)"; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -49429,16 +49246,14 @@ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; INSTALL_PATH = /usr/libexec; MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = trustd; - WARNING_CFLAGS = ( - "-Wextra", - "-Wno-unused-parameter", - "-Wno-missing-field-initializers", - "-Wno-error=deprecated-declarations", + OTHER_LDFLAGS = ( + "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); + PRODUCT_NAME = trustd; }; name = Debug; }; @@ -49473,16 +49288,14 @@ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_FUNCTION = YES; INSTALL_PATH = /usr/libexec; MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = trustd; - WARNING_CFLAGS = ( - "-Wextra", - "-Wno-unused-parameter", - "-Wno-missing-field-initializers", - "-Wno-error=deprecated-declarations", + OTHER_LDFLAGS = ( + "$(OTHER_LDFLAGS_IMG4DECODE)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); + PRODUCT_NAME = trustd; }; name = Release; }; @@ -49509,7 +49322,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNINITIALIZED_AUTOS = YES; INFOPLIST_FILE = OSX/authd/Info.plist; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; MTL_ENABLE_DEBUG_INFO = YES; @@ -49542,7 +49355,7 @@ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; - GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNINITIALIZED_AUTOS = YES; INFOPLIST_FILE = OSX/authd/Info.plist; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; MTL_ENABLE_DEBUG_INFO = NO; @@ -49732,17 +49545,25 @@ buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; EXECUTABLE_PREFIX = lib; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -49751,17 +49572,24 @@ buildSettings = { CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; EXECUTABLE_PREFIX = lib; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -49770,7 +49598,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -49787,7 +49614,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -49811,7 +49637,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -49829,7 +49654,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -50011,7 +49835,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -50021,7 +49844,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -50044,7 +49866,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -50056,7 +49877,6 @@ COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -50098,7 +49918,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -50139,7 +49958,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -50180,7 +49998,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -50214,7 +50031,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -50248,7 +50064,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -50291,7 +50106,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = NO; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -50372,6 +50186,7 @@ "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -50423,6 +50238,7 @@ "$(OTHER_LDFLAGS_IMG4DECODE)", "$(OTHER_LDFLAGS_MOBILE_KEYBAG)", "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MSUDATAACCESSOR)", ); PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -50489,13 +50305,11 @@ E7B01BF0166594AB000485F1 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -50541,13 +50355,11 @@ E7B01BF1166594AB000485F1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PRECOMPILE_PREFIX_HEADER = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -50604,7 +50416,6 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50623,7 +50434,6 @@ DYLIB_CURRENT_VERSION = 1; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_VERSION = A; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -50649,7 +50459,7 @@ TAPI_VERIFY_MODE = ErrorsOnly; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; - WARNING_CFLAGS = "-Wno-objc-designated-initializers"; + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -50657,7 +50467,6 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50677,7 +50486,6 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_VERSION = A; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -50706,7 +50514,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50721,7 +50528,6 @@ COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -50783,7 +50589,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50800,7 +50605,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -50859,7 +50663,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50875,7 +50678,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -50916,7 +50718,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50933,7 +50734,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -50969,7 +50769,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -50986,7 +50785,6 @@ DEBUGGING_SYMBOLS = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -51010,7 +50808,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51028,7 +50825,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -51045,7 +50841,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -51054,7 +50849,6 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; @@ -51071,7 +50865,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; @@ -51080,7 +50873,6 @@ DYLIB_CURRENT_VERSION = 1; ENABLE_NS_ASSERTIONS = NO; EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO; INSTALL_PATH = "$(SECURITY_FUZZER_BASE_DIR)/lib"; @@ -51096,7 +50888,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51111,7 +50902,6 @@ COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; @@ -51166,6 +50956,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainCircle.KeychainCircleTests; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_TEXT_BASED_API = YES; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Debug; }; @@ -51174,7 +50965,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51191,7 +50981,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -51243,6 +51032,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainCircle.KeychainCircleTests; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_TEXT_BASED_API = YES; + TEST_BUILD_STYLE = _APPLEINTERNAL; }; name = Release; }; @@ -51252,12 +51042,10 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "keychain/ckksctl/ckksctl-Entitlements.plist"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; @@ -51272,14 +51060,12 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "keychain/ckksctl/ckksctl-Entitlements.plist"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/sbin; MTL_ENABLE_DEBUG_INFO = NO; @@ -51291,7 +51077,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51306,7 +51091,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -51346,7 +51130,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51362,7 +51145,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -51398,7 +51180,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51414,7 +51195,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -51455,7 +51235,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51472,7 +51251,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -51507,7 +51285,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51523,7 +51300,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -51563,7 +51339,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -51580,7 +51355,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -51618,7 +51392,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; @@ -51666,6 +51439,7 @@ "-framework", Security, "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.Security.secdmockaks; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -51680,7 +51454,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; @@ -51728,6 +51501,7 @@ "-framework", Security, "$(OTHER_LDFLAGS_FOR_SECURITYD)", + "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)", ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.Security.secdmockaks; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -51770,10 +51544,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = YES; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -51812,10 +51583,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = YES; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -51839,7 +51607,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -51875,7 +51642,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -51953,10 +51719,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = YES; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Debug; }; @@ -51992,10 +51755,7 @@ REEXPORTED_LIBRARY_NAMES = ""; STRIP_STYLE = debugging; USE_HEADERMAP = YES; - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=modules-ambiguous-internal-linkage", - ); + WARNING_CFLAGS = "$(inherited)"; }; name = Release; }; @@ -52003,7 +51763,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52018,7 +51777,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -52058,7 +51816,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52074,7 +51831,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -52123,7 +51879,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52139,7 +51894,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -52179,7 +51933,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52196,7 +51949,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -52242,12 +51994,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = "$(SECURITY_FUZZER_BASE_DIR)"; @@ -52261,13 +52011,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = "$(SECURITY_FUZZER_BASE_DIR)"; MTL_ENABLE_DEBUG_INFO = NO; @@ -52315,7 +52063,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52331,7 +52078,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -52372,7 +52118,6 @@ baseConfigurationReference = DCE4E82B1D7A54D300AFB96E /* ios_on_macos.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; @@ -52389,7 +52134,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -52425,14 +52169,12 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = "security-sysdiagnose/security-sysdiagnose.entitlements.plist"; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/libexec; @@ -52446,7 +52188,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; @@ -52455,7 +52196,6 @@ CODE_SIGN_ENTITLEMENTS = "security-sysdiagnose/security-sysdiagnose.entitlements.plist"; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /usr/libexec; MTL_ENABLE_DEBUG_INFO = NO; @@ -52468,7 +52208,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++98"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -52504,7 +52243,6 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++98"; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -52540,12 +52278,10 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; DEBUG_INFORMATION_FORMAT = dwarf; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; @@ -52561,13 +52297,11 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; MTL_ENABLE_DEBUG_INFO = NO; @@ -52651,29 +52385,29 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0C9AEEB420783FBB00BF6237 /* Build configuration list for PBXNativeTarget "SignInAnalyticsTests_osx" */ = { + 0CA378E323876DD100090B7E /* Build configuration list for PBXAggregateTarget "reset_account" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0C9AEEB520783FBB00BF6237 /* Debug */, - 0C9AEEB620783FBB00BF6237 /* Release */, + 0CA378E423876DD100090B7E /* Debug */, + 0CA378E523876DD100090B7E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0CA378E323876DD100090B7E /* Build configuration list for PBXAggregateTarget "reset_account" */ = { + 0CCC227623F357EE00E1FCD0 /* Build configuration list for PBXNativeTarget "OctagonTrustTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0CA378E423876DD100090B7E /* Debug */, - 0CA378E523876DD100090B7E /* Release */, + 0CCC227723F357EE00E1FCD0 /* Debug */, + 0CCC227823F357EE00E1FCD0 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0CF4064D2072E3E3003D6A7F /* Build configuration list for PBXNativeTarget "SignInAnalyticsTests_ios" */ = { + 0CD743AB23C3EC8000FA0EC5 /* Build configuration list for PBXNativeTarget "OctagonTrust" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0CF4064E2072E3E3003D6A7F /* Debug */, - 0CF4064F2072E3E3003D6A7F /* Release */, + 0CD743AC23C3EC8000FA0EC5 /* Debug */, + 0CD743AD23C3EC8000FA0EC5 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -52714,6 +52448,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 3E88360E24F068EF00E9F4D6 /* Build configuration list for PBXNativeTarget "secseccodeapitest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E88360F24F068EF00E9F4D6 /* Debug */, + 3E88361024F068EF00E9F4D6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 438169381B4EDCBD00C54D58 /* Build configuration list for PBXNativeTarget "SOSCCAuthPlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -52750,7 +52493,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4727FBC31F9918590003AE36 /* Build configuration list for PBXNativeTarget "secdxctests_ios" */ = { + 4727FBC31F9918590003AE36 /* Build configuration list for PBXNativeTarget "secdxctests" */ = { isa = XCConfigurationList; buildConfigurations = ( 4727FBBC1F9918590003AE36 /* Debug */, @@ -52786,15 +52529,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 478D42991FD72A8100CAB645 /* Build configuration list for PBXNativeTarget "secdxctests_mac" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 478D429A1FD72A8100CAB645 /* Debug */, - 478D429B1FD72A8100CAB645 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 47C2F1872059CB690062DE30 /* Build configuration list for PBXNativeTarget "KeychainResources" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -52939,6 +52673,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 6C2045EE2424BA7F00F9461D /* Build configuration list for PBXNativeTarget "KeychainStasher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6C2045EF2424BA7F00F9461D /* Debug */, + 6C2045F02424BA7F00F9461D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 6C39237621F13E4D00D018AD /* Build configuration list for PBXNativeTarget "SecDbBackupTests" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -52957,20 +52700,20 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6C98085E1E788AEB00E70590 /* Build configuration list for PBXNativeTarget "CKKSCloudKitTests_mac" */ = { + 6C7BE2E423C3DD64003BB2CA /* Build configuration list for PBXNativeTarget "securitytool_bridge" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6C98085F1E788AEB00E70590 /* Debug */, - 6C9808601E788AEB00E70590 /* Release */, + 6C7BE2E523C3DD64003BB2CA /* Debug */, + 6C7BE2E623C3DD64003BB2CA /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6C98089A1E788AFD00E70590 /* Build configuration list for PBXNativeTarget "CKKSCloudKitTests_ios" */ = { + 6C963288242A279B00C53CE2 /* Build configuration list for PBXNativeTarget "stashtester" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6C98089B1E788AFD00E70590 /* Debug */, - 6C98089C1E788AFD00E70590 /* Release */, + 6C963285242A279B00C53CE2 /* Debug */, + 6C963286242A279B00C53CE2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -53002,7 +52745,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6CF4A0CC1E45488B00ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp_mac" */ = { + 6CF4A0CC1E45488B00ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 6CF4A0C51E45488B00ECD7B5 /* Debug */, @@ -53011,15 +52754,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6CF4A0F41E4549F300ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp_ios" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6CF4A0F51E4549F300ECD7B5 /* Debug */, - 6CF4A0F61E4549F300ECD7B5 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 790851C90CA985C10083CC4D /* Build configuration list for PBXNativeTarget "securityd_ios" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Security.xcodeproj/xcshareddata/xcschemes/CKKSTests.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/CKKSTests.xcscheme index 577b55c3..ac6fde2d 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/CKKSTests.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/CKKSTests.xcscheme @@ -1,6 +1,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/SecureTransportTests_macos.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/SecureTransportTests_macos.xcscheme new file mode 100644 index 00000000..f2cae49c --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/SecureTransportTests_macos.xcscheme @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_ios.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_ios.xcscheme index 51730e53..a9b4f2f9 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_ios.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/TrustTests_ios.xcscheme @@ -1,6 +1,6 @@ - - - - - - - - - - - - diff --git a/Security.xcodeproj/xcshareddata/xcschemes/ios - Debug.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/ios - Debug.xcscheme index d5c67142..fcc30b51 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/ios - Debug.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/ios - Debug.xcscheme @@ -1,6 +1,6 @@ - - - - @@ -71,16 +62,6 @@ ReferencedContainer = "container:Security.xcodeproj"> - - - - - - @@ -278,10 +255,6 @@ argument = "si_26_sectrust_copyproperties" isEnabled = "NO"> - - @@ -382,10 +355,6 @@ argument = "si_66_smime" isEnabled = "NO"> - - @@ -410,10 +379,6 @@ argument = "si_73_secpasswordgenerate" isEnabled = "NO"> - - @@ -430,14 +395,6 @@ argument = "si_83_seccertificate_sighashalg" isEnabled = "NO"> - - - - diff --git a/Security.xcodeproj/xcshareddata/xcschemes/ios - Release.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/ios - Release.xcscheme index 06344ef9..9eb5f631 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/ios - Release.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/ios - Release.xcscheme @@ -1,6 +1,6 @@ - - - - @@ -208,10 +199,6 @@ argument = "si_22_sectrust_iap" isEnabled = "NO"> - - @@ -228,10 +215,6 @@ argument = "si_26_sectrust_copyproperties" isEnabled = "NO"> - - @@ -320,10 +303,6 @@ argument = "si_66_smime" isEnabled = "NO"> - - @@ -348,10 +327,6 @@ argument = "si_73_secpasswordgenerate" isEnabled = "NO"> - - @@ -372,18 +347,10 @@ argument = "si_83_seccertificate_sighashalg" isEnabled = "NO"> - - - - diff --git a/Security.xcodeproj/xcshareddata/xcschemes/ios - secdtests.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/ios - secdtests.xcscheme index cf5cb28f..15062dd9 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/ios - secdtests.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/ios - secdtests.xcscheme @@ -1,6 +1,6 @@ - - - - diff --git a/Security.xcodeproj/xcshareddata/xcschemes/osx - World.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/osx - World.xcscheme index cb70464e..09e298ee 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/osx - World.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/osx - World.xcscheme @@ -1,6 +1,6 @@ - - - - @@ -67,16 +58,6 @@ ReferencedContainer = "container:Security.xcodeproj"> - - - - + + + + - - @@ -291,10 +278,6 @@ argument = "si_22_sectrust_iap" isEnabled = "NO"> - - @@ -315,10 +298,6 @@ argument = "si_26_sectrust_copyproperties" isEnabled = "NO"> - - @@ -387,10 +366,6 @@ argument = "si_68_secmatchissuer" isEnabled = "NO"> - - @@ -399,22 +374,10 @@ argument = "si_71_mobile_store_policy" isEnabled = "NO"> - - - - - - diff --git a/Security.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme index 034c0652..d10c4ae2 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme @@ -1,6 +1,6 @@ - - - - @@ -212,6 +203,10 @@ argument = "secd_61_account_leave_not_in_kansas_anymore" isEnabled = "NO"> + + @@ -224,6 +219,10 @@ argument = "secd_71_engine_save" isEnabled = "NO"> + + @@ -293,6 +292,18 @@ isEnabled = "NO"> + + + + + + - - - - diff --git a/Security.xcodeproj/xcshareddata/xcschemes/secdmockaks.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/secdmockaks.xcscheme index ac9beb1a..69540ff7 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/secdmockaks.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/secdmockaks.xcscheme @@ -1,6 +1,6 @@ 123456.test.group 123456.test.group2 com.apple.bluetooth + com.apple.token com.apple.developer.associated-domains webcredentials:localhost + com.apple.private.security.storage.Keychains + diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_Root.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_Root.cer new file mode 100644 index 0000000000000000000000000000000000000000..70cd9625440fefffe30eb983088bd6faecdaae86 GIT binary patch literal 652 zcmXqLV(KtxV&YrC%*4pV#L2MmqmS#nwaecdaItY{wRxPgWnpGAXzVcLHsEAq4rO5z zW(o~96gCh9aX5ImoD*|0)AEb*G7}Aj3^z*#r3I-)C7F5oFoj$^T#f|=IjIVs zdC7W)vIf#1h1@(M!KulmMVTd)3a)wSnR%(HMVWc&hB5|HAZcbE;o#CFXGaBB?@)!1 z)Z!9_p#1z2137VCBLf3-0}CS~6LSN@C~;n65Z4UK9ZXIw0|p2?I1HH>*;ut3Ss0X< zlNeYMPE4G3rh;YB1pSap$@>jXdv+IitvLHSmix`WDbj6I_n**0KdfeU@ zyy1_R-XW2jvB#wJXqZ))Dpz_7 WZL=@mn!2{!Ik-HoWTJAv literal 0 HcmV?d00001 diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_anyEKU_ca.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_anyEKU_ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..f32740db124008c14c6bdfb08edf582caa99db64 GIT binary patch literal 683 zcmXqLVp?v{#H71`nTe5!Nrd4eyZ?_egW0?%mWsYTcss2ibmAHVE;bIWHji_*EX+&> zjU9&E2Apinp)72|OrgPs!UlpM4hIjHb7D?rT7FSpW}=~xfdEL5orlx8v>>&pBr`7` zrjUz=%dwy!Csn~SFImq})<7Dhkef#&I5oMnD6^ze!8I>EGcPr@C^IkJP{u$CB+bkt z99){@?5N=C9jXwLT3n(Kl%HQ>AScdiWME)!U}0ozVrXm>1>_ncaSa;V>F88x14)Qe zg&gyMo`5+N>~4cd17S9Ha1b&vLc@}ok)7FzfyLgF@%uRg;Z^geoormlGnrxGxjV_n zczm{$tyMjln8#dSu8>@J{SOPv1(QJMDK{)%Y<-{3qGbMU#)5B)o$5d2_%1FnC^Fy& z+AJ%~$oQXy)qojD8SsGw_(1}|C}UzVkOlGiSj1RFW(IrBn%??WFu}g@b$R2IS02;% zt~ZbeNh`BR7>G59NLS3*y*Y3>qsQ%i!5jW~=^YZe84IyMm4(BAjg2K#R+RxcMKEVD z7^E^81nzRuz0rPpu6>dJti{LA+V8f$b#=p#ALsKnTe5!NjOezdM1Ol!lbshU3=%{EZ#n2Tb%(H8;4e#$2nUTW+sEi zc0+ChPB!LH7B*p~&|pJh13?gngNMsGF()%EzbG#=(NM@h03^uH!|7aFkXlrdnU@b! z$i>6uSWu9Ys^FQItY;`|APrK;%_9<=np|3xSyHLsnwOrLmzr9XnU`)TZ6FDfX66xc z%md1Jhbn}m7MCalmnJzo8pw(B8W|Xv8(0__n^+i{L;<;mNL+))20FS_#6Sq*Qts4> z#9W~N^pf*)4I&MM+1SBB$HWK?LuN*HW+w)gyE=Q1g%Q_r7i6)t~xU-QG-=Z3~}H*8akt?JO#aFN}6@?tmd;>JFM#%=>1 zprx|HjEw(Tm<$*U_&_{<5Dyqr>; z3lisJ5n~alI^^DWCFS6O*v(Cs_lJt?Hq_Z>VIU8ZR%Vef5Ni;b8SFJ{dh1)k1pCI< z<&9Hbc}(BC9yyUPdomcfF)1?iaG9<*T^(<2m9V+#PH~c4!R@K15*>~$Ir)rDP(l6^ pKTye|cE|5px88n8*1M*c`OdHU!rS@6+EvNP=hn0b*gihb0|04{#z_DG literal 0 HcmV?d00001 diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_ca.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..c22366949875d13d330fb4724cf2a26553a8cd1c GIT binary patch literal 664 zcmXqLVwz&m#3a3dnTe5!Nrd4eyZ?_egW0?%mWsYTcss2ibmD3QE;bIWHji_*EX+&> zjU9&E2Apinp)72|OrgPs!UlpM4hIjHb7D?rT7FSpW}=~xfdEL5orlx8v>>&pBr`7` zrjUz=%dwy!Csn~SFImq})<7Dhkef#&I5oMnD6^ze!8I>EGcPr@C^IkJP{u$CB+bkt z99){@?5N=C9jXwLT3n(Kl%HQ>AScdiWME)!U}0ozVqj_<1>_ncaSa;V=;%}_0||&z z1^x07?gTsAAksjXjU60TQB~mDxzbHcN?8`LUO3`J74i;Xf zvu3s0c-ZO|Kb$7SQ|Z{b_2hQ>zlH@%J7&wr^Dz8ydi7G%;%I43;m*a$28jmzK#OIC z85#exuo^G}DFZ%`06$0o7-LK<2C^VNABz}^hCo)avUUTthHK{i@<`cHG$2N=kM zq?K7D48$5lq$_6Z-W<4`(c|{M;0=Gg^bU#Kj75%r=5z*w6efefDJ#X#-{f8>YuKIk|x(CUrm47=Cv+WcPjv1Lc+8F literal 0 HcmV?d00001 diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_leaf.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_noEKU_leaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..b5763b8a41660a36e613d374a7313ed0afe55f87 GIT binary patch literal 667 zcmXqLVw!Hy#ALUCnTe5!Ntn4%^`}Y933r<<-4%x)*<>$bnPtGm#-Y{ban6>7naQBB z&5+xGlZ`o)g-w_#G}utsKoG>?;Nfyk%*jm4FUreIG!!xr012}5a5|S3q!yKA=Hlw-#NP`q|^N0keCYKgvmQ*UZ=A~!mrKT2T=A|1-8AyPnnRx{L z@)caYLlr_&i%S%OOOu=(4dldmjSLLT4J?d|P0WofqJUgOB(6bY105YIVju)@D0gZ_ zVlL2oddc~@29XBBZ0z8WV`78`Au}U8vl9bLyhy=|?3H;pR>*k&3hkLa^?J*S{{Q6T1x~XnbgzJZMiyQk48oLd6 zfR@S%Gcx{XVKQJa-~;jaK|EkYu{QuM2l7=}ctG)|&Bn;e%FfJaAO;c?WZ^g9Z9;LY zEJ&P>MT|w{{xqXzmE||0)ejl^+)u*Kp${Lt^J@ATW nQpjH^cQ7z9RFvVP&>7~dmrdAPm{qgwCg>XapPIRa=XWsx`60j~ literal 0 HcmV?d00001 diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_smime_ca.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_smime_ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..7342c2f71a73ae681995fce5e29c6b03057dc295 GIT binary patch literal 689 zcmXqLVp?m^#ALjHnTe5!Nrd4eyZ?_egW0?%mWsYTcss2ibmBS#E;bIWHji_*EX+&> zjU9&E2Apinp)72|OrgPs!UlpM4hIjHb7D?rT7FSpW}=~xfdEL5orlx8v>>&pBr`7` zrjUz=%dwy!Csn~SFImq})<7Dhkef#&I5oMnD6^ze!8I>EGcPr@C^IkJP{u$CB+bkt z99){@?5N=C9jXwLT3n(Kl%HQ>AScdiWME)!U}0ozVq{_%1>_ncaSa+f>F89bPndx| z@%8j|MK~4ga)U?%VK#PfATlvRLz9`2o!NhPhVFB zSMN}TkksN5h2YX8XGa4$ab6<>19JllBV!Xw6VoUl*AR(o(AYpnw~81DfxN=Z!<|}@ zm<#lwUUGh}L8O5&8#_4gm>8j<$jr#j?8LxQW%W7UD7Wd{rWEIAGkX(bRA)a9zcsDb z!b&(ds)GGj%B0dop2_(pTZ_bJXGlxk6Z;gV{p82Iz~#piJbpRf6kWf#vCp8f+kgjX zsjM&~<9`+=0|o;=5RV_k1I8751JH6HUzLRi6ouMsjI6Be%!~$NAVEPEegobn6t~KP z#Q9jnSVZz3^A>sYHR)s>346h_a_X9!&u7aU$b+PnStJa^8btDE%vhBD<$(h84Q6NC zs0Cl&g};4(oJ^QK7z|vQ6!g}*-YR8Z$9i&;#mCot-y2@8`t~Sie!s9!ccy=B%=Ya} oiVQ7@jq@DW|B2&U!Xi^}AVBzpe#+egj2zp$pFPYiEB|%|0GUq16#xJL literal 0 HcmV?d00001 diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_ssl_ca.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_ssl_ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..58ed701e9151d023f8e6f6d6131765a58e82e760 GIT binary patch literal 695 zcmXqLV%lub#ALaEnTe5!Nrd4eyZ?_egW0?%mWsYTcss2ibmCeAE;bIWHji_*EX+&> zjU9&E2Apinp)72|OrgPs!UlpM4hIjHb7D?rT7FSpW}=~xfdEL5orlx8v>>&pBr`7` zrjUz=%dwy!Csn~SFImq})<7Dhkef#&I5oMnD6^ze!8I>EGcPr@C^IkJP{u$CB+bkt z99){@?5N=C9jXwLT3n(Kl%HQ>AScdiWME)!U}0ozVq|C%1>_ncaSa;#>F88t14W2a zrGit7%2JCI97{_w5Do^r-yqUJn2jAAluV4!FlAX<2%;)pQbX|IUxnnq^f= z635n;DClmgZ5RBtXqH9fqdm+!)mwC41Rq+zJ}3Iq|EadKE=3kyj9gb;5?89>c%fZz zafLyd0YA_Mvcimv|5;cKn1Pf5A4q^7Bmj&$CKdx(5TB1lj78+LLU{1{I+6Jkg}d|S z>k28i>P)_3APsHn6Z0v;BrQf+xvny{PEH|Byuwr=z5?6RTdsliqK|b zWMyS%W<*XM%oz*@sZ0j);>K@hdY*ON{`X|zqAGToHfFB9{TDXRS9P54cXIuKg9e!? zvCbbIA1w&jt#aJAjGf7lVWVZq&h{gZTCYy$m%H=#y|MU8ol8e|GnC0>Uc6Ojx-cio UE2DtxmnPTM(##XfmVbH%0B01?pa1{> literal 0 HcmV?d00001 diff --git a/SecurityTests/ssl-policy-certs/subCA_EKU_ssl_leaf.cer b/SecurityTests/ssl-policy-certs/subCA_EKU_ssl_leaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..8531402bc61cc395fd53fe5290a07c3f2f04fc3b GIT binary patch literal 678 zcmXqLVp?R-#N@GnnTe5!Nrd4O*Y3#cu614}`aJ8aK1#oNwsork7aNCGo5wj@7G@@c z#(qO?15P&PP!={}rqEzRVFN)Bhl7X9IWZ?QEx#x)Gtp4UKma7j&co?kT98^)l9`te zQ^>``k&iDoJ!Euvp0b{;%3J)yeUG)9Ki}S_^m-$s zN!jAYK7+Ga872 z1O-|64S1VS+$swa=VK9L5xIZ!*RH*spO0~s2OSd?i>utVa*48mJV;uZMZ!R=LFBVS zc<}l9RsmtM2PcaEOl+g1DAgdFaEwSK1l zm}RD;Vo&rj_PI=o3|%VgoE-kNoLMXD#`J8iwnbLcl|TW3{dWRG9lh;W>ns8Q<9fqb literal 0 HcmV?d00001 diff --git a/SecurityTool/macOS/authz.c b/SecurityTool/macOS/authz.c index 00208dd4..de5579f7 100644 --- a/SecurityTool/macOS/authz.c +++ b/SecurityTool/macOS/authz.c @@ -678,10 +678,11 @@ authorize(int argc, char * const *argv) retval = (status ? -1 : 0); bail: - if (rights) + if (rights) { free(rights); - - return retval; + } + + return retval; } diff --git a/SecurityTool/macOS/createFVMaster.c b/SecurityTool/macOS/createFVMaster.c index 36671610..9965ce02 100644 --- a/SecurityTool/macOS/createFVMaster.c +++ b/SecurityTool/macOS/createFVMaster.c @@ -101,8 +101,11 @@ OSStatus makeMasterPassword(const char *fvmkcName, const char *masterPasswordPas OSStatus status = SecKeychainCreate(fvmkcName, (UInt32) strlen(masterPasswordPassword), masterPasswordPassword, false, initialAccess, keychainRef); if (status!=noErr) { - if (status==errSecDuplicateKeychain || status==CSSMERR_DL_DATASTORE_ALREADY_EXISTS) + if (status==errSecDuplicateKeychain || status==CSSMERR_DL_DATASTORE_ALREADY_EXISTS) { sec_error("The keychain file %s already exists", fvmkcName); + } else if (status != errSecSuccess) { + sec_error("Could not create keychain file %s: %s", fvmkcName, sec_errstr(status)); + } return status; } @@ -199,18 +202,24 @@ OSStatus createPair(CFStringRef hostName,CFStringRef userName,SecKeychainRef key // cleanup xit: - if (certRef) + if (certRef) { CFRelease(certRef); - if (certData.Data) + } + if (certData.Data) { free(certData.Data); - if (hostStr) - free(hostStr); - if (userStr) - free(userStr); - if (tpHand) - CSSM_ModuleDetach(tpHand); - if (clHand) - CSSM_ModuleDetach(clHand); + } + if (hostStr) { + free(hostStr); + } + if (userStr) { + free(userStr); + } + if (tpHand) { + CSSM_ModuleDetach(tpHand); + } + if (clHand) { + CSSM_ModuleDetach(clHand); + } if (pubKey) { CSSM_FreeKey(cspHand, @@ -707,8 +716,9 @@ keychain_createMFV(int argc, char * const *argv) return SHOW_USAGE_MESSAGE; keychainName = (argc == 1)?*argv:_masterKeychainName; - if (!keychainName || *keychainName == '\0') + if (!keychainName || *keychainName == '\0') { return -1; + } if (!password && !do_prompt) { diff --git a/SecurityTool/macOS/db_commands.cpp b/SecurityTool/macOS/db_commands.cpp index 381501f9..89655f69 100644 --- a/SecurityTool/macOS/db_commands.cpp +++ b/SecurityTool/macOS/db_commands.cpp @@ -43,7 +43,7 @@ do_db_create(const CSSM_GUID guid, const char *dbname, Boolean do_openparams, Bo try { CSSM_APPLEDL_OPEN_PARAMETERS openParameters = { sizeof(CSSM_APPLEDL_OPEN_PARAMETERS), - (do_version_0_params ? 0 : CSSM_APPLEDL_OPEN_PARAMETERS_VERSION) }; + (do_version_0_params ? 0u : CSSM_APPLEDL_OPEN_PARAMETERS_VERSION) }; Cssm cssm; Module module(guid, cssm); DL dl(module); diff --git a/SecurityTool/macOS/identity_find.m b/SecurityTool/macOS/identity_find.m index 1b3e562f..932361ed 100644 --- a/SecurityTool/macOS/identity_find.m +++ b/SecurityTool/macOS/identity_find.m @@ -391,7 +391,7 @@ do_identity_search_with_policy(CFTypeRef keychainOrArray, safe_CFRelease(&idStr); safe_CFRelease(&policy); - safe_CFRelease(policySearch); + safe_CFRelease(&policySearch); } static void diff --git a/SecurityTool/macOS/key_create.c b/SecurityTool/macOS/key_create.c index e14f64d2..8e5688f7 100644 --- a/SecurityTool/macOS/key_create.c +++ b/SecurityTool/macOS/key_create.c @@ -163,11 +163,13 @@ parse_time(const char *time, CFAbsoluteTime *ptime) sec_error("%s is not a valid date", time); result = 1; } - if (formatter) + if (formatter) { CFRelease(formatter); - if (time_string) + } + if (time_string) { CFRelease(time_string); - return result; + } + return result; } int diff --git a/SecurityTool/macOS/keychain_add.c b/SecurityTool/macOS/keychain_add.c index 506ea3a0..cd5dc33e 100644 --- a/SecurityTool/macOS/keychain_add.c +++ b/SecurityTool/macOS/keychain_add.c @@ -764,14 +764,17 @@ keychain_add_generic_password(int argc, char * const *argv) update_item); cleanup: - if (mustFreePasswordData) + if (mustFreePasswordData) { free(passwordData); - if (trusted_list) - CFRelease(trusted_list); - if (access) - CFRelease(access); + } + if (trusted_list) { + CFRelease(trusted_list); + } + if (access) { + CFRelease(access); + } - return result; + return result; } int @@ -976,12 +979,15 @@ keychain_add_internet_password(int argc, char * const *argv) update_item); cleanup: - if (mustFreePasswordData) + if (mustFreePasswordData) { free(passwordData); - if (trusted_list) - CFRelease(trusted_list); - if (access) - CFRelease(access); + } + if (trusted_list) { + CFRelease(trusted_list); + } + if (access) { + CFRelease(access); + } return result; } diff --git a/SecurityTool/macOS/keychain_import.c b/SecurityTool/macOS/keychain_import.c index d27b211b..61e1401d 100644 --- a/SecurityTool/macOS/keychain_import.c +++ b/SecurityTool/macOS/keychain_import.c @@ -416,12 +416,14 @@ keychain_import(int argc, char * const *argv) if(kcName) { kcRef = keychain_open(kcName); if(kcRef == NULL) { - return 1; + result = 1; + goto cleanup; } } else { OSStatus status = SecKeychainCopyDefault(&kcRef); if (status != noErr || kcRef == NULL) { - return 1; + result = 1; + goto cleanup; } } if(readFileSizet(inFile, &inFileData, &inFileLen)) { diff --git a/SecurityTool/macOS/keychain_lock.c b/SecurityTool/macOS/keychain_lock.c index 20a8d549..3cb1670d 100644 --- a/SecurityTool/macOS/keychain_lock.c +++ b/SecurityTool/macOS/keychain_lock.c @@ -39,10 +39,11 @@ static int do_lock_all(void) { OSStatus result = SecKeychainLockAll(); - if (result) + if (result) { sec_perror("SecKeychainLockAll", result); + } - return result; + return result; } static int diff --git a/SecurityTool/macOS/keychain_utilities.c b/SecurityTool/macOS/keychain_utilities.c index bee380fc..ff8dd7eb 100644 --- a/SecurityTool/macOS/keychain_utilities.c +++ b/SecurityTool/macOS/keychain_utilities.c @@ -507,8 +507,9 @@ print_keychain_item_attributes(FILE *stream, SecKeychainItemRef item, Boolean sh fputs("version: ", stream); result = print_keychain_version(stream, keychain); fputc('\n', stream); - if (result) + if (result) { goto loser; + } /* First find out the item class. */ status = SecKeychainItemCopyAttributesAndData(item, NULL, &itemClass, NULL, NULL, NULL); @@ -903,7 +904,7 @@ fromHex(const char *hexDigits, CSSM_DATA *data) CFDataRef CF_RETURNS_RETAINED cfFromHex(CFStringRef hex) { // behavior is undefined if you pass in a non-hex string. Don't do that. - char* chex; + char* chex = NULL; size_t len; GetCStringFromCFString(hex, &chex, &len); @@ -916,6 +917,7 @@ cfFromHex(CFStringRef hex) { CFDataIncreaseLength(bin, bytes); if(!bin || (size_t) CFDataGetLength(bin) != bytes) { + free(chex); CFReleaseNull(bin); return NULL; } @@ -925,6 +927,7 @@ cfFromHex(CFStringRef hex) { data[i] = (uint8)(hexValue(chex[2*i]) << 4 | hexValue(chex[2*i+1])); } + free(chex); return bin; } diff --git a/SecurityTool/macOS/readline.c b/SecurityTool/macOS/readline.c index a6ef891a..3976cc6a 100644 --- a/SecurityTool/macOS/readline.c +++ b/SecurityTool/macOS/readline.c @@ -140,10 +140,12 @@ read_file(const char *name, CSSM_DATA *outData) return result; loser: - if (fd != -1) + if (fd != -1) { close(fd); - if (buffer) - free(buffer); + } + if (buffer) { + free(buffer); + } return result; } diff --git a/SecurityTool/macOS/requirement.c b/SecurityTool/macOS/requirement.c index 0215b80e..abb7fec7 100644 --- a/SecurityTool/macOS/requirement.c +++ b/SecurityTool/macOS/requirement.c @@ -62,6 +62,7 @@ int requirement_evaluate(int argc, char * const *argv) fprintf(stderr, "parsing requirement failed (%d): %s\n", status, errorStr); free(errorStr); + CFReleaseSafe(errorDesc); err = 1; } @@ -82,7 +83,7 @@ int requirement_evaluate(int argc, char * const *argv) } CFArrayAppendValue(certs, cert); - CFRelease(cert); + CFReleaseSafe(cert); } // Evaluate! diff --git a/SecurityTool/macOS/trusted_cert_ssl.m b/SecurityTool/macOS/trusted_cert_ssl.m index 24ee1bf8..18effdf6 100644 --- a/SecurityTool/macOS/trusted_cert_ssl.m +++ b/SecurityTool/macOS/trusted_cert_ssl.m @@ -109,14 +109,16 @@ - (id)initWithURLString:(const char *)urlstr verbose:(int)level { - _url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%s", urlstr]]; - _udp = NO; - _finished = NO; - _verbose = level; - _error = nil; - _trust = NULL; - _queue = dispatch_get_main_queue(); - _connection = [self createConnection]; + if ((self = [super init])) { + _url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%s", urlstr]]; + _udp = NO; + _finished = NO; + _verbose = level; + _error = nil; + _trust = NULL; + _queue = dispatch_get_main_queue(); + _connection = [self createConnection]; + } return self; } diff --git a/SecurityTool/sharedTool/KeychainCheck.m b/SecurityTool/sharedTool/KeychainCheck.m index 724082bd..1eb76c7d 100644 --- a/SecurityTool/sharedTool/KeychainCheck.m +++ b/SecurityTool/sharedTool/KeychainCheck.m @@ -137,15 +137,9 @@ int verify_backup_integrity(int argc, char * const *argv) { } NSLog(@"Running backup integrity validation in %@ mode", lightweight ? @"lightweight" : @"default"); - dispatch_semaphore_t sema = dispatch_semaphore_create(0); SecItemVerifyBackupIntegrity(lightweight, ^(NSDictionary* results, NSError *error) { NSLog(@"%@", results); - dispatch_semaphore_signal(sema); }); - if (dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 30))) { - NSLog(@"Timed out waiting for backup integrity validation"); - } - return 0; } diff --git a/SecurityTool/sharedTool/SecurityCommands.h b/SecurityTool/sharedTool/SecurityCommands.h index 1792878a..85477d7d 100644 --- a/SecurityTool/sharedTool/SecurityCommands.h +++ b/SecurityTool/sharedTool/SecurityCommands.h @@ -41,9 +41,11 @@ SECURITY_COMMAND("item", keychain_item, "SAC object for deleting item added by default\n", "Manipulate keychain items.") +#if !TARGET_OS_BRIDGE SECURITY_COMMAND("policy-dryrun", policy_dryrun, "", "Try to evaluate policy old/new.") +#endif SECURITY_COMMAND("keychain-item-digest", keychain_item_digest, "itemClass keychainAccessGroup\n" @@ -223,3 +225,24 @@ SECURITY_COMMAND("show-ct-exceptions", show_ct_exceptions, " -c Output certificate exceptions (as SPKI hash).\n" " Default is both domains and certs.\n", "Display exceptions for Certificate Transparency enforcement in json.") + +SECURITY_COMMAND("add-ca-revocation-checking", add_ca_revocation_checking, + "[options]\n" + " -c cert Cert for which revocation checking should be enabled.\n" + " Specify a CA cert to enable checking for all its issued certs.\n" + " Can be specified multiple times.\n" + " -p plist plist containing entries to enable explicit revocation checking.\n" + " Resets existing entries, if present.\n" + " Overrides -c\n" + " For detailed specification, see SecTrustSettingsPriv.h.\n" + " -r which Resets cert entries for \"cert\" or \"all\".\n" + " Overrides -c and -p\n", + "Specify additional CA certs for which revocation checking is enabled") + +SECURITY_COMMAND("show-ca-revocation-checking", show_ca_revocation_checking, + "[options]\n" + " -a Output all combined CA revocation checking additions.\n" + " -i identifier Output CA revocation additions for specified identifier.\n" + " Default is the additions for this tool. Overridden by -a.\n" + " -c Output CA revocation additions (as certificate SPKI hash).\n", + "Display CA revocation checking additions in json.") diff --git a/SecurityTool/sharedTool/add_internet_password.c b/SecurityTool/sharedTool/add_internet_password.c index 1a8f54d8..7599c9c5 100644 --- a/SecurityTool/sharedTool/add_internet_password.c +++ b/SecurityTool/sharedTool/add_internet_password.c @@ -93,14 +93,16 @@ do_addinternetpassword(const char *keychainName, const char *serverName, /* @@@ For performance reasons we could choose to make the dictionaries CFRetain callback a no op and let the dictionary deal with the releasing. */ - for (; ix-- > 0;) + for (; ix-- > 0;) { CFRelease(values[ix]); + } result = SecItemAdd(attributes, NULL); - if (attributes) + if (attributes) { CFRelease(attributes); - + } + if (result) { sec_perror("SecItemAdd", result); diff --git a/SecurityTool/sharedTool/builtin_commands.h b/SecurityTool/sharedTool/builtin_commands.h index 8e57592a..79783228 100644 --- a/SecurityTool/sharedTool/builtin_commands.h +++ b/SecurityTool/sharedTool/builtin_commands.h @@ -23,6 +23,7 @@ #include "SecurityTool/sharedTool/security_tool_commands.h" +#include SECURITY_COMMAND("help", help, "[command ...]", @@ -40,6 +41,7 @@ SECURITY_COMMAND("whoami", command_whoami, "", "Ask securityd who you are.") +#if !TARGET_OS_BRIDGE SECURITY_COMMAND("sos-stats", command_sos_stats, "", "SOS for performance numbers.") @@ -60,6 +62,7 @@ SECURITY_COMMAND("watchdog", command_watchdog, " check-period \n" " graceful-exit-time \n", "Show current watchdog parameters or set an individual parameter") +#endif SECURITY_COMMAND("keychain-check", command_keychain_check, "", diff --git a/SecurityTool/sharedTool/ca_revocation_additions.m b/SecurityTool/sharedTool/ca_revocation_additions.m new file mode 100644 index 00000000..b725ac49 --- /dev/null +++ b/SecurityTool/sharedTool/ca_revocation_additions.m @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2020 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@ + * + * ca_revocation_additions.m + */ + +#import +#include +#include +#include +#include + +#include "SecurityCommands.h" + +NSString* secToolAppID = @"com.apple.security"; + +static int addCertFile(const char *fileName, NSMutableArray *array) { + SecCertificateRef certRef = NULL; + NSData *data = NULL; + unsigned char *buf = NULL; + size_t numBytes; + int rtn = 0; + + if (readFileSizet(fileName, &buf, &numBytes)) { + rtn = -1; + goto errOut; + } + + data = [NSData dataWithBytes:buf length:numBytes]; + certRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)data); + if (!certRef) { + certRef = SecCertificateCreateWithPEM(NULL, (__bridge CFDataRef)data); + if (!certRef) { + rtn = -1; + goto errOut; + } + } + + [array addObject:(__bridge id)certRef]; + +errOut: + /* Cleanup */ + free(buf); + CFReleaseNull(certRef); + return rtn; +} + +static int returnCFError(CFErrorRef CF_CONSUMED error) { + CFStringRef errorString = CFErrorCopyDescription(error); + CFStringPerformWithCString(errorString, ^(const char *utf8Str) { + fprintf(stderr, "Failed to copy CA revocation additions: %s\n", utf8Str); + }); + CFIndex errCode = CFErrorGetCode(error); + CFReleaseNull(error); + return (int)errCode; +} + +static int resetRevocationAdditions(bool resetCerts) { + bool result = false; + CFErrorRef error = NULL; + if (resetCerts) { + NSDictionary *resetCertsDict = @{ (__bridge NSString*)kSecCARevocationAdditionsKey: @[] }; + result = SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)resetCertsDict, &error); + } + if (!result) { + return returnCFError(error); + } + return 0; +} + +static int addRevocationAdditions(CFStringRef key, NSArray *newAdditions) { + CFErrorRef error = NULL; + NSDictionary *currentAdditions = CFBridgingRelease(SecTrustStoreCopyCARevocationAdditions((__bridge CFStringRef)secToolAppID, &error)); + if (!currentAdditions && error) { + return returnCFError(error); + } + + NSMutableArray *additionsForKey = nil; + if (currentAdditions && currentAdditions[(__bridge NSString*)key]) { + additionsForKey = [currentAdditions[(__bridge NSString*)key] mutableCopy]; + [additionsForKey addObjectsFromArray:newAdditions]; + } else { + additionsForKey = [newAdditions copy]; + } + + NSDictionary *newAdditionsDict = @{ (__bridge NSString*)key: additionsForKey }; + bool result = SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)newAdditionsDict, &error); + if (!result) { + return returnCFError(error); + } + + return 0; +} + +int add_ca_revocation_checking(int argc, char * const *argv) { + int arg; + + bool resetCerts = false; + + NSMutableArray *certs = [NSMutableArray array]; + NSDictionary *plist = nil; + + /* parse args */ + if (argc == 1) { + return SHOW_USAGE_MESSAGE; + } + + while ((arg = getopt(argc, argv, "c:r:p:")) != -1) { + switch(arg) { + case 'c': + if (addCertFile(optarg, certs)) { + fprintf(stderr, "Failed to read cert file\n"); + return 1; + } + break; + case 'r': + if (!strcmp(optarg, "all")) { + resetCerts = true; + } else if (!strcmp(optarg, "cert")) { + resetCerts = true; + } else { + return SHOW_USAGE_MESSAGE; + } + break; + case 'p': + plist = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]]; + break; + case '?': + default: + return SHOW_USAGE_MESSAGE; + } + } + + /* handle reset operation */ + if (resetCerts) { + return resetRevocationAdditions(resetCerts); + } + + /* set plist */ + if (plist) { + CFErrorRef error = NULL; + bool result = SecTrustStoreSetCARevocationAdditions(NULL, (__bridge CFDictionaryRef)plist, &error); + if (!result) { + return returnCFError(error); + } else { + return 0; + } + } + + /* add certs */ + int status = 0; + if ([certs count]) { + NSMutableArray*valuesForCAsKey = [NSMutableArray arrayWithCapacity:[certs count]]; + [certs enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + SecCertificateRef cert = (__bridge SecCertificateRef)obj; + NSData* hash = CFBridgingRelease(SecCertificateCopySubjectPublicKeyInfoSHA256Digest(cert)); + NSDictionary *value = @{ (__bridge NSString*)kSecCARevocationHashAlgorithmKey:@"sha256", + (__bridge NSString*)kSecCARevocationSPKIHashKey:hash }; + [valuesForCAsKey addObject:value]; + }]; + status = addRevocationAdditions(kSecCARevocationAdditionsKey, valuesForCAsKey); + } + if (status != 0) { + fprintf(stderr, "failed to add cert revocation additions\n"); + return status; + } + + return 0; +} + +static int printRevocationAdditions(CFStringRef key, NSDictionary *allAdditions) { + if (!allAdditions || !allAdditions[(__bridge NSString*)key] || + [allAdditions[(__bridge NSString*)key] count] == 0) { + CFStringPerformWithCString(key, ^(const char *utf8Str) { + fprintf(stdout, "No revocation additions for %s\n", utf8Str); + }); + return 0; + } + + NSArray *additionsForKey = allAdditions[(__bridge NSString*)key]; + NSMutableString *additionsString = [NSMutableString stringWithFormat:@"\t%@ : [",key]; + [additionsForKey enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[NSString class]]) { + if (idx == 0) { + [additionsString appendFormat:@"\"%@\"",obj]; + } else { + [additionsString appendFormat:@", \"%@\"", obj]; + } + } else if ([obj isKindOfClass:[NSDictionary class]]) { + if (idx == 0) { + [additionsString appendString:@"\n\t "]; + } else { + [additionsString appendString:@"\t "]; + } + [additionsString appendFormat:@"\"%@:", obj[(__bridge NSString*)kSecCARevocationHashAlgorithmKey]]; + NSString *hashHex = CFBridgingRelease(CFDataCopyHexString((__bridge CFDataRef)obj[(__bridge NSString*)kSecCARevocationSPKIHashKey])); + [additionsString appendString:hashHex]; + if ([additionsForKey count] == idx + 1) { // last entry + [additionsString appendString:@"\"\n"]; + } else { + [additionsString appendString:@"\",\n"]; + } + } + }]; + [additionsString appendString:@"]\n"]; + CFStringPerformWithCString((__bridge CFStringRef)additionsString, ^(const char *utf8Str) { + fprintf(stdout, "\n%s\n", utf8Str); + }); + + return 0; +} + +int show_ca_revocation_checking(int argc, char * const *argv) { + int arg; + bool allAdditions = false; + NSString *identifier = nil; + bool certAdditions = false; + + /* parse args */ + while ((arg = getopt(argc, argv, "ai:c")) != -1) { + switch(arg) { + case 'a': + allAdditions = true; + break; + case 'i': + identifier = [NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]; + break; + case 'c': + certAdditions = true; + break; + case '?': + default: + return SHOW_USAGE_MESSAGE; + } + } + + if (allAdditions) { + identifier = nil; + fprintf(stdout, "Showing revocation additions for all apps\n"); + } else if (!identifier) { + identifier = secToolAppID; + } + + if (identifier) { + CFStringPerformWithCString((__bridge CFStringRef)identifier, ^(const char *utf8Str) { + fprintf(stdout, "Showing revocation additions for %s\n", utf8Str); + }); + } + + CFErrorRef error = NULL; + NSDictionary *results = CFBridgingRelease(SecTrustStoreCopyCARevocationAdditions((__bridge CFStringRef)identifier, &error)); + + /* Copy failed, return error */ + if (!results && error) { + return returnCFError(error); + } + + /* print cert revocation additions */ + int status = 0; + if (certAdditions) { + status = printRevocationAdditions(kSecCARevocationAdditionsKey, results); + } + if (status != 0) { + fprintf(stderr, "failed to print revocation additions\n"); + return status; + } + + + return 0; +} diff --git a/SecurityTool/sharedTool/iOS/entitlements.plist b/SecurityTool/sharedTool/iOS/entitlements.plist index ecb877f8..8cdb7c53 100644 --- a/SecurityTool/sharedTool/iOS/entitlements.plist +++ b/SecurityTool/sharedTool/iOS/entitlements.plist @@ -17,6 +17,8 @@ com.apple.security com.apple.private.keychain.keychaincontrol + com.apple.private.keychain.inet_expansion_fields + com.apple.developer.icloud-services CloudKit diff --git a/SecurityTool/sharedTool/macOS/entitlements.plist b/SecurityTool/sharedTool/macOS/entitlements.plist index dc75012f..461763d5 100644 --- a/SecurityTool/sharedTool/macOS/entitlements.plist +++ b/SecurityTool/sharedTool/macOS/entitlements.plist @@ -12,6 +12,8 @@ com.apple.private.keychain.keychaincontrol + com.apple.private.keychain.inet_expansion_fields + com.apple.private.syncbubble-keychain com.apple.private.system-keychain diff --git a/SecurityTool/sharedTool/policy_dryrun.m b/SecurityTool/sharedTool/policy_dryrun.m index dc1668ec..ff46b5a8 100644 --- a/SecurityTool/sharedTool/policy_dryrun.m +++ b/SecurityTool/sharedTool/policy_dryrun.m @@ -158,11 +158,11 @@ static void reportStats(unsigned expected_mismatches, unsigned real_mismatches, int policy_dryrun(int argc, char * const *argv) { @autoreleasepool { NSError* error = nil; - // From Swift.policy, policy v5 + // From Swift.policy, policy v7 - TPPolicyDocument *tpd = [TPPolicyDocument policyDocWithHash:@"SHA256:O/ECQlWhvNlLmlDNh2+nal/yekUC87bXpV3k+6kznSo=" + TPPolicyDocument *tpd = [TPPolicyDocument policyDocWithHash:@"SHA256:dL8Qujqzprhp6FdH5GzNMtPlnZtLWMwfiiF7aykr8WU=" data:[[NSData alloc] initWithBase64EncodedString: - @"CAUSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSDAoEaVBvZBIEZnVsbBILCgNNYWMSBGZ1bGwSDAoEaU1hYxIEZnVsbBINCgdBcHBsZVRWEgJ0dhIOCgVXYXRjaBIFd2F0Y2gSFwoOQXVkaW9BY2Nlc3NvcnkSBWF1ZGlvGhsKDEFwcGxpY2F0aW9ucxIEZnVsbBIFd2F0Y2gaHwoQU2VjdXJlT2JqZWN0U3luYxIEZnVsbBIFd2F0Y2gaHAoNRGV2aWNlUGFpcmluZxIEZnVsbBIFd2F0Y2gaGgoLQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoGhUKBkhlYWx0aBIEZnVsbBIFd2F0Y2gaLQoTTGltaXRlZFBlZXJzQWxsb3dlZBIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxokChVQcm90ZWN0ZWRDbG91ZFN0b3JhZ2USBGZ1bGwSBXdhdGNoGhcKCEFwcGxlUGF5EgRmdWxsEgV3YXRjaBoZCgpBdXRvVW5sb2NrEgRmdWxsEgV3YXRjaBoWCgdNYW5hdGVlEgRmdWxsEgV3YXRjaBoYCglQYXNzd29yZHMSBGZ1bGwSBXdhdGNoGhUKBkVuZ3JhbRIEZnVsbBIFd2F0Y2gaHgoEV2lGaRIEZnVsbBIFd2F0Y2gSAnR2EgVhdWRpbxoTCgRIb21lEgRmdWxsEgV3YXRjaCIbCgVhdWRpbxIEZnVsbBIFd2F0Y2gSBWF1ZGlvIhMKBGZ1bGwSBGZ1bGwSBXdhdGNoIhUKAnR2EgRmdWxsEgV3YXRjaBICdHYiFAoFd2F0Y2gSBGZ1bGwSBXdhdGNoMiIKFgAEIhICBHZ3aHQKCl5BcHBsZVBheSQSCEFwcGxlUGF5MiYKGAAEIhQCBHZ3aHQKDF5BdXRvVW5sb2NrJBIKQXV0b1VubG9jazIeChQABCIQAgR2d2h0CgheRW5ncmFtJBIGRW5ncmFtMh4KFAAEIhACBHZ3aHQKCF5IZWFsdGgkEgZIZWFsdGgyGgoSAAQiDgIEdndodAoGXkhvbWUkEgRIb21lMiAKFQAEIhECBHZ3aHQKCV5NYW5hdGVlJBIHTWFuYXRlZTI4CiEABCIdAgR2d2h0ChVeTGltaXRlZFBlZXJzQWxsb3dlZCQSE0xpbWl0ZWRQZWVyc0FsbG93ZWQyXQpQAAISHgAEIhoCBHZ3aHQKEl5Db250aW51aXR5VW5sb2NrJBIVAAQiEQIEdndodAoJXkhvbWVLaXQkEhUABCIRAgR2d2h0CgleQXBwbGVUViQSCU5vdFN5bmNlZDIrChsABCIXAgRhZ3JwCg9eWzAtOUEtWl17MTB9XC4SDEFwcGxpY2F0aW9uczLFAQqwAQACEjQAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAobAAQiFwIEYWdycAoPXmNvbS5hcHBsZS5zYmQkEj0AAQoTAAQiDwIFY2xhc3MKBl5rZXlzJAokAAQiIAIEYWdycAoYXmNvbS5hcHBsZS5zZWN1cml0eS5zb3MkEhkABCIVAgR2d2h0Cg1eQmFja3VwQmFnVjAkEhwABCIYAgR2d2h0ChBeaUNsb3VkSWRlbnRpdHkkEhBTZWN1cmVPYmplY3RTeW5jMmMKWwACEhIABCIOAgR2d2h0CgZeV2lGaSQSQwABChMABCIPAgVjbGFzcwoGXmdlbnAkChMABCIPAgRhZ3JwCgdeYXBwbGUkChUABCIRAgRzdmNlCgleQWlyUG9ydCQSBFdpRmkynQMKgwMAAhIYAAQiFAIEdndodAoMXlBDUy1CYWNrdXAkEhoABCIWAgR2d2h0Cg5eUENTLUNsb3VkS2l0JBIYAAQiFAIEdndodAoMXlBDUy1Fc2Nyb3ckEhUABCIRAgR2d2h0CgleUENTLUZERSQSGgAEIhYCBHZ3aHQKDl5QQ1MtRmVsZHNwYXIkEhoABCIWAgR2d2h0Cg5eUENTLU1haWxEcm9wJBIaAAQiFgIEdndodAoOXlBDUy1NYWlsZHJvcCQSGwAEIhcCBHZ3aHQKD15QQ1MtTWFzdGVyS2V5JBIXAAQiEwIEdndodAoLXlBDUy1Ob3RlcyQSGAAEIhQCBHZ3aHQKDF5QQ1MtUGhvdG9zJBIZAAQiFQIEdndodAoNXlBDUy1TaGFyaW5nJBIeAAQiGgIEdndodAoSXlBDUy1pQ2xvdWRCYWNrdXAkEh0ABCIZAgR2d2h0ChFeUENTLWlDbG91ZERyaXZlJBIaAAQiFgIEdndodAoOXlBDUy1pTWVzc2FnZSQSFVByb3RlY3RlZENsb3VkU3RvcmFnZTI6CisABCInAgRhZ3JwCh9eY29tLmFwcGxlLnNhZmFyaS5jcmVkaXQtY2FyZHMkEgtDcmVkaXRDYXJkczIuCiEABCIdAgRhZ3JwChVeY29tLmFwcGxlLmNmbmV0d29yayQSCVBhc3N3b3JkczJtClwAAhIeAAQiGgIEdndodAoSXkFjY2Vzc29yeVBhaXJpbmckEhoABCIWAgR2d2h0Cg5eTmFub1JlZ2lzdHJ5JBIcAAQiGAIEdndodAoQXldhdGNoTWlncmF0aW9uJBINRGV2aWNlUGFpcmluZzIOCgIABhIIQmFja3N0b3A=" options:0]]; + @"CAcSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSDAoEaVBvZBIEZnVsbBILCgNNYWMSBGZ1bGwSDAoEaU1hYxIEZnVsbBINCgdBcHBsZVRWEgJ0dhIOCgVXYXRjaBIFd2F0Y2gSFwoOQXVkaW9BY2Nlc3NvcnkSBWF1ZGlvGh4KBEhvbWUSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aJAoVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlEgRmdWxsEgV3YXRjaBoYCglQYXNzd29yZHMSBGZ1bGwSBXdhdGNoGh8KEFNlY3VyZU9iamVjdFN5bmMSBGZ1bGwSBXdhdGNoGh4KBFdpRmkSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aGgoLQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoGhcKCEFwcGxlUGF5EgRmdWxsEgV3YXRjaBoVCgZIZWFsdGgSBGZ1bGwSBXdhdGNoGhkKCkF1dG9VbmxvY2sSBGZ1bGwSBXdhdGNoGi0KE0xpbWl0ZWRQZWVyc0FsbG93ZWQSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aHAoNRGV2aWNlUGFpcmluZxIEZnVsbBIFd2F0Y2gaFgoHTWFuYXRlZRIEZnVsbBIFd2F0Y2gaFQoGRW5ncmFtEgRmdWxsEgV3YXRjaBoXCghCYWNrc3RvcBIEZnVsbBIFd2F0Y2gaGwoMQXBwbGljYXRpb25zEgRmdWxsEgV3YXRjaCITCgRmdWxsEgRmdWxsEgV3YXRjaCIVCgJ0dhIEZnVsbBIFd2F0Y2gSAnR2IhQKBXdhdGNoEgRmdWxsEgV3YXRjaCIbCgVhdWRpbxIEZnVsbBIFd2F0Y2gSBWF1ZGlvMiIKFgAEIhICBHZ3aHQKCl5BcHBsZVBheSQSCEFwcGxlUGF5MiYKGAAEIhQCBHZ3aHQKDF5BdXRvVW5sb2NrJBIKQXV0b1VubG9jazIeChQABCIQAgR2d2h0CgheRW5ncmFtJBIGRW5ncmFtMh4KFAAEIhACBHZ3aHQKCF5IZWFsdGgkEgZIZWFsdGgyGgoSAAQiDgIEdndodAoGXkhvbWUkEgRIb21lMiAKFQAEIhECBHZ3aHQKCV5NYW5hdGVlJBIHTWFuYXRlZTI4CiEABCIdAgR2d2h0ChVeTGltaXRlZFBlZXJzQWxsb3dlZCQSE0xpbWl0ZWRQZWVyc0FsbG93ZWQyXQpQAAISHgAEIhoCBHZ3aHQKEl5Db250aW51aXR5VW5sb2NrJBIVAAQiEQIEdndodAoJXkhvbWVLaXQkEhUABCIRAgR2d2h0CgleQXBwbGVUViQSCU5vdFN5bmNlZDIrChsABCIXAgRhZ3JwCg9eWzAtOUEtWl17MTB9XC4SDEFwcGxpY2F0aW9uczLKAQq1AQACEjYAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAodAAQiGQIEYWdycAoRXmNvbVwuYXBwbGVcLnNiZCQSQAABChMABCIPAgVjbGFzcwoGXmtleXMkCicABCIjAgRhZ3JwChteY29tXC5hcHBsZVwuc2VjdXJpdHlcLnNvcyQSGQAEIhUCBHZ3aHQKDV5CYWNrdXBCYWdWMCQSHAAEIhgCBHZ3aHQKEF5pQ2xvdWRJZGVudGl0eSQSEFNlY3VyZU9iamVjdFN5bmMyYwpbAAISEgAEIg4CBHZ3aHQKBl5XaUZpJBJDAAEKEwAEIg8CBWNsYXNzCgZeZ2VucCQKEwAEIg8CBGFncnAKB15hcHBsZSQKFQAEIhECBHN2Y2UKCV5BaXJQb3J0JBIEV2lGaTKdAwqDAwACEhgABCIUAgR2d2h0CgxeUENTLUJhY2t1cCQSGgAEIhYCBHZ3aHQKDl5QQ1MtQ2xvdWRLaXQkEhgABCIUAgR2d2h0CgxeUENTLUVzY3JvdyQSFQAEIhECBHZ3aHQKCV5QQ1MtRkRFJBIaAAQiFgIEdndodAoOXlBDUy1GZWxkc3BhciQSGgAEIhYCBHZ3aHQKDl5QQ1MtTWFpbERyb3AkEhoABCIWAgR2d2h0Cg5eUENTLU1haWxkcm9wJBIbAAQiFwIEdndodAoPXlBDUy1NYXN0ZXJLZXkkEhcABCITAgR2d2h0CgteUENTLU5vdGVzJBIYAAQiFAIEdndodAoMXlBDUy1QaG90b3MkEhkABCIVAgR2d2h0Cg1eUENTLVNoYXJpbmckEh4ABCIaAgR2d2h0ChJeUENTLWlDbG91ZEJhY2t1cCQSHQAEIhkCBHZ3aHQKEV5QQ1MtaUNsb3VkRHJpdmUkEhoABCIWAgR2d2h0Cg5eUENTLWlNZXNzYWdlJBIVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlMj0KLgAEIioCBGFncnAKIl5jb21cLmFwcGxlXC5zYWZhcmlcLmNyZWRpdC1jYXJkcyQSC0NyZWRpdENhcmRzMjAKIwAEIh8CBGFncnAKF15jb21cLmFwcGxlXC5jZm5ldHdvcmskEglQYXNzd29yZHMybQpcAAISHgAEIhoCBHZ3aHQKEl5BY2Nlc3NvcnlQYWlyaW5nJBIaAAQiFgIEdndodAoOXk5hbm9SZWdpc3RyeSQSHAAEIhgCBHZ3aHQKEF5XYXRjaE1pZ3JhdGlvbiQSDURldmljZVBhaXJpbmcyDgoCAAYSCEJhY2tzdG9w" options:0]]; TPPolicy *policy = [tpd policyWithSecrets:@{} decrypter:nil error:&error]; if (error != nil) { NSLog(@"policy error: %@", error); @@ -172,6 +172,15 @@ int policy_dryrun(int argc, char * const *argv) { NSLog(@"policy is nil"); return 1; } + + TPSyncingPolicy* syncingPolicy = [policy syncingPolicyForModel:@"iPhone" + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_UNKNOWN + error:&error]; + if(syncingPolicy == nil || error != nil) { + NSLog(@"syncing policy is nil: %@", error); + return 1; + } + unsigned real_mismatches = 0; unsigned expected_mismatches = 0; NSMutableArray* reportedMismatches = [[NSMutableArray alloc] init]; @@ -219,7 +228,7 @@ int policy_dryrun(int argc, char * const *argv) { NSMutableDictionary* mutA = [a mutableCopy]; mutA[(id)kSecClass] = (id)itemClass; - NSString* newView = [policy mapKeyToView:mutA]; + NSString* newView = [syncingPolicy mapDictionaryToView:mutA]; if (newView != nil) { NSLog(@"new: %@", newView); } diff --git a/SecurityTool/sharedTool/scep.c b/SecurityTool/sharedTool/scep.c index 304c9270..39e2f744 100644 --- a/SecurityTool/sharedTool/scep.c +++ b/SecurityTool/sharedTool/scep.c @@ -441,30 +441,44 @@ extern int command_scep(int argc, char * const *argv) (void) scep_signing_certificate; // Silence analyzer -#if 0 +/* GetCACaps capabilities advertised by SCEP server: - +--------------------+----------------------------------------------+ - | Keyword | Description | - +--------------------+----------------------------------------------+ - | "GetNextCACert" | CA Supports the GetNextCACert message. | - | "POSTPKIOperation" | PKIOPeration messages may be sent via HTTP | - | | POST. | - | "Renewal" | Clients may use current certificate and key | - | | to authenticate an enrollment request for a | - | | new certificate. | - | "SHA-512" | CA Supports the SHA-512 hashing algorithm in | - | | signatures and fingerprints. | - | "SHA-256" | CA Supports the SHA-256 hashing algorithm in | - | | signatures and fingerprints. | - | "SHA-1" | CA Supports the SHA-1 hashing algorithm in | - | | signatures and fingerprints. | - | "DES3" | CA Supports triple-DES for encryption. | - +--------------------+----------------------------------------------+ -#endif + +--------------------+----------------------------------------------+ + | Keyword | Description | + +--------------------+----------------------------------------------+ + | "AES" | CA supports the AES128-CBC encryption | + | | algorithm. | + | | | + | "DES3" | CA supports the triple DES-CBC encryption | + | | algorithm. | + | | | + | "GetNextCACert" | CA supports the GetNextCACert | + | | message. | + | | | + | "POSTPKIOperation" | CA supports PKIOPeration messages sent | + | | via HTTP POST. | + | | | + | "Renewal" | CA supports the Renewal CA operation. | + | | | + | "SHA-1" | CA supports the SHA-1 hashing algorithm. | + | | | + | "SHA-256" | CA supports the SHA-256 hashing algorithm. | + | | | + | "SHA-512" | CA supports the SHA-512 hashing algorithm. | + | | | + | "SCEPStandard" | CA supports all mandatory-to-implement | + | | sections of the SCEP standard. This keyword | + | | implies "AES", | + | | "POSTPKIOperation", and "SHA-256", as well | + | | as the provisions of | + | | Section 2.9. | + +--------------------+----------------------------------------------+ +*/ bool scep_can_use_post = false; - bool scep_use_3des = false; + bool scep_can_use_3des = false; + bool scep_can_use_aes = false; bool scep_can_use_sha1 = false; bool scep_can_use_sha512 = false; bool scep_can_use_sha256 = false; @@ -496,21 +510,14 @@ extern int command_scep(int argc, char * const *argv) CFRange caps_length = CFRangeMake(0, CFArrayGetCount(caps)); scep_can_use_post = CFArrayContainsValue(caps, caps_length, CFSTR("POSTPKIOperation")); - scep_use_3des = CFArrayContainsValue(caps, caps_length, CFSTR("DES3")); + scep_can_use_3des = CFArrayContainsValue(caps, caps_length, CFSTR("DES3")); + scep_can_use_aes = CFArrayContainsValue(caps, caps_length, CFSTR("AES")); scep_can_use_sha1 = CFArrayContainsValue(caps, caps_length, CFSTR("SHA-1")); scep_can_use_sha256 = CFArrayContainsValue(caps, caps_length, CFSTR("SHA-256")); scep_can_use_sha512 = CFArrayContainsValue(caps, caps_length, CFSTR("SHA-512")); - - // We probably inteded these to be the values and not override them below.. - // but for now to quiet the analyzer we reference them here. see scep.c, command_scep assumes 3des and sha1 - (void) scep_use_3des; - (void) scep_can_use_sha1; CFRelease(caps); } - scep_use_3des = true; - scep_can_use_sha1 = true; - csr_parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (scep_key_usage) @@ -520,11 +527,14 @@ extern int command_scep(int argc, char * const *argv) else fprintf(stderr, "No SCEP challenge provided, hope that's ok.\n"); - if (!scep_use_3des) { - CFDictionarySetValue(csr_parameters, kSecCMSBulkEncryptionAlgorithm, kSecCMSEncryptionAlgorithmDESCBC); - fprintf(stderr, "SCEP server does not support 3DES, falling back to DES. You should reconfigure your server.\n"); + // set encryption algorithm for CMS + if (scep_can_use_aes) { + CFDictionarySetValue(csr_parameters, kSecCMSBulkEncryptionAlgorithm, kSecCMSEncryptionAlgorithmAESCBC); + } else if (!scep_can_use_3des) { + fprintf(stderr, "SCEP server does not support 3DES -- using it anyway. You must reconfigure your server.\n"); } + // set hash algorithmn for CMS if (scep_can_use_sha512) { CFDictionarySetValue(csr_parameters, kSecCMSSignHashAlgorithm, kSecCMSHashingAlgorithmSHA512); } else if (scep_can_use_sha256) { @@ -532,7 +542,7 @@ extern int command_scep(int argc, char * const *argv) } else if (scep_can_use_sha1) { CFDictionarySetValue(csr_parameters, kSecCMSSignHashAlgorithm, kSecCMSHashingAlgorithmSHA1); } else { - fprintf(stderr, "SCEP server does not support SHA-1. You must reconfigure your server.\n"); + fprintf(stderr, "SCEP server does not support SHA-1 -- using it anyway. You must reconfigure your server.\n"); } if (scep_subject_alt_name) { diff --git a/SecurityTool/sharedTool/sos.m b/SecurityTool/sharedTool/sos.m index 1fae8a91..0a3d7214 100644 --- a/SecurityTool/sharedTool/sos.m +++ b/SecurityTool/sharedTool/sos.m @@ -184,12 +184,15 @@ command_sos_control(__unused int argc, __unused char * const * argv) bool gbinfo = false; bool gbtriggered = false; bool circleHash = false; + bool triggerRingUpdate = false; + bool iCloudIdentityStatus = false; static struct option long_options[] = { /* These options set a flag. */ {"assertStashAccountKey", no_argument, NULL, 'a'}, {"trigger-backup", optional_argument, NULL, 'B'}, + {"trigger-ring-update", no_argument, NULL, 'R'}, {"trigger-sync", optional_argument, NULL, 's'}, {"circle-hash", optional_argument, NULL, 'H'}, {"ghostbustByMID", optional_argument, NULL, 'M'}, @@ -198,10 +201,11 @@ command_sos_control(__unused int argc, __unused char * const * argv) {"ghostbustByAge", optional_argument, NULL, 'A'}, {"ghostbustInfo", optional_argument, NULL, 'G'}, {"ghostbustTriggered", optional_argument, NULL, 'T'}, + {"icloudIdentityStatus", optional_argument, NULL, 'i'}, {0, 0, 0, 0} }; - while ((ch = getopt_long(argc, argv, "as:AB:GHMSIT", long_options, &option_index)) != -1) { + while ((ch = getopt_long(argc, argv, "as:AB:GHIMRSTi", long_options, &option_index)) != -1) { switch (ch) { case 'a': { assertStashAccountKey = true; @@ -239,6 +243,9 @@ command_sos_control(__unused int argc, __unused char * const * argv) gboptions |= SOSGhostBustByMID; break; } + case 'R': + triggerRingUpdate = true; + break; case 'S': { gboptions |= SOSGhostBustBySerialNumber; break; @@ -254,6 +261,9 @@ command_sos_control(__unused int argc, __unused char * const * argv) case 'H': circleHash = true; break; + case 'i': + iCloudIdentityStatus = true; + break; case '?': default: { @@ -300,7 +310,7 @@ command_sos_control(__unused int argc, __unused char * const * argv) } else if (triggerSync) { [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) { printControlFailureMessage(error); - }] triggerSync:syncingPeers complete:^(bool res, NSError *error) { + }] rpcTriggerSync:syncingPeers complete:^(bool res, NSError *error) { if (res) { printf("starting to sync was successful\n"); } else { @@ -310,11 +320,21 @@ command_sos_control(__unused int argc, __unused char * const * argv) } else if (triggerBackup) { [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) { printControlFailureMessage(error); - }] triggerBackup:backupPeers complete:^(NSError *error) { + }] rpcTriggerBackup:backupPeers complete:^(NSError *error) { if (error == NULL) { printf("trigger backup was successful\n"); } else { - printf("%s", [[NSString stringWithFormat:@"Failed to start sync: %@\n", error] UTF8String]); + printf("%s", [[NSString stringWithFormat:@"Failed to start backup: %@\n", error] UTF8String]); + } + }]; + } else if (triggerRingUpdate) { + [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) { + printControlFailureMessage(error); + }] rpcTriggerRingUpdate:^(NSError *error) { + if (error == NULL) { + printf("trigger ring update was successful\n"); + } else { + printf("%s", [[NSString stringWithFormat:@"Failed to start ring update: %@\n", error] UTF8String]); } }]; @@ -339,6 +359,17 @@ command_sos_control(__unused int argc, __unused char * const * argv) } }]; + } else if (iCloudIdentityStatus) { + [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) { + printControlFailureMessage(error); + }] iCloudIdentityStatus:^(NSData *json, NSError *error) { + if (json) { + printf("iCloudIdentityStatus:\n%s\n", [[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding] UTF8String]); + } else { + printf("%s", [[NSString stringWithFormat:@"failed to get iCloudIdentityStatus: %@\n", error] UTF8String]); + } + }]; + } else { [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) { diff --git a/SecurityTool/sharedTool/sub_commands.h b/SecurityTool/sharedTool/sub_commands.h index 61f5d813..e6d5b1c4 100644 --- a/SecurityTool/sharedTool/sub_commands.h +++ b/SecurityTool/sharedTool/sub_commands.h @@ -26,7 +26,10 @@ // This file can't be once, it gets included multiple times to get definitions and declarations. #include "SecurityTool/sharedTool/SecurityCommands.h" + +#if !TARGET_OS_BRIDGE #include "keychain/SecureObjectSync/Tool/keychain_sync.h" #include "keychain/SecureObjectSync/Tool/keychain_sync_test.h" #include "keychain/SecureObjectSync/Tool/keychain_log.h" #include "keychain/SecureObjectSync/Tool/recovery_key.h" +#endif diff --git a/SecurityTool/sharedTool/trust_update.m b/SecurityTool/sharedTool/trust_update.m index 17323408..8111e2cb 100644 --- a/SecurityTool/sharedTool/trust_update.m +++ b/SecurityTool/sharedTool/trust_update.m @@ -80,6 +80,26 @@ static int check_OTA_sec_experiment_asset(void) { return 0; } +static int check_valid_update(void) { + CFErrorRef error = NULL; + bool result = SecTrustTriggerValidUpdate(&error); + if (!result) { + CFStringRef errorDescription = error ? CFErrorCopyDescription(error) : NULL; + if (errorDescription) { + char *errMsg = CFStringToCString(errorDescription); + fprintf(stdout, "Update failed: %s\n", errMsg ? errMsg : "no error message"); + free(errMsg); + CFRelease(errorDescription); + } else { + fprintf(stdout, "Update failed: no description\n"); + } + CFReleaseNull(error); + } else { + fprintf(stdout, "Updated triggered\n"); + } + return 0; +} + int check_trust_update(int argc, char * const *argv) { int arg; @@ -87,12 +107,14 @@ int check_trust_update(int argc, char * const *argv) { return SHOW_USAGE_MESSAGE; } - while ((arg = getopt(argc, argv, "se")) != -1) { + while ((arg = getopt(argc, argv, "ser")) != -1) { switch(arg) { case 's': return check_OTA_Supplementals_asset(); case 'e': return check_OTA_sec_experiment_asset(); + case 'r': + return check_valid_update(); case '?': default: return SHOW_USAGE_MESSAGE; diff --git a/SharedMocks/NSXPCConnectionMock.m b/SharedMocks/NSXPCConnectionMock.m index f667d23c..89102a49 100644 --- a/SharedMocks/NSXPCConnectionMock.m +++ b/SharedMocks/NSXPCConnectionMock.m @@ -14,8 +14,7 @@ @implementation NSXPCConnectionMock - (instancetype) initWithRealObject:(id)reality { - self = [super init]; - if (self) { + if ((self = [super init])) { _reality = reality; } return self; diff --git a/SharedWebCredentialViewService/SWCViewController.h b/SharedWebCredentialViewService/SWCViewController.h index 3ac3843e..9b047a7d 100755 --- a/SharedWebCredentialViewService/SWCViewController.h +++ b/SharedWebCredentialViewService/SWCViewController.h @@ -6,7 +6,9 @@ // #import +#if !TARGET_OS_TV #import +#endif @interface SWCViewController : SBSUIRemoteAlertItemContentViewController diff --git a/SharedWebCredentialViewService/SWCViewController.m b/SharedWebCredentialViewService/SWCViewController.m index 25e643ca..23bf5312 100755 --- a/SharedWebCredentialViewService/SWCViewController.m +++ b/SharedWebCredentialViewService/SWCViewController.m @@ -109,7 +109,7 @@ const NSString* SWC_SERVER_KEY = @"srvr"; self.backgroundView = [[UIView alloc] init]; self.backgroundView.backgroundColor = [UIColor systemBackgroundColor]; - self.imageView.image = [UIImage symbolImageNamed:@"checkmark"]; + self.imageView.image = [UIImage systemImageNamed:@"checkmark"]; self.imageView.hidden = YES; } diff --git a/SharedWebCredentialViewService/entitlements.plist b/SharedWebCredentialViewService/entitlements.plist index ef81b9b7..7f762505 100755 --- a/SharedWebCredentialViewService/entitlements.plist +++ b/SharedWebCredentialViewService/entitlements.plist @@ -6,5 +6,24 @@ com.apple.private.associated-domains + com.apple.security.iokit-user-client-class + + AGXDevice + AGXDeviceUserClient + AGXSharedUserClient + AGXCommandQueue + IOAccelContext + IOAccelContext2 + IOAccelDevice + IOAccelDevice2 + IOAccelSharedUserClient + IOAccelSharedUserClient2 + IOAccelSubmitter + IOAccelSubmitter2 + IOAVControllerConcreteUserClient + IOMobileFramebufferUserClient + IOSurfaceRootUserClient + RootDomainUserClient + diff --git a/TestPlan.xctestplan b/TestPlan.xctestplan deleted file mode 100644 index 551dd811..00000000 --- a/TestPlan.xctestplan +++ /dev/null @@ -1,18 +0,0 @@ -{ - "configurations" : [ - { - "id" : "E61600EC-4F68-414B-932D-2A0655D233A4", - "name" : "Configuration 1", - "options" : { - - } - } - ], - "defaultOptions" : { - - }, - "testTargets" : [ - - ], - "version" : 1 -} diff --git a/base/SecBase.h b/base/SecBase.h index 104b0315..028df742 100644 --- a/base/SecBase.h +++ b/base/SecBase.h @@ -30,7 +30,7 @@ // Truth table for following declarations: // -// TARGET_OS_OSX TARGET_OS_OSX TARGET_OS_IPHONE TARGET_OS_IPHONE TARGET_OS_IOSMAC +// TARGET_OS_OSX TARGET_OS_OSX TARGET_OS_IPHONE TARGET_OS_IPHONE TARGET_OS_MACCATALYST // SEC_IOS_ON_OSX SEC_IOS_ON_OSX // ================================================================================================================= // SEC_OS_IPHONE 0 1 1 1 1 @@ -46,12 +46,12 @@ #endif // SEC_IOS_ON_OSX #endif // TARGET_OS_OSX -#if TARGET_OS_IOSMAC +#if TARGET_OS_MACCATALYST #define SEC_OS_IPHONE 1 #define SEC_OS_OSX 0 #define SEC_OS_OSX_INCLUDES 0 -#endif // TARGET_OS_IOSMAC +#endif // TARGET_OS_MACCATALYST #ifndef SEC_OS_IPHONE // block above did not fire; set flags to current platform @@ -71,7 +71,7 @@ #define SEC_DEPRECATED_ATTRIBUTE #endif -#define CSSM_DEPRECATED API_DEPRECATED("CSSM is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) +#define CSSM_DEPRECATED API_DEPRECATED("CSSM is not supported", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) __BEGIN_DECLS @@ -139,19 +139,19 @@ typedef struct CF_BRIDGED_TYPE(id) __SecKeychain *SecKeychainRef @typedef SecKeychainItemRef @abstract Contains information about a keychain item. */ -typedef struct CF_BRIDGED_TYPE(id) __SecKeychainItem *SecKeychainItemRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecKeychainItem *SecKeychainItemRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainSearchRef @abstract Contains information about a keychain search. */ -typedef struct CF_BRIDGED_TYPE(id) __SecKeychainSearch *SecKeychainSearchRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecKeychainSearch *SecKeychainSearchRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainAttrType @abstract Represents a keychain attribute type. */ -typedef OSType SecKeychainAttrType API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef OSType SecKeychainAttrType API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @struct SecKeychainAttribute @@ -160,19 +160,19 @@ typedef OSType SecKeychainAttrType API_UNAVAILABLE(ios, watchos, tvos, bridgeos, @field length The length of the buffer pointed to by data. @field data A pointer to the attribute data. */ -struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) SecKeychainAttribute +struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) SecKeychainAttribute { SecKeychainAttrType tag; UInt32 length; void * __nullable data; }; -typedef struct SecKeychainAttribute SecKeychainAttribute API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct SecKeychainAttribute SecKeychainAttribute API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainAttributePtr @abstract Represents a pointer to a keychain attribute structure. */ -typedef SecKeychainAttribute *SecKeychainAttributePtr API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef SecKeychainAttribute *SecKeychainAttributePtr API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainAttributeList @@ -180,30 +180,30 @@ typedef SecKeychainAttribute *SecKeychainAttributePtr API_UNAVAILABLE(ios, watch @field count An unsigned 32-bit integer that represents the number of keychain attributes in the array. @field attr A pointer to the first keychain attribute in the array. */ -struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) SecKeychainAttributeList +struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) SecKeychainAttributeList { UInt32 count; SecKeychainAttribute * __nullable attr; }; -typedef struct SecKeychainAttributeList SecKeychainAttributeList API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct SecKeychainAttributeList SecKeychainAttributeList API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainStatus @abstract Represents the status of a keychain. */ -typedef UInt32 SecKeychainStatus API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef UInt32 SecKeychainStatus API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecTrustedApplicationRef @abstract Contains information about a trusted application. */ -typedef struct CF_BRIDGED_TYPE(id) __SecTrustedApplication *SecTrustedApplicationRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecTrustedApplication *SecTrustedApplicationRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecAccessRef @abstract Contains information about an access. */ -typedef struct CF_BRIDGED_TYPE(id) __SecAccess *SecAccessRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecAccess *SecAccessRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); #if TARGET_OS_OSX typedef struct __SecAccess OpaqueSecAccessRef; @@ -213,13 +213,13 @@ typedef struct __SecAccess OpaqueSecAccessRef; @typedef SecACLRef @abstract Contains information about an access control list (ACL) entry. */ -typedef struct CF_BRIDGED_TYPE(id) __SecACL *SecACLRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecACL *SecACLRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecPasswordRef @abstract Contains information about a password. */ -typedef struct CF_BRIDGED_TYPE(id) __SecPassword *SecPasswordRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct CF_BRIDGED_TYPE(id) __SecPassword *SecPasswordRef API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @typedef SecKeychainAttributeInfo @@ -229,13 +229,13 @@ typedef struct CF_BRIDGED_TYPE(id) __SecPassword *SecPasswordRef API_UNAVAILABLE @field format A pointer to the first CSSM_DB_ATTRIBUTE_FORMAT in the array. @discussion Each tag and format item form a pair. */ -struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) SecKeychainAttributeInfo +struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) SecKeychainAttributeInfo { UInt32 count; UInt32 *tag; UInt32 * __nullable format; }; -typedef struct SecKeychainAttributeInfo SecKeychainAttributeInfo API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +typedef struct SecKeychainAttributeInfo SecKeychainAttributeInfo API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecCopyErrorMessageString @@ -336,6 +336,7 @@ CF_ENUM(OSStatus) errSecCoreFoundationUnknown = -4960, errSecMissingEntitlement = -34018, /* A required entitlement isn't present. */ + errSecRestrictedAPI = -34020, /* Client is restricted and is not permitted to perform this operation. */ errSecNotAvailable = -25291, /* No keychain is available. You may need to restart your computer. */ errSecReadOnly = -25292, /* This keychain cannot be modified. */ @@ -704,6 +705,7 @@ CF_ENUM(OSStatus) errSecCertificatePolicyNotAllowed = -67899, /* The requested policy is not allowed for this certificate. */ errSecCertificateNameNotAllowed = -67900, /* The requested name is not allowed for this certificate. */ errSecCertificateValidityPeriodTooLong = -67901, /* The validity period in the certificate exceeds the maximum allowed. */ + errSecCertificateIsCA = -67902, /* The verified certificate is a CA rather than an end-entity */ }; @@ -785,6 +787,7 @@ CF_ENUM(OSStatus) @constant errSSLATSLeafCertificateHashAlgorithmViolation ATS violation: peer leaf certificate hash algorithm is not ATS compliant @constant errSSLATSCertificateHashAlgorithmViolation ATS violation: peer certificate hash algorithm is not ATS compliant @constant errSSLATSCertificateTrustViolation ATS violation: peer certificate is not issued by trusted peer + @constant errSSLEarlyDataRejected Early application data rejected by peer */ /* @@ -883,6 +886,9 @@ CF_ENUM(OSStatus) { errSSLATSLeafCertificateHashAlgorithmViolation = -9884, /* ATS violation: peer leaf certificate hash algorithm is not ATS compliant */ errSSLATSCertificateHashAlgorithmViolation = -9885, /* ATS violation: peer certificate hash algorithm is not ATS compliant */ errSSLATSCertificateTrustViolation = -9886, /* ATS violation: peer certificate is not issued by trusted peer */ + + /* early data errors */ + errSSLEarlyDataRejected = -9890, /* Early application data rejected by peer */ }; CF_IMPLICIT_BRIDGING_DISABLED diff --git a/base/SecBasePriv.h b/base/SecBasePriv.h index d2732607..16578154 100644 --- a/base/SecBasePriv.h +++ b/base/SecBasePriv.h @@ -125,7 +125,7 @@ OSStatus SecKeychainErrFromOSStatus(OSStatus osStatus) * This only apply to MacOS where background session exists. */ void _SecSetSecuritydTargetUID(uid_t uid) - API_AVAILABLE(macos(10.13.5)) API_UNAVAILABLE(ios, iosmac, watchos, tvos, bridgeos); + API_AVAILABLE(macos(10.13.5)) API_UNAVAILABLE(ios, macCatalyst, watchos, tvos, bridgeos); diff --git a/base/SecInternal.h b/base/SecInternal.h index 92d8f3a9..aaa000f4 100644 --- a/base/SecInternal.h +++ b/base/SecInternal.h @@ -29,7 +29,7 @@ #ifndef _SECURITY_SECINTERNAL_H_ #define _SECURITY_SECINTERNAL_H_ -#include +#include "utilities/simulatecrash_assert.h" #include #include diff --git a/codesign_wrapper/check_entitlements.c b/codesign_wrapper/check_entitlements.c index 0ab4da76..68633e06 100644 --- a/codesign_wrapper/check_entitlements.c +++ b/codesign_wrapper/check_entitlements.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/cssm/cssmapple.h b/cssm/cssmapple.h index 456174f9..8fcb7582 100644 --- a/cssm/cssmapple.h +++ b/cssm/cssmapple.h @@ -570,6 +570,8 @@ enum CSSMERR_APPLETP_IDENTIFIER_MISSING = -2147408837, /* Certificate authority pinning mismatch */ CSSMERR_APPLETP_CA_PIN_MISMATCH = -2147408836, + /* Leaf pinning mismatch */ + CSSMERR_APPLETP_LEAF_PIN_MISMATCH = -2147408835, }; /* Apple .mac TP private error codes. */ @@ -605,7 +607,7 @@ enum enum { - CSSM_APPLEDL_OPEN_PARAMETERS_VERSION = 1 + CSSM_APPLEDL_OPEN_PARAMETERS_VERSION = 1u }; enum cssm_appledl_open_parameters_mask diff --git a/experiment/SecExperiment.m b/experiment/SecExperiment.m index c39ddaa5..f6e82895 100644 --- a/experiment/SecExperiment.m +++ b/experiment/SecExperiment.m @@ -154,11 +154,10 @@ SEC_EXP_OBJECT_IMPL_INTERNAL_OBJC(sec_experiment, return SEC_EXP_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { - return SEC_EXP_NIL_OUT_OF_MEMORY; - } else { + if ((self = [super init])) { self->innerExperiment = [[SecExperiment alloc] initWithName:name]; + } else { + return SEC_EXP_NIL_OUT_OF_MEMORY; } return self; } @@ -169,11 +168,10 @@ SEC_EXP_OBJECT_IMPL_INTERNAL_OBJC(sec_experiment, return SEC_EXP_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { - return SEC_EXP_NIL_OUT_OF_MEMORY; - } else { + if ((self = [super init])) { self->innerExperiment = experiment; + } else { + return SEC_EXP_NIL_OUT_OF_MEMORY; } return self; } @@ -224,11 +222,10 @@ SEC_EXP_OBJECT_IMPL_INTERNAL_OBJC(sec_experiment, return SEC_EXP_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { - return SEC_EXP_NIL_OUT_OF_MEMORY; - } else { + if ((self = [super init])) { self.name = [NSString stringWithUTF8String:name]; + } else { + return SEC_EXP_NIL_OUT_OF_MEMORY; } return self; } @@ -381,10 +378,7 @@ SEC_EXP_OBJECT_IMPL_INTERNAL_OBJC(sec_experiment, return SEC_EXP_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { - return SEC_EXP_NIL_OUT_OF_MEMORY; - } else { + if ((self = [super init])) { // Parse out experiment information from the configuration dictionary self.config = configuration; self.identifier = [configuration objectForKey:SecExperimentConfigurationKeyExperimentIdentifier]; @@ -400,7 +394,10 @@ SEC_EXP_OBJECT_IMPL_INTERNAL_OBJC(sec_experiment, } self.configurationData = [configuration objectForKey:SecExperimentConfigurationKeyConfigurationData]; + } else { + return SEC_EXP_NIL_OUT_OF_MEMORY; } + return self; } diff --git a/experiment/SecExperimentInternal.h b/experiment/SecExperimentInternal.h index 2e05a813..efb4f251 100644 --- a/experiment/SecExperimentInternal.h +++ b/experiment/SecExperimentInternal.h @@ -30,7 +30,7 @@ extern const NSString *SecExperimentConfigurationKeyConfigurationData; @interface SecExperiment : NSObject @property (readonly) NSString *name; -@property (readonly) NSString *identifier; +@property (readonly, nullable) NSString *identifier; @property (readonly) BOOL samplingDisabled; - (instancetype)initWithName:(const char *)name; - (BOOL)experimentIsAllowedForProcess; @@ -51,7 +51,7 @@ extern const NSString *SecExperimentConfigurationKeyConfigurationData; * Create an ARC-able `sec_experiment_t` instance wrapping an internal `SecExperiment` object. * * @param experiment - * Name of the experiment. + * The experiment * * @return a `sec_experiment_t` instance. */ diff --git a/experiment/tool/experimentTool.m b/experiment/tool/experimentTool.m index e08c385d..84aa3f61 100644 --- a/experiment/tool/experimentTool.m +++ b/experiment/tool/experimentTool.m @@ -22,9 +22,9 @@ run_experiment(const char *experiment_name, size_t num_runs, bool sampling_disab for (size_t i = 0; i < num_runs; i++) { (void)sec_experiment_run_with_sampling_disabled(experiment_name, ^bool(const char *identifier, xpc_object_t experiment_config) { runs++; - CFDictionaryRef configuration = (CFDictionaryRef)_CFXPCCreateCFObjectFromXPCObject(experiment_config); + NSDictionary* configuration = (__bridge_transfer NSDictionary*)_CFXPCCreateCFObjectFromXPCObject(experiment_config); if (configuration != NULL) { - [configurations addObject:(__bridge NSDictionary *)configuration]; + [configurations addObject:configuration]; } return true; }, ^(const char * _Nonnull identifier) { @@ -58,6 +58,7 @@ main(int argc, const char *argv[]) while ((arg = getopt(argc, gargv, "e:n:sruh")) != -1) { switch (arg) { case 'e': + free(experiment_name); // Only the last instance of -e counts experiment_name = strdup(optarg); break; case 'n': @@ -77,6 +78,7 @@ main(int argc, const char *argv[]) break; default: fprintf(stderr, "%s: FAILURE: unknown option \"%c\"\n", argv[0], arg); + free(experiment_name); return -1; } } diff --git a/featureflags/Security.plist b/featureflags/Security.plist index 1ffb729d..19d4b097 100644 --- a/featureflags/Security.plist +++ b/featureflags/Security.plist @@ -2,6 +2,16 @@ + SecErrorNestedErrorCapping + + Enabled + + + OctagonEscrowRecordFetch + + Enabled + + EnableSecureObjectSync Enabled @@ -30,7 +40,7 @@ CKKSViewsFromPolicy Enabled - + securitydReportPolicy @@ -42,5 +52,20 @@ Enabled + OctagonOptimization + + Enabled + + + SecItemRateLimiting + + Enabled + + + LegacyAPICounts + + Enabled + + diff --git a/header_symlinks/OctagonTrust/OTCDPRecoveryInformation.h b/header_symlinks/OctagonTrust/OTCDPRecoveryInformation.h new file mode 120000 index 00000000..2ce370d7 --- /dev/null +++ b/header_symlinks/OctagonTrust/OTCDPRecoveryInformation.h @@ -0,0 +1 @@ +./..//keychain/ot/proto/generated_source/OTCDPRecoveryInformation.h \ No newline at end of file diff --git a/header_symlinks/OctagonTrust/OTEscrowAuthenticationInformation.h b/header_symlinks/OctagonTrust/OTEscrowAuthenticationInformation.h new file mode 120000 index 00000000..e50cdc1c --- /dev/null +++ b/header_symlinks/OctagonTrust/OTEscrowAuthenticationInformation.h @@ -0,0 +1 @@ +./..//keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.h \ No newline at end of file diff --git a/header_symlinks/OctagonTrust/OTEscrowRecord.h b/header_symlinks/OctagonTrust/OTEscrowRecord.h new file mode 120000 index 00000000..13ded541 --- /dev/null +++ b/header_symlinks/OctagonTrust/OTEscrowRecord.h @@ -0,0 +1 @@ +./..//keychain/ot/proto/generated_source/OTEscrowRecord.h \ No newline at end of file diff --git a/header_symlinks/OctagonTrust/OTEscrowRecordMetadata.h b/header_symlinks/OctagonTrust/OTEscrowRecordMetadata.h new file mode 120000 index 00000000..eeaa348a --- /dev/null +++ b/header_symlinks/OctagonTrust/OTEscrowRecordMetadata.h @@ -0,0 +1 @@ +./..//keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h \ No newline at end of file diff --git a/header_symlinks/OctagonTrust/OTEscrowRecordMetadataClientMetadata.h b/header_symlinks/OctagonTrust/OTEscrowRecordMetadataClientMetadata.h new file mode 120000 index 00000000..a875bda1 --- /dev/null +++ b/header_symlinks/OctagonTrust/OTEscrowRecordMetadataClientMetadata.h @@ -0,0 +1 @@ +./..//keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h \ No newline at end of file diff --git a/header_symlinks/OctagonTrust/OTEscrowTranslation.h b/header_symlinks/OctagonTrust/OTEscrowTranslation.h new file mode 120000 index 00000000..3d26489a --- /dev/null +++ b/header_symlinks/OctagonTrust/OTEscrowTranslation.h @@ -0,0 +1 @@ +./../keychain/OctagonTrust/OTEscrowTranslation.h \ No newline at end of file diff --git a/header_symlinks/OctagonTrust/OTICDPRecordContext.h b/header_symlinks/OctagonTrust/OTICDPRecordContext.h new file mode 120000 index 00000000..c06c0ba5 --- /dev/null +++ b/header_symlinks/OctagonTrust/OTICDPRecordContext.h @@ -0,0 +1 @@ +./..//keychain/ot/proto/generated_source/OTICDPRecordContext.h \ No newline at end of file diff --git a/header_symlinks/OctagonTrust/OTICDPRecordSilentContext.h b/header_symlinks/OctagonTrust/OTICDPRecordSilentContext.h new file mode 120000 index 00000000..882187b2 --- /dev/null +++ b/header_symlinks/OctagonTrust/OTICDPRecordSilentContext.h @@ -0,0 +1 @@ +./..//keychain/ot/proto/generated_source/OTICDPRecordSilentContext.h \ No newline at end of file diff --git a/header_symlinks/OctagonTrust/OctagonTrust.h b/header_symlinks/OctagonTrust/OctagonTrust.h new file mode 120000 index 00000000..54e11ad6 --- /dev/null +++ b/header_symlinks/OctagonTrust/OctagonTrust.h @@ -0,0 +1 @@ +./../keychain/OctagonTrust/OctagonTrust.h \ No newline at end of file diff --git a/header_symlinks/Security/SFSignInAnalytics.h b/header_symlinks/Security/SFSignInAnalytics.h deleted file mode 120000 index fca39ae9..00000000 --- a/header_symlinks/Security/SFSignInAnalytics.h +++ /dev/null @@ -1 +0,0 @@ -./../keychain/Signin Metrics/SFSignInAnalytics.h \ No newline at end of file diff --git a/header_symlinks/Security/SecExperimentPriv.h b/header_symlinks/Security/SecExperimentPriv.h index eac6c122..778afb6a 120000 --- a/header_symlinks/Security/SecExperimentPriv.h +++ b/header_symlinks/Security/SecExperimentPriv.h @@ -1 +1 @@ -./../SecExperiment/SecExperimentPriv.h \ No newline at end of file +./../experiment/SecExperimentPriv.h \ No newline at end of file diff --git a/header_symlinks/Security/certExtensionTemplates.h b/header_symlinks/Security/certExtensionTemplates.h index 4ec4d929..fefd8c30 120000 --- a/header_symlinks/Security/certExtensionTemplates.h +++ b/header_symlinks/Security/certExtensionTemplates.h @@ -1 +1 @@ -./OSX/libsecurity_asn1/lib/certExtensionTemplates.h \ No newline at end of file +./../OSX/libsecurity_asn1/lib/certExtensionTemplates.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecBreadcrumb.h b/header_symlinks/macOS/Security/SecBreadcrumb.h deleted file mode 120000 index fb71c7f4..00000000 --- a/header_symlinks/macOS/Security/SecBreadcrumb.h +++ /dev/null @@ -1 +0,0 @@ -./../../OSX/Breadcrumb/SecBreadcrumb.h \ No newline at end of file diff --git a/header_symlinks/macOS/Security/SecCertificateBundle.h b/header_symlinks/macOS/Security/SecCertificateBundle.h deleted file mode 120000 index b651860d..00000000 --- a/header_symlinks/macOS/Security/SecCertificateBundle.h +++ /dev/null @@ -1 +0,0 @@ -./../../OSX/libsecurity_keychain/lib/SecCertificateBundle.h \ No newline at end of file diff --git a/keychain/CoreDataKeychain/SecCDKeychain.m b/keychain/CoreDataKeychain/SecCDKeychain.m index 77ac9689..12617744 100644 --- a/keychain/CoreDataKeychain/SecCDKeychain.m +++ b/keychain/CoreDataKeychain/SecCDKeychain.m @@ -302,6 +302,7 @@ SecCDKeychainLookupValueType* const SecCDKeychainLookupValueTypeDate = (SecCDKey - (NSData*)_onQueueGetDatabaseKeyDataWithError:(NSError**)error { + dispatch_assert_queue(_queue); NSData* keyData = nil; NSDictionary* databaseKeyQuery = @{ (id)kSecClass : (id)kSecClassGenericPassword, (id)kSecAttrAccessGroup : @"com.apple.security.securityd", @@ -458,6 +459,7 @@ SecCDKeychainLookupValueType* const SecCDKeychainLookupValueTypeDate = (SecCDKey - (void)_onQueueDropClassAPersistentStore { + dispatch_assert_queue(_queue); for (NSPersistentStore* store in _classAPersistentStores) { NSError* error = nil; if (![_persistentStoreCoordinator removePersistentStore:store error:&error]) { diff --git a/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m b/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m index b79201ec..28dafff8 100644 --- a/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m +++ b/keychain/KeychainDataclassOwner/KeychainDataclassOwner.m @@ -93,19 +93,29 @@ static NSString* const KeychainDataclass = @"KeychainDataclass"; creditCardsQuery[(id)kSecAttrAccessGroup] = @"com.apple.safari.credit-cards"; OSStatus creditCardsResult = SecItemDelete((__bridge CFDictionaryRef)creditCardsQuery); - if (inetResult != errSecSuccess) { + if (inetResult == errSecSuccess) { + secnotice("itemDelete", "deleted synchronizable passwords from table inet"); + } else { secwarning("failed to delete synchronizable passwords from table inet: %d", (int)inetResult); } - if (genpResult != errSecSuccess) { + if (genpResult == errSecSuccess) { + secnotice("itemDelete", "deleted synchronizable passwords from table genp"); + } else { secwarning("failed to delete synchronizable passwords from table genp: %d", (int)genpResult); } - if (certResult != errSecSuccess) { - secwarning("failed to delete synchronizable passwords from table cert: %d", (int)certResult); + if (certResult == errSecSuccess) { + secnotice("itemDelete", "deleted synchronizable certificates from table cert"); + } else { + secwarning("failed to delete synchronizable certificates from table cert: %d", (int)certResult); } - if (keyResult != errSecSuccess) { - secwarning("failed to delete synchronizable passwords from table keys: %d", (int)keyResult); + if (keyResult == errSecSuccess) { + secnotice("itemDelete", "deleted synchronizable keys from table keys"); + } else { + secwarning("failed to delete synchronizable keys from table keys: %d", (int)keyResult); } - if (creditCardsResult != errSecSuccess) { + if (creditCardsResult == errSecSuccess) { + secnotice("itemDelete", "deleted credit cards from table genp"); + } else { secwarning("failed to delete credit cards from table genp: %d", (int)creditCardsResult); } } diff --git a/keychain/KeychainStasher/KeychainStasher-Info.plist b/keychain/KeychainStasher/KeychainStasher-Info.plist new file mode 100644 index 00000000..777a5d4d --- /dev/null +++ b/keychain/KeychainStasher/KeychainStasher-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + KeychainStasher + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/keychain/KeychainStasher/KeychainStasher.entitlements b/keychain/KeychainStasher/KeychainStasher.entitlements new file mode 100644 index 00000000..7a31b992 --- /dev/null +++ b/keychain/KeychainStasher/KeychainStasher.entitlements @@ -0,0 +1,10 @@ + + + + + application-identifier + com.apple.security.KeychainStasher + com.apple.private.keychain.sysbound + + + diff --git a/keychain/KeychainStasher/KeychainStasher.h b/keychain/KeychainStasher/KeychainStasher.h new file mode 100644 index 00000000..c723cebb --- /dev/null +++ b/keychain/KeychainStasher/KeychainStasher.h @@ -0,0 +1,5 @@ +#import +#import "KeychainStasherProtocol.h" + +@interface KeychainStasher : NSObject +@end diff --git a/keychain/KeychainStasher/KeychainStasher.m b/keychain/KeychainStasher/KeychainStasher.m new file mode 100644 index 00000000..efc8cdd4 --- /dev/null +++ b/keychain/KeychainStasher/KeychainStasher.m @@ -0,0 +1,116 @@ +#import + +#import "utilities/debugging.h" +#import +#import "LocalKeychainAnalytics.h" + +#import "KeychainStasher.h" + +NSString* const kApplicationIdentifier = @"com.apple.security.KeychainStasher"; + +@implementation KeychainStasher + +- (NSError*)errorWithStatus:(OSStatus)status message:(NSString*)format, ... NS_FORMAT_FUNCTION(2, 3) +{ + if (status == errSecSuccess) { + return nil; + } + + NSString* desc; + if (format) { + va_list ap; + va_start(ap, format); + desc = [[NSString alloc] initWithFormat:format arguments:ap]; + va_end(ap); + } + return [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + userInfo:desc ? @{NSLocalizedDescriptionKey : desc} : nil]; +} + +- (NSMutableDictionary*)baseQuery { + return [@{ + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly, + // Prevents backups in case this ever comes to the Mac, prevents sync + (id)kSecAttrSysBound : @(kSecSecAttrSysBoundPreserveDuringRestore), + // Belt-and-suspenders prohibition on syncing + (id)kSecAttrSynchronizable : @NO, + (id)kSecClass : (id)kSecClassKey, + (id)kSecAttrApplicationLabel : @"loginstash", + // This is the default, but just making sure + (id)kSecAttrAccessGroup : kApplicationIdentifier, + } mutableCopy]; +} + +- (void)stashKey:(NSData*)key withReply:(void (^)(NSError*))reply { + secnotice("stashkey", "Will attempt to stash key"); + if (!key || key.length == 0) { + reply([self errorWithStatus:errSecParam message:@"nil or empty key passed"]); + return; + } + + NSMutableDictionary* query = [self baseQuery]; + query[(id)kSecValueData] = key; + + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); + secnotice("stashkey", "SecItemAdd result: %ld", (long)status); + + if (status == errSecDuplicateItem) { + [[LocalKeychainAnalytics logger] logResultForEvent:LKAEventStash hardFailure:NO result:[self errorWithStatus:status message:nil]]; + query[(id)kSecValueData] = nil; + NSDictionary* update = @{(id)kSecValueData : key}; + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update); + secnotice("stashkey", "SecItemUpdate result: %ld", (long)status); + } + + [[LocalKeychainAnalytics logger] logResultForEvent:LKAEventStash hardFailure:YES result:[self errorWithStatus:status message:nil]]; + if (status == errSecSuccess) { + reply(nil); + } else { + reply([self errorWithStatus:status message:@"Stash failed with keychain error"]); + } +} + +- (void)loadKeyWithReply:(void (^)(NSData*, NSError*))reply { + secnotice("KeychainStasher", "Will attempt to retrieve stashed key"); + + NSMutableDictionary* query = [self baseQuery]; + query[(id)kSecReturnData] = @YES; + + CFTypeRef object = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &object); + + if (status != errSecSuccess) { + if (status == errSecItemNotFound) { + reply(nil, [self errorWithStatus:status message:@"No stashed key found"]); + } else { + reply(nil, [self errorWithStatus:status message:@"Keychain error"]); + } + [[LocalKeychainAnalytics logger] logResultForEvent:LKAEventStashLoad hardFailure:YES result:[self errorWithStatus:status message:nil]]; + return; + } + + NSData* key; + if (!object || CFGetTypeID(object) != CFDataGetTypeID() || !(key = CFBridgingRelease(object))) { + reply(nil, [self errorWithStatus:errSecInternalError + message:@"No or bad object: %d / %lu / %d", + object != NULL, object ? CFGetTypeID(object) : 0, key != nil]); + [[LocalKeychainAnalytics logger] logResultForEvent:LKAEventStashLoad + hardFailure:YES + result:[self errorWithStatus:errSecInternalError message:nil]]; + return; + } + + // Caller does not need to wait for our delete + reply(key, nil); + + query[(id)kSecReturnData] = nil; + status = SecItemDelete((__bridge CFDictionaryRef)query); + if (status != errSecSuccess) { + seccritical("Unable to delete masterkey after load: %d", (int)status); + } + [[LocalKeychainAnalytics logger] logResultForEvent:LKAEventStashLoad hardFailure:NO result:[self errorWithStatus:status message:nil]]; +} + +@end diff --git a/keychain/KeychainStasher/KeychainStasherProtocol.h b/keychain/KeychainStasher/KeychainStasherProtocol.h new file mode 100644 index 00000000..c837e325 --- /dev/null +++ b/keychain/KeychainStasher/KeychainStasherProtocol.h @@ -0,0 +1,13 @@ +#ifndef KeychainStasherProtocol_h +#define KeychainStasherProtocol_h + +#import + +@protocol KeychainStasherProtocol + +- (void)stashKey:(NSData*)key withReply:(void (^)(NSError*))reply; +- (void)loadKeyWithReply:( void (^)(NSData*, NSError*))reply; + +@end + +#endif /* KeychainStasherProtocol_h */ diff --git a/keychain/KeychainStasher/com.apple.security.KeychainStasher.plist b/keychain/KeychainStasher/com.apple.security.KeychainStasher.plist new file mode 100644 index 00000000..df467bce --- /dev/null +++ b/keychain/KeychainStasher/com.apple.security.KeychainStasher.plist @@ -0,0 +1,25 @@ + + + + + EnablePressuredExit + + EnableTransactions + + LimitLoadToSessionType + Background + POSIXSpawnType + Adaptive + Label + com.apple.security.KeychainStasher + MachServices + + com.apple.security.KeychainStasher + + + ProgramArguments + + /usr/libexec/KeychainStasher + + + diff --git a/keychain/KeychainStasher/com.apple.security.KeychainStasher.sb b/keychain/KeychainStasher/com.apple.security.KeychainStasher.sb new file mode 100644 index 00000000..5c86637d --- /dev/null +++ b/keychain/KeychainStasher/com.apple.security.KeychainStasher.sb @@ -0,0 +1,22 @@ +(version 1) + +(deny default) +(deny file-map-executable process-info* nvram*) +(deny dynamic-code-generation) + +(import "system.sb") +(import "com.apple.corefoundation.sb") +(corefoundation) + +(allow process-info-dirtycontrol (target self)) + +(allow mach-lookup (global-name "com.apple.securityd.xpc")) + +(allow file-read-metadata) + +(if (param "ANALYTICSDIR") + (allow file-read* file-write* (subpath (param "ANALYTICSDIR")))) + +(allow file-read* (subpath "/usr/libexec")) + +(allow user-preference-read (preference-domain "kCFPreferencesAnyApplication")) diff --git a/keychain/KeychainStasher/main.m b/keychain/KeychainStasher/main.m new file mode 100644 index 00000000..45be5ed2 --- /dev/null +++ b/keychain/KeychainStasher/main.m @@ -0,0 +1,72 @@ +#import +#import +#import +#import +#import + +#import +#import +#import + +#import "KeychainStasher.h" + +NSString* const KeychainStasherMachServiceName = @"com.apple.security.KeychainStasher"; + +@interface ServiceDelegate : NSObject +@end + +@implementation ServiceDelegate + +- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection { + // We should encounter no more than 1 transaction per boot in normal conditions, so get out of everyone's way ASAP + xpc_transaction_exit_clean(); + + NSNumber* value = [newConnection valueForEntitlement:kSecEntitlementPrivateStashService]; + if (value == nil || ![value boolValue]) { + secerror("KeychainStasher: client not entitled, rejecting connection"); + [newConnection invalidate]; + return NO; + } + + newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)]; + newConnection.exportedObject = [KeychainStasher new]; + [newConnection resume]; + return YES; +} + +@end + +int main(int argc, const char *argv[]) +{ + if (geteuid() == 0) { + secerror("KeychainStasher invoked as root, do not want."); + return 1; + } else { + secnotice("KeychainStasher", "Invoked with uid %d", geteuid()); + } + + NSString* analyticsdir = [[(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(nil) URLByAppendingPathComponent:@"Analytics/"] path]; + if (analyticsdir) { + const char* sandbox_parameters[] = {"ANALYTICSDIR", analyticsdir.UTF8String, NULL}; + char* sandbox_error = NULL; + if (0 != sandbox_init_with_parameters("com.apple.security.KeychainStasher", SANDBOX_NAMED, sandbox_parameters, &sandbox_error)) { + secerror("unable to enter sandbox with parameter: %s", sandbox_error); + sandbox_free_error(sandbox_error); + abort(); + } + } else { // If this fails somehow we will go ahead without analytics + char* sandbox_error = NULL; + if (0 != sandbox_init("com.apple.security.KeychainStasher", SANDBOX_NAMED, &sandbox_error)) { + secerror("unable to enter sandbox: %s", sandbox_error); + sandbox_free_error(sandbox_error); + abort(); + } + } + + ServiceDelegate *delegate = [ServiceDelegate new]; + NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:KeychainStasherMachServiceName]; + listener.delegate = delegate; + [listener resume]; + [[NSRunLoop currentRunLoop] run]; + return 0; +} diff --git a/keychain/OctagonTrust/Info.plist b/keychain/OctagonTrust/Info.plist new file mode 100644 index 00000000..9bcb2444 --- /dev/null +++ b/keychain/OctagonTrust/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/keychain/OctagonTrust/OTEscrowTranslation.h b/keychain/OctagonTrust/OTEscrowTranslation.h new file mode 100644 index 00000000..700c2d0a --- /dev/null +++ b/keychain/OctagonTrust/OTEscrowTranslation.h @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2020 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@ +*/ + +#ifndef EscrowTranslation_h +#define EscrowTranslation_h +#if __OBJC2__ + +#import +#import +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OTEscrowTranslation : NSObject + +//dictionary to escrow auth ++ (OTEscrowAuthenticationInformation* _Nullable )dictionaryToEscrowAuthenticationInfo:(NSDictionary*)dictionary; + +//escrow auth to dictionary ++ (NSDictionary* _Nullable)escrowAuthenticationInfoToDictionary:(OTEscrowAuthenticationInformation*)escrowAuthInfo; + +//dictionary to escrow record ++ (OTEscrowRecord* _Nullable)dictionaryToEscrowRecord:(NSDictionary*)dictionary; + +//escrow record to dictionary ++ (NSDictionary* _Nullable)escrowRecordToDictionary:(OTEscrowRecord*)escrowRecord; + +//dictionary to icdp record context ++ (OTICDPRecordContext* _Nullable)dictionaryToCDPRecordContext:(NSDictionary*)dictionary; + +//icdp record context to dictionary ++ (NSDictionary* _Nullable)CDPRecordContextToDictionary:(OTICDPRecordContext*)context; + ++ (NSDictionary * _Nullable) metadataToDictionary:(OTEscrowRecordMetadata*)metadata; + ++ (OTEscrowRecordMetadata * _Nullable) dictionaryToMetadata:(NSDictionary*)dictionary; + ++ (BOOL)supportedRestorePath:(OTICDPRecordContext*)cdpContext; + +@end + +NS_ASSUME_NONNULL_END + +#endif + +#endif /* EscrowTranslation_h */ diff --git a/keychain/OctagonTrust/OTEscrowTranslation.m b/keychain/OctagonTrust/OTEscrowTranslation.m new file mode 100644 index 00000000..3d558964 --- /dev/null +++ b/keychain/OctagonTrust/OTEscrowTranslation.m @@ -0,0 +1,396 @@ +/* +* Copyright (c) 2020 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@ +*/ + +#import +#import "OTEscrowTranslation.h" + +#import +#import +#import +#import "keychain/ot/categories/OctagonEscrowRecoverer.h" +#import +#import +#import +#import "keychain/ot/OTClique+Private.h" +#import + +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CloudServices); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" + +SOFT_LINK_CLASS(CloudServices, SecureBackup); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupErrorDomain, NSErrorDomain); + +/* Escrow Authentication Information used for SRP*/ +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationAppleID, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationPassword, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationiCloudEnvironment, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationAuthToken, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationEscrowProxyURL, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupIDMSRecoveryKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupFMiPRecoveryKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupFMiPUUIDKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAuthenticationDSID, NSString*); + +/* CDP recovery information */ +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUseCachedPassphraseKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPassphraseKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecoveryKeyKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupContainsiCDPDataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupSilentRecoveryAttemptKey, NSString*); + + +/* Escrow Record Fields set by SecureBackup*/ +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupIsEnabledKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesRecoveryKeyKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupLastBackupTimestampKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupLastBackupDateKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupEscrowTrustStatusKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordStatusKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordIDKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPeerInfoDataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPeerInfoSerialNumberKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupPeerInfoOSVersionKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAlliCDPRecordsKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordLabelKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupEscrowedSPKIKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBottleIDKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupSerialNumberKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBuildVersionKey, NSString*); + +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesRandomPassphraseKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesComplexPassphraseKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesNumericPassphraseKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupNumericPassphraseLengthKey, NSString*); + +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecoveryRequiresVerificationTokenKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupAccountIsHighSecurityKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupSMSTargetInfoKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupMetadataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupUsesMultipleiCSCKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupClientMetadataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBottleValidityKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupEscrowDateKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRemainingAttemptsKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupCoolOffEndKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecoveryStatusKey, NSString*); + +#pragma clang diagnostic pop + +static NSString * const kCliqueSecureBackupTimestampKey = @"com.apple.securebackup.timestamp"; +static NSString * const kCliqueEscrowServiceRecordMetadataKey = @"metadata"; +static NSString * const kCliqueSecureBackupEncodedMetadataKey = @"encodedMetadata"; +static NSString * const kCliqueSecureBackupKeybagDigestKey = @"BackupKeybagDigest"; +static NSString * const kCliqueSecureBackupMetadataTimestampKey = @"SecureBackupMetadataTimestamp"; +static NSString * const kCliqueSecureBackupDeviceColor = @"device_color"; +static NSString * const kCliqueSecureBackupDeviceEnclosureColor = @"device_enclosure_color"; +static NSString * const kCliqueSecureBackupDeviceMID = @"device_mid"; +static NSString * const kCliqueSecureBackupDeviceModel = @"device_model"; +static NSString * const kCliqueSecureBackupDeviceModelClass = @"device_model_class"; +static NSString * const kCliqueSecureBackupDeviceModelVersion = @"device_model_version"; +static NSString * const kCliqueSecureBackupDeviceName = @"device_name"; +static NSString * const kCliqueSecureBackupDevicePlatform = @"device_platform"; +static NSString * const kCliqueSecureBackupSilentAttemptAllowed = @"silentAttemptAllowed"; + +@implementation OTEscrowTranslation + +//dictionary to escrow auth ++ (OTEscrowAuthenticationInformation*) dictionaryToEscrowAuthenticationInfo:(NSDictionary*)dictionary +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + OTEscrowAuthenticationInformation* escrowAuthInfo = [[OTEscrowAuthenticationInformation alloc] init]; + escrowAuthInfo.authenticationAppleid = dictionary[getkSecureBackupAuthenticationAppleID()]; + escrowAuthInfo.authenticationAuthToken = dictionary[getkSecureBackupAuthenticationAuthToken()]; + escrowAuthInfo.authenticationDsid = dictionary[getkSecureBackupAuthenticationDSID()]; + escrowAuthInfo.authenticationEscrowproxyUrl = dictionary[getkSecureBackupAuthenticationEscrowProxyURL()]; + escrowAuthInfo.authenticationIcloudEnvironment = dictionary[getkSecureBackupAuthenticationiCloudEnvironment()]; + escrowAuthInfo.authenticationPassword = dictionary[getkSecureBackupAuthenticationPassword()]; + escrowAuthInfo.fmipUuid = dictionary[getkSecureBackupFMiPUUIDKey()]; + escrowAuthInfo.fmipRecovery = [dictionary[getkSecureBackupFMiPRecoveryKey()] boolValue]; + escrowAuthInfo.idmsRecovery = [dictionary[getkSecureBackupIDMSRecoveryKey()] boolValue]; + + return escrowAuthInfo; +} + +//escrow auth to dictionary ++ (NSDictionary*) escrowAuthenticationInfoToDictionary:(OTEscrowAuthenticationInformation*)escrowAuthInfo +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; + if(![escrowAuthInfo.authenticationAppleid isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationAppleID()] = escrowAuthInfo.authenticationAppleid; + } + if(![escrowAuthInfo.authenticationAuthToken isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationAuthToken()] = escrowAuthInfo.authenticationAuthToken; + } + if(![escrowAuthInfo.authenticationDsid isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationDSID()] = escrowAuthInfo.authenticationDsid; + } + if(![escrowAuthInfo.authenticationEscrowproxyUrl isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationEscrowProxyURL()] = escrowAuthInfo.authenticationEscrowproxyUrl; + } + if(![escrowAuthInfo.authenticationIcloudEnvironment isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationiCloudEnvironment()] = escrowAuthInfo.authenticationIcloudEnvironment; + } + if(![escrowAuthInfo.authenticationPassword isEqualToString:@""]){ + dictionary[getkSecureBackupAuthenticationPassword()] = escrowAuthInfo.authenticationPassword; + } + if(![escrowAuthInfo.fmipUuid isEqualToString:@""]){ + dictionary[getkSecureBackupFMiPUUIDKey()] = escrowAuthInfo.fmipUuid; + } + dictionary[getkSecureBackupFMiPRecoveryKey()] = escrowAuthInfo.fmipRecovery ? @YES : @NO; + dictionary[getkSecureBackupIDMSRecoveryKey()] = escrowAuthInfo.idmsRecovery ? @YES : @NO; + + return dictionary; +} + ++ (OTCDPRecoveryInformation*)dictionaryToCDPRecoveryInformation:(NSDictionary*)dictionary +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + OTCDPRecoveryInformation* info = [[OTCDPRecoveryInformation alloc] init]; + info.recoverySecret = dictionary[getkSecureBackupPassphraseKey()]; + info.useCachedSecret = [dictionary[getkSecureBackupUseCachedPassphraseKey()] boolValue]; + info.recoveryKey = dictionary[getkSecureBackupRecoveryKeyKey()]; + info.usePreviouslyCachedRecoveryKey = [dictionary[getkSecureBackupUsesRecoveryKeyKey()] boolValue]; + info.silentRecoveryAttempt = [dictionary[@"SecureBackupSilentRecoveryAttempt"] boolValue]; + info.containsIcdpData =[dictionary[getkSecureBackupContainsiCDPDataKey()] boolValue]; + info.usesMultipleIcsc = [dictionary[getkSecureBackupUsesMultipleiCSCKey()] boolValue]; + return info; +} + ++ (NSDictionary*)cdpRecoveryInformationToDictionary:(OTCDPRecoveryInformation*)info +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; + dictionary[getkSecureBackupPassphraseKey()] = info.recoverySecret; + dictionary[getkSecureBackupUseCachedPassphraseKey()] = info.useCachedSecret ? @YES : @NO; + dictionary[getkSecureBackupRecoveryKeyKey()] = info.recoveryKey; + dictionary[getkSecureBackupUsesRecoveryKeyKey()] = info.usePreviouslyCachedRecoveryKey ? @YES : @NO; + dictionary[@"SecureBackupSilentRecoveryAttempt"] = info.silentRecoveryAttempt ? @YES : @NO; + dictionary[getkSecureBackupContainsiCDPDataKey()] = info.containsIcdpData ? @YES : @NO; + dictionary[getkSecureBackupUsesMultipleiCSCKey()] = info.usesMultipleIcsc ? @YES : @NO; + + return dictionary; +} + ++ (NSDate *)_dateWithSecureBackupDateString:(NSString *)dateString +{ + NSDateFormatter *dateFormatter = [NSDateFormatter new]; + dateFormatter.dateFormat = @"dd-MM-yyyy HH:mm:ss"; + NSDate *ret = [dateFormatter dateFromString:dateString]; + + if (ret) { + return ret; + } + // New date format is GMT + dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; + dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss"; + return [dateFormatter dateFromString:dateString]; +} + ++ (NSString*)_stringWithSecureBackupDate:(NSDate*) date +{ + NSDateFormatter *dateFormatter = [NSDateFormatter new]; + dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; + dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss"; + return [dateFormatter stringFromDate: date]; +} + ++ (OTEscrowRecordMetadata *) dictionaryToMetadata:(NSDictionary*)dictionary +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + OTEscrowRecordMetadata *metadata = [[OTEscrowRecordMetadata alloc] init]; + + metadata.backupKeybagDigest = dictionary[kCliqueSecureBackupKeybagDigestKey]; + metadata.secureBackupUsesMultipleIcscs = [dictionary[getkSecureBackupUsesMultipleiCSCKey()] boolValue]; + metadata.bottleId = dictionary[getkSecureBackupBottleIDKey()]; + metadata.bottleValidity = dictionary[@"bottleValid"]; + NSDate* secureBackupTimestamp = [OTEscrowTranslation _dateWithSecureBackupDateString: dictionary[kCliqueSecureBackupTimestampKey]]; + + metadata.secureBackupTimestamp = [secureBackupTimestamp timeIntervalSince1970]; + metadata.escrowedSpki = dictionary[getkSecureBackupEscrowedSPKIKey()]; + metadata.peerInfo = dictionary[getkSecureBackupPeerInfoDataKey()]; + metadata.serial = dictionary[getkSecureBackupSerialNumberKey()]; + + NSDictionary* escrowInformationMetadataClientMetadata = dictionary[getkSecureBackupClientMetadataKey()]; + metadata.clientMetadata = [[OTEscrowRecordMetadataClientMetadata alloc] init]; + NSNumber *platform = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDevicePlatform]; + metadata.clientMetadata.devicePlatform = [platform longLongValue]; + + NSDate* secureBackupMetadataTimestamp = [OTEscrowTranslation _dateWithSecureBackupDateString: escrowInformationMetadataClientMetadata[kCliqueSecureBackupMetadataTimestampKey]]; + metadata.clientMetadata.secureBackupMetadataTimestamp = [secureBackupMetadataTimestamp timeIntervalSince1970]; + + NSNumber *passphraseLength = escrowInformationMetadataClientMetadata[getkSecureBackupNumericPassphraseLengthKey()]; + metadata.clientMetadata.secureBackupNumericPassphraseLength = [passphraseLength longLongValue]; + metadata.clientMetadata.secureBackupUsesComplexPassphrase = [escrowInformationMetadataClientMetadata[getkSecureBackupUsesComplexPassphraseKey()] boolValue]; + metadata.clientMetadata.secureBackupUsesNumericPassphrase = [escrowInformationMetadataClientMetadata[getkSecureBackupUsesNumericPassphraseKey()] boolValue]; + metadata.clientMetadata.deviceColor = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceColor]; + metadata.clientMetadata.deviceEnclosureColor = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceEnclosureColor]; + metadata.clientMetadata.deviceMid = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceMID]; + metadata.clientMetadata.deviceModel = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceModel]; + metadata.clientMetadata.deviceModelClass = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceModelClass]; + metadata.clientMetadata.deviceModelVersion = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceModelVersion]; + metadata.clientMetadata.deviceName = escrowInformationMetadataClientMetadata[kCliqueSecureBackupDeviceName]; + + return metadata; +} + +//dictionary to escrow record ++ (OTEscrowRecord*) dictionaryToEscrowRecord:(NSDictionary*)dictionary +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + OTEscrowRecord* record = [[OTEscrowRecord alloc] init]; + NSDate* creationDate = dictionary[getkSecureBackupEscrowDateKey()]; + record.creationDate = [creationDate timeIntervalSince1970]; + NSDictionary* escrowInformationMetadata = dictionary[kCliqueEscrowServiceRecordMetadataKey]; + record.escrowInformationMetadata = [OTEscrowTranslation dictionaryToMetadata:escrowInformationMetadata]; + + NSNumber *remainingAttempts = dictionary[getkSecureBackupRemainingAttemptsKey()]; + + record.remainingAttempts = [remainingAttempts longLongValue]; + record.label = dictionary[getkSecureBackupRecordLabelKey()]; + record.recordStatus = [dictionary[getkSecureBackupRecordStatusKey()] isEqualToString:@"valid"] ? OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID : OTEscrowRecord_RecordStatus_RECORD_STATUS_INVALID; + record.silentAttemptAllowed = [dictionary[kCliqueSecureBackupSilentAttemptAllowed] boolValue]; + record.recordId = dictionary[getkSecureBackupRecordIDKey()]; + record.serialNumber = dictionary[getkSecureBackupPeerInfoSerialNumberKey()]; + if(dictionary[getkSecureBackupCoolOffEndKey()]) { + record.coolOffEnd = [dictionary[getkSecureBackupCoolOffEndKey()] longLongValue]; + } + record.recoveryStatus = [dictionary[getkSecureBackupRecoveryStatusKey()] intValue]; + return record; +} + ++ (NSDictionary *) metadataToDictionary:(OTEscrowRecordMetadata*)metadata +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + dictionary[getkSecureBackupClientMetadataKey()] = [NSMutableDictionary dictionary]; + + dictionary[kCliqueSecureBackupKeybagDigestKey] = metadata.backupKeybagDigest; + dictionary[getkSecureBackupUsesMultipleiCSCKey()] = [[NSNumber alloc]initWithUnsignedLongLong:metadata.secureBackupUsesMultipleIcscs]; + dictionary[getkSecureBackupBottleIDKey()] = metadata.bottleId; + dictionary[@"bottleValid"] = metadata.bottleValidity; + dictionary[kCliqueSecureBackupTimestampKey] = [OTEscrowTranslation _stringWithSecureBackupDate: [NSDate dateWithTimeIntervalSince1970: metadata.secureBackupTimestamp]]; + dictionary[getkSecureBackupEscrowedSPKIKey()] = metadata.escrowedSpki; + dictionary[getkSecureBackupPeerInfoDataKey()] = metadata.peerInfo; + dictionary[getkSecureBackupSerialNumberKey()] = metadata.serial; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDevicePlatform] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.devicePlatform]; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupMetadataTimestampKey] = [OTEscrowTranslation _stringWithSecureBackupDate: [NSDate dateWithTimeIntervalSince1970: metadata.clientMetadata.secureBackupMetadataTimestamp]]; + dictionary[getkSecureBackupClientMetadataKey()][getkSecureBackupNumericPassphraseLengthKey()] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.secureBackupNumericPassphraseLength]; + dictionary[getkSecureBackupClientMetadataKey()][getkSecureBackupUsesComplexPassphraseKey()] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.secureBackupUsesComplexPassphrase]; + dictionary[getkSecureBackupClientMetadataKey()][getkSecureBackupUsesNumericPassphraseKey()] = [[NSNumber alloc]initWithUnsignedLongLong: metadata.clientMetadata.secureBackupUsesNumericPassphrase]; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceColor] = metadata.clientMetadata.deviceColor; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceEnclosureColor] = metadata.clientMetadata.deviceEnclosureColor; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceMID] = metadata.clientMetadata.deviceMid; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceModel] = metadata.clientMetadata.deviceModel; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceModelClass] = metadata.clientMetadata.deviceModelClass; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceModelVersion] = metadata.clientMetadata.deviceModelVersion; + dictionary[getkSecureBackupClientMetadataKey()][kCliqueSecureBackupDeviceName] = metadata.clientMetadata.deviceName; + + return dictionary; +} + +//escrow record to dictionary ++ (NSDictionary*) escrowRecordToDictionary:(OTEscrowRecord*)escrowRecord +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; + dictionary[getkSecureBackupEscrowDateKey()] = [NSDate dateWithTimeIntervalSince1970: escrowRecord.creationDate]; + + dictionary[kCliqueEscrowServiceRecordMetadataKey] = [OTEscrowTranslation metadataToDictionary: escrowRecord.escrowInformationMetadata]; + + dictionary[getkSecureBackupRemainingAttemptsKey()] = [[NSNumber alloc]initWithUnsignedLongLong:escrowRecord.remainingAttempts]; + dictionary[getkSecureBackupRecordLabelKey()] = escrowRecord.label; + dictionary[getkSecureBackupRecordStatusKey()] = escrowRecord.recordStatus == OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID ? @"valid" : @"invalid"; + dictionary[kCliqueSecureBackupSilentAttemptAllowed] = [[NSNumber alloc] initWithUnsignedLongLong: escrowRecord.silentAttemptAllowed]; + dictionary[getkSecureBackupRecordIDKey()] = escrowRecord.recordId; + dictionary[getkSecureBackupPeerInfoSerialNumberKey()] = escrowRecord.serialNumber; + dictionary[getkSecureBackupCoolOffEndKey()] = @(escrowRecord.coolOffEnd); + dictionary[getkSecureBackupRecoveryStatusKey()] = @(escrowRecord.recoveryStatus); + + return dictionary; +} + ++ (OTICDPRecordContext*)dictionaryToCDPRecordContext:(NSDictionary*)dictionary +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + OTICDPRecordContext* context = [[OTICDPRecordContext alloc] init]; + context.authInfo = [OTEscrowTranslation dictionaryToEscrowAuthenticationInfo:dictionary]; + context.cdpInfo = [OTEscrowTranslation dictionaryToCDPRecoveryInformation:dictionary]; + + return context; +} + ++ (NSDictionary*)CDPRecordContextToDictionary:(OTICDPRecordContext*)context +{ + if ([OTClique isCloudServicesAvailable] == NO) { + return nil; + } + + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + + [dictionary addEntriesFromDictionary:[OTEscrowTranslation escrowAuthenticationInfoToDictionary:context.authInfo]]; + [dictionary addEntriesFromDictionary:[OTEscrowTranslation cdpRecoveryInformationToDictionary:context.cdpInfo]]; + + return dictionary; +} + ++ (BOOL)supportedRestorePath:(OTICDPRecordContext *)cdpContext +{ + return (cdpContext.authInfo.idmsRecovery == false + && (cdpContext.authInfo.fmipUuid == nil || [cdpContext.authInfo.fmipUuid isEqualToString:@""]) + && cdpContext.authInfo.fmipRecovery == false + && (cdpContext.cdpInfo.recoveryKey == nil || [cdpContext.cdpInfo.recoveryKey isEqualToString:@""]) + && cdpContext.cdpInfo.usePreviouslyCachedRecoveryKey == false); +} + +@end + diff --git a/keychain/OctagonTrust/OctagonTrust.h b/keychain/OctagonTrust/OctagonTrust.h new file mode 100644 index 00000000..72d31de3 --- /dev/null +++ b/keychain/OctagonTrust/OctagonTrust.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2020 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@ + */ + +#if __OBJC2__ + +#import +#import +#import +#import +#import +#import +#import +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +//! Project version number for OctagonTrust. +FOUNDATION_EXPORT double OctagonTrustVersionNumber; + +//! Project version string for OctagonTrust. +FOUNDATION_EXPORT const unsigned char OctagonTrustVersionString[]; + +extern NSString* OTCKContainerName; + +@interface OTConfigurationContext(Framework) +@property (nonatomic, copy, nullable) OTEscrowAuthenticationInformation* escrowAuth; +@end + +@interface OTClique(Framework) + +/* * + * @abstract Fetch recommended iCDP escrow records + * + * @param data, context containing parameters to setup OTClique + * @param error, error gets filled if something goes horribly wrong + * + * @return array of escrow records that can get a device back into trust + */ ++ (NSArray* _Nullable)fetchEscrowRecords:(OTConfigurationContext*)data error:(NSError**)error; + + +/* * + * @abstract Fetch all iCDP escrow records + * + * @param data, context containing parameters to setup OTClique + * @param error, error gets filled if something goes horribly wrong + * + * @return array of all escrow records (viable and legacy) + */ ++ (NSArray* _Nullable)fetchAllEscrowRecords:(OTConfigurationContext*)data error:(NSError**)error; + +/* * + * @abstract Perform escrow recovery of a particular record (not silent) + * + * @param data, context containing parameters to setup OTClique + * @param cdpContext, context containing parameters used in recovery + * @param escrowRecord, the chosen escrow record to recover from + * @param error, error gets filled if something goes horribly wrong + * + * @return clique, returns a new clique instance + */ ++ (instancetype _Nullable)performEscrowRecovery:(OTConfigurationContext*)data + cdpContext:(OTICDPRecordContext*)cdpContext + escrowRecord:(OTEscrowRecord*)escrowRecord + error:(NSError**)error; + +/* * + * @abstract Perform a silent escrow recovery + * + * @param data, context containing parameters to setup OTClique + * @param cdpContext, context containing parameters used in recovery + * @param allRecords, all fetched escrow records + * @param error, error gets filled if something goes horribly wrong + * @return clique, returns a new clique instance + */ ++ (instancetype _Nullable)performSilentEscrowRecovery:(OTConfigurationContext*)data + cdpContext:(OTICDPRecordContext*)cdpContext + allRecords:(NSArray*)allRecords + error:(NSError**)error; + ++ (BOOL) invalidateEscrowCache:(OTConfigurationContext*)data error:(NSError**)error; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/keychain/OctagonTrust/OctagonTrust.m b/keychain/OctagonTrust/OctagonTrust.m new file mode 100644 index 00000000..b24f5351 --- /dev/null +++ b/keychain/OctagonTrust/OctagonTrust.m @@ -0,0 +1,657 @@ +/* +* Copyright (c) 2020 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@ +*/ + +#if __OBJC2__ + +#import "OctagonTrust.h" +#import +#import +#import "OTEscrowTranslation.h" + +#import +#import +#import +#import "keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h" +#import "keychain/ot/OTDefines.h" +#import "keychain/ot/OTControl.h" +#import "keychain/ot/OTClique+Private.h" +#import +#include + +SOFT_LINK_FRAMEWORK(PrivateFrameworks, KeychainCircle); +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CloudServices); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +SOFT_LINK_CLASS(CloudServices, SecureBackup); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupErrorDomain, NSErrorDomain); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupiCDPRecordsKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupMetadataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordIDKey, NSString*); + +SOFT_LINK_CONSTANT(CloudServices, kEscrowServiceRecordDataKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupKeybagDigestKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupBagPasswordKey, NSString*); +SOFT_LINK_CONSTANT(CloudServices, kSecureBackupRecordLabelKey, NSString*); + +#pragma clang diagnostic pop + +static NSString * const kOTEscrowAuthKey = @"kOTEscrowAuthKey"; +NSString* OTCKContainerName = @"com.apple.security.keychain"; + +@implementation OTConfigurationContext(Framework) + +@dynamic escrowAuth; + +-(void) setEscrowAuth:(id)e +{ + objc_setAssociatedObject(self, (__bridge const void * _Nonnull)(kOTEscrowAuthKey), e, OBJC_ASSOCIATION_ASSIGN); + +} +- (id) escrowAuth +{ + return objc_getAssociatedObject(self, (__bridge const void * _Nonnull)(kOTEscrowAuthKey)); +} + +@end + +@implementation OTClique(Framework) + ++ (NSArray*)filterViableSOSRecords:(NSArray*)nonViable +{ + NSMutableArray* viableSOS = [NSMutableArray array]; + for(OTEscrowRecord* record in nonViable) { + if (record.viabilityStatus == OTEscrowRecord_SOSViability_SOS_VIABLE) { + [viableSOS addObject:record]; + } + } + + return viableSOS; +} + +/* + * desired outcome from filtering on an iOS/macOS platform: + * Escrow Record data validation outcome Outcome of fetch records + Octagon Viable, SOS Viable Record gets recommended, normal Octagon and SOS join + Octagon Viable, SOS Doesn't work Record gets recommended, normal Octagon join, SOS reset + Octagon Doesn't work, SOS Viable Record gets recommended, Octagon reset, normal SOS join + Octagon Doesn't work, SOS Doesn't work no records recommended. Force user to reset all protected data + + * desired outcome from filtering on an watchOS/tvOS/etc: + Escrow Record data validation outcome Outcome of fetch records + Octagon Viable, SOS Viable Record gets recommended, normal Octagon and SOS noop + Octagon Viable, SOS Doesn't work Record gets recommended, normal Octagon join, SOS noop + Octagon Doesn't work, SOS Viable Record gets recommended, Octagon reset, SOS noop + Octagon Doesn't work, SOS Doesn't work no records recommended. Force user to reset all protected data +*/ + ++ (NSArray* _Nullable)filterRecords:(NSArray*)allRecords +{ + NSMutableArray* viable = [NSMutableArray array]; + NSMutableArray* partial = [NSMutableArray array]; + NSMutableArray* nonViable = [NSMutableArray array]; + + for (OTEscrowRecord* record in allRecords) { + if(record.recordViability == OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE && + record.escrowInformationMetadata.bottleId != nil && + [record.escrowInformationMetadata.bottleId length] != 0) { + [viable addObject:record]; + } else if(record.recordViability == OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE && + record.escrowInformationMetadata.bottleId != nil && + [record.escrowInformationMetadata.bottleId length] != 0) { + [partial addObject:record]; + } else { + [nonViable addObject:record]; + } + } + + for(OTEscrowRecord* record in viable) { + secnotice("octagontrust-fetchescrowrecords", "viable record: %@ serial:%@ bottleID:%@ silent allowed:%d", + record.label, + record.escrowInformationMetadata.serial, + record.escrowInformationMetadata.bottleId, + (int)record.silentAttemptAllowed); + } + for(OTEscrowRecord* record in partial) { + secnotice("octagontrust-fetchescrowrecords", "partially viable record: %@ serial:%@ bottleID:%@ silent allowed:%d", + record.label, + record.escrowInformationMetadata.serial, + record.escrowInformationMetadata.bottleId, + (int)record.silentAttemptAllowed); + } + for(OTEscrowRecord* record in nonViable) { + secnotice("octagontrust-fetchescrowrecords", "nonviable record: %@ serial:%@ bottleID:%@ silent allowed:%d", + record.label, + record.escrowInformationMetadata.serial, + record.escrowInformationMetadata.bottleId, + (int)record.silentAttemptAllowed); + } + + if ([viable count] > 0) { + secnotice("octagontrust-fetchescrowrecords", "Returning %d viable records", (int)[viable count]); + return viable; + } + + if ([partial count] > 0) { + secnotice("octagontrust-fetchescrowrecords", "Returning %d partially viable records", (int)[partial count]); + return partial; + } + + if (OctagonPlatformSupportsSOS()) { + NSArray* viableSOSRecords = [self filterViableSOSRecords:nonViable]; + secnotice("octagontrust-fetchescrowrecords", "Returning %d sos viable records", (int)[viableSOSRecords count]); + return viableSOSRecords; + } + + secnotice("octagontrust-fetchescrowrecords", "no viable records!"); + + return nil; +} + ++ (NSArray* _Nullable)fetchAndHandleEscrowRecords:(OTConfigurationContext*)data shouldFilter:(BOOL)shouldFiler error:(NSError**)error +{ + OctagonSignpost signPost = OctagonSignpostBegin(OctagonSignpostNameFetchEscrowRecords); + bool subTaskSuccess = false; + + NSError* localError = nil; + NSArray* escrowRecordDatas = [OTClique fetchEscrowRecordsInternal:data error:&localError]; + if(localError) { + secerror("octagontrust-fetchAndHandleEscrowRecords: failed to fetch escrow records: %@", localError); + if(error){ + *error = localError; + } + OctagonSignpostEnd(signPost, OctagonSignpostNameFetchEscrowRecords, OctagonSignpostNumber1(OctagonSignpostNameFetchEscrowRecords), (int)subTaskSuccess); + return nil; + } + + NSMutableArray* escrowRecords = [NSMutableArray array]; + + for(NSData* recordData in escrowRecordDatas){ + OTEscrowRecord* translated = [[OTEscrowRecord alloc] initWithData:recordData]; + if(translated.escrowInformationMetadata.bottleValidity == nil || [translated.escrowInformationMetadata.bottleValidity isEqualToString:@""]){ + switch(translated.recordViability) { + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE: + translated.escrowInformationMetadata.bottleValidity = @"valid"; + break; + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE: + translated.escrowInformationMetadata.bottleValidity = @"valid"; + break; + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY: + translated.escrowInformationMetadata.bottleValidity = @"invalid"; + break; + } + } + if(translated.recordId == nil || [translated.recordId isEqualToString:@""]){ + translated.recordId = [[translated.label stringByReplacingOccurrencesOfString:OTEscrowRecordPrefix withString:@""] mutableCopy]; + } + if((translated.serialNumber == nil || [translated.serialNumber isEqualToString:@""]) && translated.escrowInformationMetadata.peerInfo != nil && [translated.escrowInformationMetadata.peerInfo length] > 0) { + CFErrorRef cfError = NULL; + SOSPeerInfoRef peer = SOSPeerInfoCreateFromData(kCFAllocatorDefault, &cfError, (__bridge CFDataRef)translated.escrowInformationMetadata.peerInfo); + if(cfError != NULL){ + secnotice("octagontrust-handleEscrowRecords", "failed to create sos peer info: %@", cfError); + } else { + translated.serialNumber = (NSString*)CFBridgingRelease(SOSPeerInfoCopySerialNumber(peer)); + } + } + + [escrowRecords addObject:translated]; + } + subTaskSuccess = true; + OctagonSignpostEnd(signPost, OctagonSignpostNameFetchEscrowRecords, OctagonSignpostNumber1(OctagonSignpostNameFetchEscrowRecords), (int)subTaskSuccess); + + if (shouldFiler == YES) { + return [OTClique filterRecords:escrowRecords]; + } + + return escrowRecords; +} + ++ (NSArray* _Nullable)fetchAllEscrowRecords:(OTConfigurationContext*)data error:(NSError**)error +{ +#if OCTAGON + secnotice("octagontrust-fetchallescrowrecords", "fetching all escrow records for context :%@, altdsid:%@", data.context, data.altDSID); + return [OTClique fetchAndHandleEscrowRecords:data shouldFilter:NO error:error]; +#else + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; +#endif +} + ++ (NSArray* _Nullable)fetchEscrowRecords:(OTConfigurationContext*)data error:(NSError**)error +{ +#if OCTAGON + if (OctagonIsOptimizationEnabled() && OctagonIsEscrowRecordFetchEnabled()) { + secnotice("octagontrust-fetchescrowrecords", "fetching filtered escrow records for context with feature flag enabled:%@, altdsid:%@", data.context, data.altDSID); + return [OTClique fetchAndHandleEscrowRecords:data shouldFilter:YES error:error]; + } else { + if ([OTClique isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return NULL; + } + + OctagonSignpost signPost = OctagonSignpostBegin(OctagonSignpostNameGetAccountInfo); + secnotice("octagontrust-fetchescrowrecords", "fetching escrow records for context with feature flag disabled:%@, altdsid:%@", data.context, data.altDSID); + id sb = data.sbd ?: [[getSecureBackupClass() alloc] init]; + + OTEscrowAuthenticationInformation *escrowAuth = nil; + NSDictionary* escrowAuthDictionary = nil; + if(data.escrowAuth != nil) { + escrowAuth = data.escrowAuth; + escrowAuthDictionary = [OTEscrowTranslation escrowAuthenticationInfoToDictionary:escrowAuth]; + } + NSDictionary* results = nil; + NSError* recoverError = [sb getAccountInfoWithInfo:escrowAuthDictionary results:&results]; + bool subTaskSuccess = false; + if(recoverError || results == nil) { + secerror("octagontrust-fetchescrowrecords: error fetching escrow records: %@", recoverError); + if(error){ + *error = recoverError; + } + OctagonSignpostEnd(signPost, OctagonSignpostNameGetAccountInfo, OctagonSignpostNumber1(OctagonSignpostNameGetAccountInfo), (int)subTaskSuccess); + return nil; + } else { + secnotice("octagontrust-fetchescrowrecords", "recovered accountWithInfo results: %@", results); + NSArray *icdpRecords = results[getkSecureBackupiCDPRecordsKey()]; + secnotice("octagontrust-fetchescrowrecords", "recovered iCDP records: %@", icdpRecords); + + NSMutableArray* records = [NSMutableArray array]; + for (NSDictionary *dictionaryRecord in icdpRecords) { + OTEscrowRecord* otEscrowRecord = [OTEscrowTranslation dictionaryToEscrowRecord:dictionaryRecord]; + [records addObject:otEscrowRecord]; + } + secnotice("octagontrust-fetchescrowrecords", "translated dictionary records to escrow record protos: %@", records); + + subTaskSuccess = true; + OctagonSignpostEnd(signPost, OctagonSignpostNameGetAccountInfo, OctagonSignpostNumber1(OctagonSignpostNameGetAccountInfo), (int)subTaskSuccess); + + return records; + } + } +#else + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; +#endif +} + ++ (OTClique* _Nullable)handleRecoveryResults:(OTConfigurationContext*)data recoveredInformation:(NSDictionary*)recoveredInformation sosViability:(OTEscrowRecord_SOSViability)sosViability performedSilentBurn:(BOOL)performedSilentBurn recoverError:(NSError*)recoverError error:(NSError**)error +{ + if ([self isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; + } + + OTClique* clique = [[OTClique alloc] initWithContextData:data]; + BOOL resetToOfferingOccured = NO; + + if(recoverError) { + secnotice("octagontrust-handleRecoveryResults", "sbd escrow recovery failed: %@", recoverError); + if(recoverError.code == 40 /* kSecureBackupRestoringLegacyBackupKeychainError */ && [recoverError.domain isEqualToString:getkSecureBackupErrorDomain()]) { + if([OTClique platformSupportsSOS]) { + secnotice("octagontrust-handleRecoveryResults", "Can't restore legacy backup with no keybag. Resetting SOS to offering"); + CFErrorRef resetToOfferingError = NULL; + bool successfulReset = SOSCCResetToOffering(&resetToOfferingError); + resetToOfferingOccured = YES; + if(!successfulReset || resetToOfferingError) { + secerror("octagontrust-handleRecoveryResults: failed to reset to offering:%@", resetToOfferingError); + } else { + secnotice("octagontrust-handleRecoveryResults", "resetting SOS circle successful"); + } + CFReleaseNull(resetToOfferingError); + } else { + secnotice("octagontrust-handleRecoveryResults", "Legacy restore failed on a non-SOS platform"); + } + } else { + if(error) { + *error = recoverError; + } + return nil; + } + } + + NSError* localError = nil; + OTControl* control = nil; + + if (data.otControl) { + control = data.otControl; + } else { + control = [data makeOTControl:&localError]; + } + if (!control) { + secerror("octagontrust-handleRecoveryResults: unable to create otcontrol: %@", localError); + if (error) { + *error = localError; + } + return nil; + } + + // look for OT Bottles + NSString *bottleID = recoveredInformation[@"bottleID"]; + NSString *isValid = recoveredInformation[@"bottleValid"]; + NSData *bottledPeerEntropy = recoveredInformation[@"EscrowServiceEscrowData"][@"BottledPeerEntropy"]; + bool shouldResetOctagon = false; + + if(bottledPeerEntropy && bottleID && [isValid isEqualToString:@"valid"]){ + secnotice("octagontrust-handleRecoveryResults", "recovering from bottle: %@", bottleID); + __block NSError* restoreBottleError = nil; + OctagonSignpost bottleRestoreSignPost = performedSilentBurn ? OctagonSignpostBegin(OctagonSignpostNamePerformOctagonJoinForSilent) : OctagonSignpostBegin(OctagonSignpostNamePerformOctagonJoinForNonSilent); + + //restore bottle! + [control restore:OTCKContainerName + contextID:data.context + bottleSalt:data.altDSID + entropy:bottledPeerEntropy + bottleID:bottleID + reply:^(NSError * _Nullable restoreError) { + if(restoreError) { + secnotice("octagontrust-handleRecoveryResults", "restore bottle errored: %@", restoreError); + } else { + secnotice("octagontrust-handleRecoveryResults", "restoring bottle succeeded"); + } + restoreBottleError = restoreError; + if (performedSilentBurn) { + OctagonSignpostEnd(bottleRestoreSignPost, OctagonSignpostNamePerformOctagonJoinForSilent, OctagonSignpostNumber1(OctagonSignpostNamePerformOctagonJoinForSilent), (int)true); + } else { + OctagonSignpostEnd(bottleRestoreSignPost, OctagonSignpostNamePerformOctagonJoinForNonSilent, OctagonSignpostNumber1(OctagonSignpostNamePerformOctagonJoinForNonSilent), (int)true); + } + }]; + + if(restoreBottleError) { + if(error){ + *error = restoreBottleError; + } + return nil; + } + } else { + shouldResetOctagon = true; + } + + if(shouldResetOctagon) { + secnotice("octagontrust-handleRecoveryResults", "bottle %@ is not valid, resetting octagon", bottleID); + NSError* resetError = nil; + [clique resetAndEstablish:CuttlefishResetReasonNoBottleDuringEscrowRecovery error:&resetError]; + if(resetError) { + secerror("octagontrust-handleRecoveryResults: failed to reset octagon: %@", resetError); + if(error){ + *error = resetError; + } + return nil; + } else{ + secnotice("octagontrust-handleRecoveryResults", "reset octagon succeeded"); + } + } + + // Join SOS circle if platform is supported and we didn't previously reset SOS + if (OctagonPlatformSupportsSOS() && resetToOfferingOccured == NO) { + if (sosViability == OTEscrowRecord_SOSViability_SOS_NOT_VIABLE) { + secnotice("octagontrust-handleRecoveryResults", "Record will not allow device to join SOS. Invoking reset to offering"); + CFErrorRef resetToOfferingError = NULL; + bool successfulReset = SOSCCResetToOffering(&resetToOfferingError); + if(!successfulReset || resetToOfferingError) { + secerror("octagontrust-handleRecoveryResults: failed to reset to offering:%@", resetToOfferingError); + } else { + secnotice("octagontrust-handleRecoveryResults", "resetting SOS circle successful"); + } + CFReleaseNull(resetToOfferingError); + } else { + NSError* joinAfterRestoreError = nil; + secnotice("octagontrust-handleRecoveryResults", "attempting joinAfterRestore"); + BOOL joinAfterRestoreResult = [clique joinAfterRestore:&joinAfterRestoreError]; + if(joinAfterRestoreError || joinAfterRestoreResult == NO) { + secnotice("octagontrust-handleRecoveryResults", "failed to join after restore: %@", joinAfterRestoreError); + } else { + secnotice("octagontrust-handleRecoveryResults", "joinAfterRestore succeeded"); + } + } + } + + + // call SBD to kick off keychain data restore + id sb = data.sbd ?: [[getSecureBackupClass() alloc] init]; + NSError* restoreError = nil; + + NSMutableSet *viewsNotToBeRestored = [NSMutableSet set]; + [viewsNotToBeRestored addObject:@"iCloudIdentity"]; + [viewsNotToBeRestored addObject:@"PCS-MasterKey"]; + [viewsNotToBeRestored addObject:@"KeychainV0"]; + + NSDictionary *escrowRecords = recoveredInformation[getkEscrowServiceRecordDataKey()]; + if (escrowRecords == nil) { + secnotice("octagontrust-handleRecoveryResults", "unable to request keychain restore, record data missing"); + return clique; + } + + + NSData *keybagDigest = escrowRecords[getkSecureBackupKeybagDigestKey()]; + NSData *password = escrowRecords[getkSecureBackupBagPasswordKey()]; + if (keybagDigest == nil || password == nil) { + secnotice("octagontrust-handleRecoveryResults", "unable to request keychain restore, digest or password missing"); + return clique; + } + + BOOL haveBottledPeer = (bottledPeerEntropy && bottleID && [isValid isEqualToString:@"valid"]) || shouldResetOctagon; + [sb restoreKeychainAsyncWithPassword:password + keybagDigest:keybagDigest + haveBottledPeer:haveBottledPeer + viewsNotToBeRestored:viewsNotToBeRestored + error:&restoreError]; + + if (restoreError) { + secerror("octagontrust-handleRecoveryResults: error restoring keychain items: %@", restoreError); + } + + return clique; +} + ++ (instancetype _Nullable)performEscrowRecovery:(OTConfigurationContext*)data + cdpContext:(OTICDPRecordContext*)cdpContext + escrowRecord:(OTEscrowRecord*)escrowRecord + error:(NSError**)error +{ +#if OCTAGON + secnotice("octagontrust-performEscrowRecovery", "performEscrowRecovery invoked for context:%@, altdsid:%@", data.context, data.altDSID); + + if ([self isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; + } + + OctagonSignpost performEscrowRecoverySignpost = OctagonSignpostBegin(OctagonSignpostNamePerformEscrowRecovery); + bool subTaskSuccess = true; + + id sb = data.sbd ?: [[getSecureBackupClass() alloc] init]; + NSDictionary* recoveredInformation = nil; + NSError* recoverError = nil; + + BOOL supportedRestorePath = [OTEscrowTranslation supportedRestorePath:cdpContext]; + secnotice("octagontrust-performEscrowRecovery", "restore path is supported? %@", supportedRestorePath ? @"YES" : @"NO"); + + if (OctagonIsOptimizationEnabled() && supportedRestorePath) { + secnotice("octagontrust-performEscrowRecovery", "optimization flag turned on"); + OctagonSignpost recoverFromSBDSignPost = OctagonSignpostBegin(OctagonSignpostNameRecoverWithCDPContext); + recoveredInformation = [sb recoverWithCDPContext:cdpContext escrowRecord:escrowRecord error:&recoverError]; + subTaskSuccess = (recoverError == nil) ? true : false; + OctagonSignpostEnd(recoverFromSBDSignPost, OctagonSignpostNameRecoverWithCDPContext, OctagonSignpostNumber1(OctagonSignpostNameRecoverWithCDPContext), (int)subTaskSuccess); + } else { + secnotice("octagontrust-performEscrowRecovery", "optimization flag turned off"); + NSMutableDictionary* sbdRecoveryArguments = [[OTEscrowTranslation CDPRecordContextToDictionary:cdpContext] mutableCopy]; + NSDictionary* metadata = [OTEscrowTranslation metadataToDictionary:escrowRecord.escrowInformationMetadata]; + sbdRecoveryArguments[getkSecureBackupMetadataKey()] = metadata; + sbdRecoveryArguments[getkSecureBackupRecordIDKey()] = escrowRecord.recordId; + secnotice("octagontrust-performEscrowRecovery", "using sbdRecoveryArguments: %@", sbdRecoveryArguments); + + OctagonSignpost recoverFromSBDSignPost = OctagonSignpostBegin(OctagonSignpostNamePerformRecoveryFromSBD); + recoverError = [sb recoverWithInfo:sbdRecoveryArguments results:&recoveredInformation]; + subTaskSuccess = (recoverError == nil) ? true : false; + OctagonSignpostEnd(recoverFromSBDSignPost, OctagonSignpostNamePerformRecoveryFromSBD, OctagonSignpostNumber1(OctagonSignpostNamePerformRecoveryFromSBD), (int)subTaskSuccess); + } + + OTEscrowRecord_SOSViability viableForSOS = escrowRecord.viabilityStatus; + + OTClique* clique = [OTClique handleRecoveryResults:data recoveredInformation:recoveredInformation sosViability:viableForSOS performedSilentBurn:NO recoverError:recoverError error:error]; + + if(recoverError) { + subTaskSuccess = false; + OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNamePerformEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformEscrowRecovery), (int)subTaskSuccess); + } else { + OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNamePerformEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformEscrowRecovery), (int)subTaskSuccess); + } + return clique; + +#else + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; +#endif +} + ++ (OTEscrowRecord* _Nullable) recordMatchingLabel:(NSString*)label allRecords:(NSArray*)allRecords +{ + for(OTEscrowRecord* record in allRecords) { + if ([record.label isEqualToString:label]) { + return record; + } + } + return nil; +} + ++ (instancetype _Nullable)performSilentEscrowRecovery:(OTConfigurationContext*)data + cdpContext:(OTICDPRecordContext*)cdpContext + allRecords:(NSArray*)allRecords + error:(NSError**)error +{ +#if OCTAGON + secnotice("octagontrust-performSilentEscrowRecovery", "performSilentEscrowRecovery invoked for context:%@, altdsid:%@", data.context, data.altDSID); + + if ([self isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; + } + + OctagonSignpost performSilentEscrowRecoverySignpost = OctagonSignpostBegin(OctagonSignpostNamePerformSilentEscrowRecovery); + bool subTaskSuccess = true; + + id sb = data.sbd ?: [[getSecureBackupClass() alloc] init]; + NSDictionary* recoveredInformation = nil; + NSError* recoverError = nil; + + BOOL supportedRestorePath = [OTEscrowTranslation supportedRestorePath:cdpContext]; + secnotice("octagontrust-performSilentEscrowRecovery", "restore path is supported? %@", supportedRestorePath ? @"YES" : @"NO"); + + if (OctagonIsOptimizationEnabled() && supportedRestorePath) { + secnotice("octagontrust-performSilentEscrowRecovery", "optimization flag turned on"); + OctagonSignpost recoverFromSBDSignPost = OctagonSignpostBegin(OctagonSignpostNameRecoverSilentWithCDPContext); + recoveredInformation = [sb recoverSilentWithCDPContext:cdpContext allRecords:allRecords error:&recoverError]; + subTaskSuccess = (recoverError == nil) ? true : false; + OctagonSignpostEnd(recoverFromSBDSignPost, OctagonSignpostNameRecoverSilentWithCDPContext, OctagonSignpostNumber1(OctagonSignpostNameRecoverSilentWithCDPContext), (int)subTaskSuccess); + } else { + secnotice("octagontrust-performSilentEscrowRecovery", "optimization flag turned off"); + NSDictionary* sbdRecoveryArguments = [OTEscrowTranslation CDPRecordContextToDictionary:cdpContext]; + + OctagonSignpost recoverFromSBDSignPost = OctagonSignpostBegin(OctagonSignpostNamePerformRecoveryFromSBD); + recoverError = [sb recoverWithInfo:sbdRecoveryArguments results:&recoveredInformation]; + subTaskSuccess = (recoverError == nil) ? true : false; + OctagonSignpostEnd(recoverFromSBDSignPost, OctagonSignpostNamePerformRecoveryFromSBD, OctagonSignpostNumber1(OctagonSignpostNamePerformRecoveryFromSBD), (int)subTaskSuccess); + } + + NSString* label = recoveredInformation[getkSecureBackupRecordLabelKey()]; + OTEscrowRecord* chosenRecord = [OTClique recordMatchingLabel:label allRecords:allRecords]; + OTEscrowRecord_SOSViability viableForSOS = chosenRecord ? chosenRecord.viabilityStatus : OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN; + + OTClique *clique = [OTClique handleRecoveryResults:data recoveredInformation:recoveredInformation sosViability:viableForSOS performedSilentBurn:YES recoverError:recoverError error:error]; + + if(recoverError) { + subTaskSuccess = false; + OctagonSignpostEnd(performSilentEscrowRecoverySignpost, OctagonSignpostNamePerformSilentEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformSilentEscrowRecovery), (int)subTaskSuccess); + } else { + OctagonSignpostEnd(performSilentEscrowRecoverySignpost, OctagonSignpostNamePerformSilentEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformSilentEscrowRecovery), (int)subTaskSuccess); + } + + return clique; + +#else + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; +#endif +} + ++ (BOOL) invalidateEscrowCache:(OTConfigurationContext*)configurationContext error:(NSError**)error +{ +#if OCTAGON + secnotice("octagontrust-invalidateEscrowCache", "invalidateEscrowCache invoked for context:%@, altdsid:%@", configurationContext.context, configurationContext.altDSID); + __block NSError* localError = nil; + __block BOOL invalidatedCache = NO; + + OTControl *control = [configurationContext makeOTControl:&localError]; + if (!control) { + secnotice("clique-invalidateEscrowCache", "unable to create otcontrol: %@", localError); + if (error) { + *error = localError; + } + return invalidatedCache; + } + + [control invalidateEscrowCache:OTCKContainerName + contextID:configurationContext.context + reply:^(NSError * _Nullable invalidateError) { + if(invalidateError) { + secnotice("clique-invalidateEscrowCache", "invalidateEscrowCache errored: %@", invalidateError); + } else { + secnotice("clique-invalidateEscrowCache", "invalidateEscrowCache succeeded"); + invalidatedCache = YES; + } + localError = invalidateError; + }]; + + if(error && localError) { + *error = localError; + } + + secnotice("clique-invalidateEscrowCache", "invalidateEscrowCache complete"); + + return invalidatedCache; +#else + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return NO; +#endif +} + +@end + +#endif diff --git a/keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h b/keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h new file mode 100644 index 00000000..1bd22615 --- /dev/null +++ b/keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h @@ -0,0 +1,27 @@ + +#if OCTAGON + +#ifndef OctagonTrustEscrowRecoverer_h +#define OctagonTrustEscrowRecoverer_h + +@protocol OctagonEscrowRecovererPrococol +- (NSError*)recoverWithInfo:(NSDictionary*)info results:(NSDictionary**)results; +- (NSError *)getAccountInfoWithInfo:(NSDictionary *)info results:(NSDictionary**)results; +- (NSError *)disableWithInfo:(NSDictionary *)info; +- (NSDictionary*)recoverWithCDPContext:(OTICDPRecordContext*)cdpContext + escrowRecord:(OTEscrowRecord*)escrowRecord + error:(NSError**)error; +- (NSDictionary*)recoverSilentWithCDPContext:(OTICDPRecordContext*)cdpContext + allRecords:(NSArray*)allRecords + error:(NSError**)error; +- (void)restoreKeychainAsyncWithPassword:password + keybagDigest:(NSData *)keybagDigest + haveBottledPeer:(BOOL)haveBottledPeer + viewsNotToBeRestored:(NSMutableSet *)viewsNotToBeRestored + error:(NSError **)error; + +@end + +#endif /* OctagonTrustEscrowRecoverer_h */ + +#endif // OCTAGON diff --git a/keychain/OctagonTrust/ot-tests/OctagonTrustTests+Errors.m b/keychain/OctagonTrust/ot-tests/OctagonTrustTests+Errors.m new file mode 100644 index 00000000..baf22123 --- /dev/null +++ b/keychain/OctagonTrust/ot-tests/OctagonTrustTests+Errors.m @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2020 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@ + */ + +#import +#import "OctagonTrustTests.h" + +#if OCTAGON + +NS_ASSUME_NONNULL_BEGIN + + +@implementation OctagonTrustTests (OctagonTrustTestsErrors) +- (void) testDepthCountOnErrors +{ + SecErrorSetOverrideNestedErrorCappingIsEnabled(true); + //previousError == nil case + CFErrorRef errorWithoutPreviousSet = NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, &errorWithoutPreviousSet, NULL, CFSTR("no previous error")); + XCTAssertNotNil((__bridge NSError*) errorWithoutPreviousSet, "errorWithoutPreviousSet should not be nil"); + NSDictionary *userInfo = [(__bridge NSError*)errorWithoutPreviousSet userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + NSNumber *depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 0, "depth should be 0"); + + //previousError is set with a depth of 0 + CFErrorRef newError = NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, errorWithoutPreviousSet, &newError, NULL, CFSTR("previousError exists!")); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 1, "depth should be 1"); + + //previousError is set with a dpeth of 1 + CFErrorRef secondError = NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, newError, &secondError, NULL, CFSTR("using previous error that already has a chain")); + XCTAssertNotNil((__bridge NSError*) secondError, "secondError should not be nil"); + userInfo = [(__bridge NSError*)secondError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 2, "depth should be 2"); +} +- (void) testErrorCap +{ + SecErrorSetOverrideNestedErrorCappingIsEnabled(true); + //previousError == nil case + CFErrorRef previous= NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, &previous, NULL, CFSTR("no previous error")); + XCTAssertNotNil((__bridge NSError*) previous, "errorWithoutPreviousSet should not be nil"); + NSDictionary *userInfo = [(__bridge NSError*)previous userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + NSNumber *depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 0, "depth should be 0"); + + //stay within the cap limit + CFErrorRef newError = NULL; + for(int i = 0; i<200; i++) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("previousError exists %d!"), i); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], i+1, "depth should be i+1"); + previous = newError; + newError = nil; + } + + //now blow the cap limit + previous = NULL; + newError = NULL; + int depthCounter = 0; + + for(int i = 0; i < 500; i++) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("previousError exists %d!"), i); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + if (i >= 201) { + NSDictionary* previousUserInfo = [(__bridge NSError*)previous userInfo]; + NSDictionary* newErrorUserInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertTrue([previousUserInfo isEqualToDictionary:newErrorUserInfo], "newError should equal previous error"); + } + + if (i <= 199) { + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], depthCounter, "depth should be %d", depthCounter); + depthCounter++; + } else { + userInfo = [(__bridge NSError*)newError userInfo]; + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 200, "depth should be 200"); + } + + previous = newError; + newError = nil; + } +} + +- (void) testErrorCapWithFeatureFlagDisable +{ + SecErrorSetOverrideNestedErrorCappingIsEnabled(false); + //previousError == nil case + CFErrorRef previous= NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, &previous, NULL, CFSTR("no previous error")); + XCTAssertNotNil((__bridge NSError*) previous, "errorWithoutPreviousSet should not be nil"); + NSDictionary *userInfo = [(__bridge NSError*)previous userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + NSNumber *depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 0, "depth should be 0"); + + //stay within the cap limit + CFErrorRef newError = NULL; + for(int i = 0; i<200; i++) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("previousError exists %d!"), i); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], i+1, "depth should be i+1"); + previous = newError; + newError = nil; + } + + //now blow the cap limit + previous = NULL; + newError = NULL; + + for(int i = 0; i < 500; i++) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("previousError exists %d!"), i); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], i, "depth should be %d", i); + previous = newError; + newError = nil; + } +} + +- (void) testNestedErrorCreationUsingSameErrorParameters +{ + SecErrorSetOverrideNestedErrorCappingIsEnabled(true); + //previousError == nil case + CFErrorRef previous= NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, &previous, NULL, CFSTR("no previous error")); + XCTAssertNotNil((__bridge NSError*) previous, "previous should not be nil"); + NSDictionary *userInfo = [(__bridge NSError*)previous userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + NSNumber *depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 0, "depth should be 0"); + + //now pass the exact same error + CFErrorRef newError = NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("no previous error")); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 0, "depth should be 0"); + + previous = newError; + newError = NULL; + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("no previous error1")); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 1, "depth should be 1"); + + previous = newError; + newError = NULL; + for(int i = 0; i < 500; i++) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, previous, &newError, NULL, CFSTR("no previous error1")); + XCTAssertNotNil((__bridge NSError*) newError, "newError should not be nil"); + userInfo = [(__bridge NSError*)newError userInfo]; + XCTAssertNotNil(userInfo, "userInfo should not be nil"); + depth = userInfo[@"numberOfErrorsDeep"]; + XCTAssertNotNil(depth, "depth should not be nil"); + XCTAssertEqual([depth longValue], 1, "depth should be 1"); + previous = newError; + newError = nil; + } +} + +@end +NS_ASSUME_NONNULL_END + +#endif diff --git a/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowRecords.m b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowRecords.m new file mode 100644 index 00000000..0f7fb0b3 --- /dev/null +++ b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowRecords.m @@ -0,0 +1,722 @@ +/* +* Copyright (c) 2020 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@ +*/ + + +#import +#import + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" +#import +#pragma clang diagnostic pop + +#import +#import "OctagonTrustTests-EscrowTestVectors.h" + +#import "keychain/ot/OTConstants.h" +#import "keychain/ot/OTManager.h" +#import "keychain/ot/OTDefines.h" +#import "keychain/ot/OTClique+Private.h" + +#import "keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h" + +#import + +#import "keychain/ckks/tests/MockCloudKit.h" +#import "keychain/ckks/tests/CKKSMockSOSPresentAdapter.h" +#import "utilities/SecCFError.h" +#import "keychain/categories/NSError+UsefulConstructors.h" + +#import "OctagonTrustTests.h" + +@implementation ProxyXPCConnection + +- (instancetype)initWithInterface:(NSXPCInterface*)interface obj:(id)obj +{ + if(self = [super init]) { + self.obj = obj; + self.serverInterface = interface; + self.listener = [NSXPCListener anonymousListener]; + + self.listener.delegate = self; + [self.listener resume]; + } + + return self; +} + +- (NSXPCConnection*)connection +{ + NSXPCConnection* connection = [[NSXPCConnection alloc] initWithListenerEndpoint:self.listener.endpoint]; + connection.remoteObjectInterface = self.serverInterface; + [connection resume]; + return connection; +} + +- (BOOL)listener:(NSXPCListener*)listener newConnection:(NSXPCConnection*)newConnection { + newConnection.exportedInterface = self.serverInterface; + newConnection.exportedObject = self.obj; + [newConnection resume]; + return true; + } + +@end + +@interface FakeOTControlEntitlementBearer : NSObject +@property NSMutableDictionary* entitlements; +-(instancetype)init; +- (nullable id)valueForEntitlement:(NSString *)entitlement; +@end + +@implementation FakeOTControlEntitlementBearer + +-(instancetype)init +{ + if(self = [super init]) { + self.entitlements = [NSMutableDictionary dictionary]; + self.entitlements[kSecEntitlementPrivateOctagonEscrow] = @YES; + } + return self; +} +-(id)valueForEntitlement:(NSString*)entitlement +{ + return self.entitlements[entitlement]; +} + +@end + +@interface OTMockSecureBackup : NSObject +@property (nonatomic) NSString * bottleID; +@property (nonatomic) NSData* entropy; + +@end + +@implementation OTMockSecureBackup + +-(instancetype) initWithBottleID:(NSString*)b entropy:(NSData*)e { + if(self = [super init]) { + self.bottleID = b; + self.entropy = e; + } + return self; +} + +- (NSError *)disableWithInfo:(NSDictionary *)info { + return nil; +} + +- (NSError *)getAccountInfoWithInfo:(NSDictionary *)info results:(NSDictionary *__autoreleasing *)results { + NSError* localError = nil; + NSData *testVectorData = [accountInfoWithInfoSample dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localError]; + *results = testVectorPlist; + + return nil; +} + +- (NSDictionary *)recoverSilentWithCDPContext:(OTICDPRecordContext *)cdpContext allRecords:(NSArray *)allRecords error:(NSError *__autoreleasing *)error { + return nil; +} + +- (NSDictionary *)recoverWithCDPContext:(OTICDPRecordContext *)cdpContext escrowRecord:(OTEscrowRecord *)escrowRecord error:(NSError *__autoreleasing *)error { + return nil; +} + +- (NSError *)recoverWithInfo:(NSDictionary *)info results:(NSDictionary *__autoreleasing *)results { + return nil; +} + +- (void)restoreKeychainAsyncWithPassword:(id)password keybagDigest:(NSData *)keybagDigest haveBottledPeer:(BOOL)haveBottledPeer viewsNotToBeRestored:(NSMutableSet *)viewsNotToBeRestored error:(NSError *__autoreleasing *)error { +} + + +@end + +@implementation OctagonTrustTests + +- (OTEscrowRecord*)createLegacyRecord +{ + OTEscrowRecord *nonViableRecord = [[OTEscrowRecord alloc] init]; + nonViableRecord.creationDate = [NSDate date].timeIntervalSince1970; + nonViableRecord.label = [[NSUUID UUID] UUIDString]; + nonViableRecord.recordStatus = OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + nonViableRecord.recordViability = OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY; + nonViableRecord.serialNumber = [[NSUUID UUID] UUIDString]; + nonViableRecord.silentAttemptAllowed = 1; + nonViableRecord.escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + nonViableRecord.escrowInformationMetadata.bottleValidity = @"invalid"; + + // It even has a bottleId! Not a useful one, though. + nonViableRecord.escrowInformationMetadata.bottleId = [[NSUUID UUID] UUIDString]; + return nonViableRecord; +} + +- (OTEscrowRecord*)createLegacyRecordWithSOSNotViable +{ + OTEscrowRecord *nonViableRecord = [[OTEscrowRecord alloc] init]; + nonViableRecord.creationDate = [NSDate date].timeIntervalSince1970; + nonViableRecord.label = [[NSUUID UUID] UUIDString]; + nonViableRecord.recordStatus = OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + nonViableRecord.recordViability = OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY; + nonViableRecord.viabilityStatus = OTEscrowRecord_SOSViability_SOS_NOT_VIABLE; + nonViableRecord.serialNumber = [[NSUUID UUID] UUIDString]; + nonViableRecord.silentAttemptAllowed = 1; + nonViableRecord.escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + nonViableRecord.escrowInformationMetadata.bottleValidity = @"invalid"; + + // It even has a bottleId! Not a useful one, though. + nonViableRecord.escrowInformationMetadata.bottleId = [[NSUUID UUID] UUIDString]; + return nonViableRecord; +} + +- (OTEscrowRecord*)createPartialRecord +{ + OTEscrowRecord *partiallyViableRecord = [[OTEscrowRecord alloc] init]; + partiallyViableRecord.creationDate = [NSDate date].timeIntervalSince1970; + partiallyViableRecord.label = [[NSUUID UUID] UUIDString]; + partiallyViableRecord.recordStatus = OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + partiallyViableRecord.recordViability = OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE; + partiallyViableRecord.escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + partiallyViableRecord.escrowInformationMetadata.bottleValidity = @"valid"; + partiallyViableRecord.escrowInformationMetadata.bottleId = [[NSUUID UUID] UUIDString]; + + partiallyViableRecord.serialNumber =[[NSUUID UUID] UUIDString]; + partiallyViableRecord.silentAttemptAllowed = 1; + return partiallyViableRecord; +} + +- (OTEscrowRecord*)createOctagonViableSOSViableRecord +{ + OTEscrowRecord *octagonAndSOSViableRecord = [[OTEscrowRecord alloc] init]; + octagonAndSOSViableRecord.creationDate = [NSDate date].timeIntervalSince1970; + octagonAndSOSViableRecord.label = [[NSUUID UUID] UUIDString]; + octagonAndSOSViableRecord.recordStatus = OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + octagonAndSOSViableRecord.recordViability = OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE; + octagonAndSOSViableRecord.viabilityStatus = OTEscrowRecord_SOSViability_SOS_VIABLE; + + octagonAndSOSViableRecord.escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + octagonAndSOSViableRecord.escrowInformationMetadata.bottleValidity = @"valid"; + octagonAndSOSViableRecord.escrowInformationMetadata.bottleId = [[NSUUID UUID] UUIDString]; + + octagonAndSOSViableRecord.serialNumber =[[NSUUID UUID] UUIDString]; + octagonAndSOSViableRecord.silentAttemptAllowed = 1; + return octagonAndSOSViableRecord; +} + +- (OTEscrowRecord*)createOctagonNotViableSOSViableRecord +{ + OTEscrowRecord *octagonAndSOSViableRecord = [[OTEscrowRecord alloc] init]; + octagonAndSOSViableRecord.creationDate = [NSDate date].timeIntervalSince1970; + octagonAndSOSViableRecord.label = [[NSUUID UUID] UUIDString]; + octagonAndSOSViableRecord.recordStatus = OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + octagonAndSOSViableRecord.recordViability = OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY; + octagonAndSOSViableRecord.viabilityStatus = OTEscrowRecord_SOSViability_SOS_VIABLE; + + octagonAndSOSViableRecord.escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + octagonAndSOSViableRecord.escrowInformationMetadata.bottleValidity = @"invalid"; + octagonAndSOSViableRecord.escrowInformationMetadata.bottleId = [[NSUUID UUID] UUIDString]; + + octagonAndSOSViableRecord.serialNumber =[[NSUUID UUID] UUIDString]; + octagonAndSOSViableRecord.silentAttemptAllowed = 1; + return octagonAndSOSViableRecord; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnOneRecord:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + NSError* localError = nil; + NSData *testVectorData = [accountInfoWithInfoSample dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localError]; + + NSArray *testVectorICDPRecords = testVectorPlist[@"SecureBackupAlliCDPRecords"]; + XCTAssertNotNil(testVectorICDPRecords, "should not be nil"); + + NSDictionary *testVectorRecord = testVectorICDPRecords[0]; + + OTEscrowRecord *record = [OTEscrowTranslation dictionaryToEscrowRecord:testVectorRecord]; + + NSArray *records = @[record.data]; + return records; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnMixedRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + NSError* localError = nil; + NSData *testVectorData = [accountInfoWithInfoSample dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localError]; + + NSArray *testVectorICDPRecords = testVectorPlist[@"SecureBackupAlliCDPRecords"]; + XCTAssertNotNil(testVectorICDPRecords, "should not be nil"); + + NSDictionary *testVectorRecord = testVectorICDPRecords[0]; + + OTEscrowRecord *record = [OTEscrowTranslation dictionaryToEscrowRecord:testVectorRecord]; + + NSArray *records = @[record.data, [self createLegacyRecord].data, [self createLegacyRecord].data]; + return records; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnPartiallyViableRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + return @[[self createPartialRecord].data, [self createPartialRecord].data]; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnOctagonViableSOSViableRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + return @[[self createOctagonViableSOSViableRecord].data, [self createOctagonViableSOSViableRecord].data]; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnLegacyRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + return @[[self createLegacyRecord].data, [self createLegacyRecord].data]; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnLegacyNonViableSOSRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + return @[[self createLegacyRecordWithSOSNotViable].data, [self createLegacyRecordWithSOSNotViable].data]; +} + +- (NSArray* _Nullable)mockFetchEscrowRecordsInternalReturnOctagonNotViableSOSViableRecords:(OTConfigurationContext*)data + error:(NSError* __autoreleasing *)error +{ + return @[[self createOctagonNotViableSOSViableRecord].data, [self createOctagonNotViableSOSViableRecord].data]; +} + +- (void)setUp +{ + [super setUp]; + + FakeOTControlEntitlementBearer *otControlEntitlementBearer = [[FakeOTControlEntitlementBearer alloc]init]; + id otControlEntitlementChecker = [OctagonXPCEntitlementChecker createWithManager:self.injectedOTManager entitlementBearer:otControlEntitlementBearer]; + + NSXPCInterface *interface = OTSetupControlProtocol([NSXPCInterface interfaceWithProtocol:@protocol(OTControlProtocol)]); + self.otXPCProxy = [[ProxyXPCConnection alloc] initWithInterface:interface obj: otControlEntitlementChecker]; + + self.otControl = [[OTControl alloc] initWithConnection:self.otXPCProxy.connection sync: true]; + + self.mockClique = OCMClassMock([OTClique class]); +} + +- (void)testFetchOneViableEscrowRecord +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnOneRecord:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 1, "should only return 1 record"); + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.label isEqualToString:@"com.apple.icdp.record"], "label should be com.apple.icdp.record"); + XCTAssertTrue([firstRecord.serialNumber isEqualToString:@"C39V209AJ9L5"], "serial number should be C39V209AJ9L5"); + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE, "record viability should be fully viable"); +} + +- (void)testFetchTwoPartiallyViableEscrowRecords +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnPartiallyViableRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 2, "should only return 2 records"); + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE, "record viability should be partial"); + + OTEscrowRecord *secondRecord = escrowRecords[1]; + XCTAssertTrue([secondRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(secondRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE, "record viability should be partial"); +} + +- (void)testFetchViableAndLegacyEscrowRecords +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnMixedRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertEqual(escrowRecords.count, 1, "should only return 1 record"); + XCTAssertNil(localErrror, "error should be nil"); + + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.label isEqualToString:@"com.apple.icdp.record"], "label should be com.apple.icdp.record"); + XCTAssertTrue([firstRecord.serialNumber isEqualToString:@"C39V209AJ9L5"], "serial number should be C39V209AJ9L5"); + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE, "record viability should be fully viable"); +} + +- (void)testFetchLegacyEscrowRecords +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnLegacyRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertEqual(escrowRecords.count, 0, "should return zero records"); + XCTAssertNil(localErrror, "error should be nil"); +} + +- (void)testFetchRecordsOctagonViableSOSUnknownViability +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnOneRecord:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 1, "should only return 1 record"); + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.label isEqualToString:@"com.apple.icdp.record"], "label should be com.apple.icdp.record"); + XCTAssertTrue([firstRecord.serialNumber isEqualToString:@"C39V209AJ9L5"], "serial number should be C39V209AJ9L5"); + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE, "record viability should be fully viable"); + XCTAssertEqual(firstRecord.viabilityStatus, OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN, "record SOS viability should be unknown"); +} + +- (void)testFetchRecordsOctagonViableSOSViable +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnOctagonViableSOSViableRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 2, "should only return 2 records"); + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE, "record viability should be fully viable"); + XCTAssertEqual(firstRecord.viabilityStatus, OTEscrowRecord_SOSViability_SOS_VIABLE, "record sos viability should be fully viable"); + + OTEscrowRecord *secondRecord = escrowRecords[1]; + XCTAssertTrue([secondRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"valid"], "bottle validity should be valid"); + XCTAssertEqual(secondRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE, "record viability should be fully viable"); + XCTAssertEqual(secondRecord.viabilityStatus, OTEscrowRecord_SOSViability_SOS_VIABLE, "record sos viability should be fully viable"); +} + +- (void)testFetchRecordsOctagonNotViableSOSViable +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnOctagonNotViableSOSViableRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + if (OctagonPlatformSupportsSOS()) { + XCTAssertEqual(escrowRecords.count, 2, "should only return 2 records"); + OTEscrowRecord *firstRecord = escrowRecords[0]; + XCTAssertTrue([firstRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"invalid"], "bottle validity should be invalid"); + XCTAssertEqual(firstRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY, "record viability should be set to legacy"); + XCTAssertEqual(firstRecord.viabilityStatus, OTEscrowRecord_SOSViability_SOS_VIABLE, "record sos viability should be fully viable"); + + OTEscrowRecord *secondRecord = escrowRecords[1]; + XCTAssertTrue([secondRecord.escrowInformationMetadata.bottleValidity isEqualToString: @"invalid"], "bottle validity should be invalid"); + XCTAssertEqual(secondRecord.recordViability, OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY, "record viability should be set to legacy"); + XCTAssertEqual(secondRecord.viabilityStatus, OTEscrowRecord_SOSViability_SOS_VIABLE, "record sos viability should be fully viable"); + } else { + XCTAssertEqual(escrowRecords.count, 0, "should return 0 records"); + + } +} + +- (void)testFetchRecordsOctagonNotViableSOSNotViable +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnLegacyNonViableSOSRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 0, "should return 0 records"); +} + +- (void)testFetchAllRecords +{ + OctagonSetOptimizationEnabled(true); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.otControl = self.otControl; + + OCMStub([self.mockClique fetchEscrowRecordsInternal:[OCMArg any] error:[OCMArg anyObjectRef]]).andCall(self, @selector(mockFetchEscrowRecordsInternalReturnLegacyNonViableSOSRecords:error:)); + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchAllEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + + XCTAssertEqual(escrowRecords.count, 2, "should return 2 records"); +} + +- (void)testFetchEscrowRecordOptimizationOff +{ + OctagonSetOptimizationEnabled(false); + + OTConfigurationContext *cliqueContextConfiguration = [[OTConfigurationContext alloc]init]; + cliqueContextConfiguration.context = OTDefaultContext; + cliqueContextConfiguration.dsid = @"1234"; + cliqueContextConfiguration.altDSID = @"altdsid"; + cliqueContextConfiguration.sbd = [[OTMockSecureBackup alloc]initWithBottleID:@"" entropy:[NSData data]]; + cliqueContextConfiguration.otControl = self.otControl; + + NSError* localErrror = nil; + NSArray* escrowRecords = [OTClique fetchEscrowRecords:cliqueContextConfiguration error:&localErrror]; + XCTAssertNil(localErrror, "error should be nil"); + XCTAssertNotNil(escrowRecords, "escrow records should not be nil"); + + for (OTEscrowRecord* record in escrowRecords) { + XCTAssertEqual(record.creationDate, 1580440060, "escrow record creation date should be 1580440060"); + XCTAssertNotNil(record.escrowInformationMetadata.backupKeybagDigest, "escrow record backup key bag digest should not be nil"); + XCTAssertTrue([record.label isEqualToString:@"com.apple.icdp.record"], "escrow record label should be com.apple.icdp.record"); + XCTAssertEqual(record.recordStatus, OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID, "escrow record record status should be valid"); + XCTAssertEqual(record.remainingAttempts, 10, "escrow record remaining attempts should be 10"); + XCTAssertEqual(record.silentAttemptAllowed, 1, "escrow record silent attempted allowed should be true"); + XCTAssertTrue([record.serialNumber isEqualToString:@"C39V209AJ9L5"], "escrow record serial number should be equal"); + XCTAssertTrue([record.recordId isEqualToString:@"sNs6voV0N35D/T91SuGmJnGO29"], "escrow record record id should be true"); + XCTAssertEqual(record.silentAttemptAllowed, 1, "escrow record silent attempted allowed should be true"); + + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceColor isEqualToString: @"1"], "escrow record device color should be 1"); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceEnclosureColor isEqualToString:@"1"], "escrow record "); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceMid isEqualToString:@"yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X"], "escrow record MID should be yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X"); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceModel isEqualToString:@"iPhone 8 Plus"], "escrow record device model should be iPhone 8 Plus"); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceModelClass isEqualToString: @"iPhone"], "escrow record model calss should be iPhone"); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceModelVersion isEqualToString:@"iPhone10,5"], "escrow record model version should be iPhone10,5"); + XCTAssertTrue([record.escrowInformationMetadata.clientMetadata.deviceName isEqualToString:@"iPhone"], "escrow record device name should be iPhone "); + XCTAssertEqual(record.escrowInformationMetadata.clientMetadata.secureBackupMetadataTimestamp, 1580440060, "escrow record timestamp should be 1580440060"); + XCTAssertEqual(record.escrowInformationMetadata.clientMetadata.secureBackupNumericPassphraseLength, 6, "escrow record passphrase length should be 6"); + XCTAssertEqual(record.escrowInformationMetadata.clientMetadata.secureBackupUsesComplexPassphrase, 1, "escrow record uses complex passphrase should be 1"); + XCTAssertEqual(record.escrowInformationMetadata.clientMetadata.secureBackupUsesNumericPassphrase, 1, "escrow record uses numeric passphrase should be 1"); + XCTAssertNotNil(record.escrowInformationMetadata.escrowedSpki, "escrow record escrowed spki should not be nil"); + XCTAssertNotNil(record.escrowInformationMetadata.peerInfo, "escrow record peer info should be not nil"); + XCTAssertEqual(record.escrowInformationMetadata.secureBackupTimestamp, 1580440060, "escrow record timestamp should be 1580440060"); + XCTAssertEqual(record.escrowInformationMetadata.secureBackupUsesMultipleIcscs, 1, "escrow record uses multiple icscs should be 1"); + + NSData *testVectorData = [accountInfoWithInfoSample dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localErrror]; + + //now translate back to dictionary! + NSDictionary *translatedBackToDictionary = [OTEscrowTranslation escrowRecordToDictionary:record]; + XCTAssertNotNil(translatedBackToDictionary, "should not be nil"); + + NSArray *testVectorICDPRecords = testVectorPlist[@"SecureBackupAlliCDPRecords"]; + XCTAssertNotNil(testVectorICDPRecords, "should not be nil"); + + NSDictionary *testVectorRecord = testVectorICDPRecords[0]; + XCTAssertNotNil(testVectorRecord, "should not be nil"); + XCTAssertTrue([testVectorRecord[@"SecureBackupEscrowDate"] isEqualToDate: translatedBackToDictionary[@"SecureBackupEscrowDate"]], "should be equal"); + XCTAssertTrue([testVectorRecord[@"recordStatus"] isEqualToString:translatedBackToDictionary[@"recordStatus"]], "should be equal"); + XCTAssertTrue([testVectorRecord[@"silentAttemptAllowed"] isEqualToNumber:translatedBackToDictionary[@"silentAttemptAllowed"]], "should be equal"); + + XCTAssertTrue([testVectorRecord[@"peerInfoSerialNumber"] isEqualToString:translatedBackToDictionary[@"peerInfoSerialNumber"]], "should be equal"); + XCTAssertTrue([testVectorRecord[@"recordID"] isEqualToString:translatedBackToDictionary[@"recordID"]], "should be equal"); + + NSDictionary *testVectorMetadata = testVectorRecord[@"metadata"]; + XCTAssertNotNil(testVectorMetadata, "should not be nil"); + + NSDictionary *translatedMetadata = translatedBackToDictionary[@"metadata"]; + XCTAssertNotNil(translatedMetadata, "should not be nil"); + + XCTAssertTrue([testVectorMetadata[@"com.apple.securebackup.timestamp"] isEqualToString: translatedMetadata[@"com.apple.securebackup.timestamp"]], "should be equal"); + XCTAssertTrue([testVectorMetadata[@"bottleID"] isEqualToString:translatedMetadata[@"bottleID"]], "should be equal"); + XCTAssertTrue([testVectorMetadata[@"escrowedSPKI"] isEqualToData:translatedMetadata[@"escrowedSPKI"]], "should be equal"); + XCTAssertTrue([testVectorMetadata[@"SecureBackupUsesMultipleiCSCs"] isEqualToNumber: translatedMetadata[@"SecureBackupUsesMultipleiCSCs"]], "should be equal"); + XCTAssertTrue([testVectorMetadata[@"peerInfo"] isEqualToData:translatedMetadata[@"peerInfo"]], "should be equal"); + XCTAssertTrue([testVectorMetadata[@"BackupKeybagDigest"] isEqualToData: translatedMetadata[@"BackupKeybagDigest"]], "should be equal"); + + NSDictionary *testVectorClientMetadata = testVectorMetadata[@"ClientMetadata"]; + XCTAssertNotNil(testVectorClientMetadata, "should not be nil"); + NSDictionary *translatedClientMetadata = translatedMetadata[@"ClientMetadata"]; + XCTAssertNotNil(translatedClientMetadata, "should not be nil"); + XCTAssertTrue([testVectorClientMetadata isEqualToDictionary:translatedClientMetadata], "should be equal"); + } + +} + +- (void)testCDPRecordContextTranslation +{ + NSError* localError = nil; + NSData *testVectorData = [testCDPRemoteRecordContextTestVector dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localError]; + XCTAssertNotNil(testVectorPlist, "testVectorPlist should not be nil"); + OTICDPRecordContext *cdpContext = [OTEscrowTranslation dictionaryToCDPRecordContext:testVectorPlist]; + XCTAssertNotNil(cdpContext, "cdpContext should not be nil"); + XCTAssertTrue([cdpContext.authInfo.authenticationAppleid isEqualToString:@"anna.535.paid@icloud.com"], "authenticationAppleid should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationAuthToken isEqualToString:@"EAAbAAAABLwIAAAAAF5PGvkRDmdzLmljbG91ZC5hdXRovQBx359KJvlZTwe1q6BwXvK4gQUYo2WQbKT8UDtn8rcA6FvEYBANaAk1ofWx/bcfB4pcLiXR3Y0kncELCwFCEEpqpZS+klD9AY1oT9zW6VtyOgQTZJ4mfWz103+FoMh8nLJAVpYVfM/UjsiNsLfTX+rUmevfeA=="], "authenticationAuthToken should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationDsid isEqualToString:@"16187698960"], "authenticationDsid should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationEscrowproxyUrl isEqualToString:@"https://p97-escrowproxy.icloud.com:443"], "authenticationEscrowproxyUrl should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationIcloudEnvironment isEqualToString:@"PROD"], "authenticationIcloudEnvironment should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationPassword isEqualToString: @"PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET"], "authenticationPassword should match"); + XCTAssertFalse(cdpContext.authInfo.fmipRecovery, "fmipRecovery should be false"); + XCTAssertFalse(cdpContext.authInfo.idmsRecovery, "idmsRecovery should be false"); + + + XCTAssertTrue(cdpContext.cdpInfo.containsIcdpData, "containsIcdpData should be true"); + XCTAssertFalse(cdpContext.cdpInfo.silentRecoveryAttempt, "silentRecoveryAttempt should be false"); + XCTAssertTrue(cdpContext.cdpInfo.usesMultipleIcsc, "usesMultipleIcsc should match"); + XCTAssertFalse(cdpContext.cdpInfo.useCachedSecret, "useCachedSecret should be false"); + XCTAssertFalse(cdpContext.cdpInfo.usePreviouslyCachedRecoveryKey, "usePreviouslyCachedRecoveryKey should be false"); + XCTAssertNil(cdpContext.cdpInfo.recoveryKey, "recoveryKey should be nil"); + XCTAssertTrue([cdpContext.cdpInfo.recoverySecret isEqualToString:@"333333"], "recoverySecret should be 333333"); + + NSDictionary *translateBack = [OTEscrowTranslation CDPRecordContextToDictionary:cdpContext]; + XCTAssertNotNil(translateBack, "translateBack should not be nil"); + + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationAppleID"]) isEqualToString:@"anna.535.paid@icloud.com"], "SecureBackupAuthenticationAppleID should be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationAuthToken"]) isEqualToString:@"EAAbAAAABLwIAAAAAF5PGvkRDmdzLmljbG91ZC5hdXRovQBx359KJvlZTwe1q6BwXvK4gQUYo2WQbKT8UDtn8rcA6FvEYBANaAk1ofWx/bcfB4pcLiXR3Y0kncELCwFCEEpqpZS+klD9AY1oT9zW6VtyOgQTZJ4mfWz103+FoMh8nLJAVpYVfM/UjsiNsLfTX+rUmevfeA=="], "SecureBackupAuthenticationAuthToken should be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationDSID"]) isEqualToString:@"16187698960"], "SecureBackupAuthenticationDSIDshould be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationEscrowProxyURL"]) isEqualToString:@"https://p97-escrowproxy.icloud.com:443"], "SecureBackupAuthenticationEscrowProxyURL be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationPassword"]) isEqualToString:@"PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET"], "SecureBackupAuthenticationPassword be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationiCloudEnvironment"]) isEqualToString:@"PROD"], "SecureBackupAuthenticationiCloudEnvironment be equal"); + XCTAssertTrue(translateBack[@"SecureBackupContainsiCDPData"], "SecureBackupContainsiCDPData true"); + XCTAssertTrue([translateBack[@"SecureBackupFMiPRecoveryKey"] isEqualToNumber:@NO], "SecureBackupFMiPRecoveryKey is false"); + XCTAssertTrue([translateBack[@"SecureBackupIDMSRecovery"] isEqualToNumber:@NO], "SecureBackupIDMSRecovery false"); + XCTAssertTrue([translateBack[@"SecureBackupPassphrase"] isEqualToString: @"333333"], "SecureBackupPassphrase true"); + XCTAssertTrue([translateBack[@"SecureBackupSilentRecoveryAttempt"] isEqualToNumber:@NO], "SecureBackupSilentRecoveryAttempt false"); + XCTAssertTrue([translateBack[@"SecureBackupUseCachedPassphrase"] isEqualToNumber:@NO], "SecureBackupUseCachedPassphrase false"); + XCTAssertTrue([translateBack[@"SecureBackupUsesMultipleiCSCs"] isEqualToNumber:@YES], "SecureBackupUsesMultipleiCSCs true"); + XCTAssertTrue([translateBack[@"SecureBackupUsesRecoveryKey"] isEqualToNumber:@NO], "SecureBackupUsesRecoveryKey false"); +} + +- (void)testCDPSilentRecordContextTranslation +{ + NSError* localError = nil; + NSData *testVectorData = [CDPRecordContextSilentTestVector dataUsingEncoding:kCFStringEncodingUTF8]; + NSPropertyListFormat format; + NSDictionary *testVectorPlist = [NSPropertyListSerialization propertyListWithData:testVectorData options: NSPropertyListMutableContainersAndLeaves format:&format error:&localError]; + XCTAssertNotNil(testVectorPlist, "testVectorPlist should not be nil"); + OTICDPRecordContext *cdpContext = [OTEscrowTranslation dictionaryToCDPRecordContext:testVectorPlist]; + XCTAssertNotNil(cdpContext, "cdpContext should not be nil"); + XCTAssertTrue([cdpContext.authInfo.authenticationAppleid isEqualToString:@"anna.535.paid@icloud.com"], "authenticationAppleid should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationAuthToken isEqualToString:@"EAAbAAAABLwIAAAAAF5PHOERDmdzLmljbG91ZC5hdXRovQDwjwm2kXoklEtO/xeL3YCPlBr7IkVuV26y2BfLco+QhJFm4VhgFZSBFUg5l4g/uV2DG95xadgk0+rWLhyXDGZwHN2V9jju3eo6sRwGVj4g5iBFStuj4unTKylu3iFkNSKtTMXAyBXpn4EiRX+8dwumC2FKkA=="], "authenticationAuthToken should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationDsid isEqualToString:@"16187698960"], "authenticationDsid should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationEscrowproxyUrl isEqualToString:@"https://p97-escrowproxy.icloud.com:443"], "authenticationEscrowproxyUrl should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationIcloudEnvironment isEqualToString:@"PROD"], "authenticationIcloudEnvironment should match"); + XCTAssertTrue([cdpContext.authInfo.authenticationPassword isEqualToString: @"PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET"], "authenticationPassword should match"); + XCTAssertFalse(cdpContext.authInfo.fmipRecovery, "fmipRecovery should be false"); + XCTAssertFalse(cdpContext.authInfo.idmsRecovery, "idmsRecovery should be false"); + + + XCTAssertTrue(cdpContext.cdpInfo.containsIcdpData, "containsIcdpData should be true"); + XCTAssertTrue(cdpContext.cdpInfo.silentRecoveryAttempt, "silentRecoveryAttempt should be true"); + XCTAssertTrue(cdpContext.cdpInfo.usesMultipleIcsc, "usesMultipleIcsc should match"); + XCTAssertFalse(cdpContext.cdpInfo.useCachedSecret, "useCachedSecret should be false"); + XCTAssertFalse(cdpContext.cdpInfo.usePreviouslyCachedRecoveryKey, "usePreviouslyCachedRecoveryKey should be false"); + XCTAssertNil(cdpContext.cdpInfo.recoveryKey, "recoveryKey should be nil"); + XCTAssertTrue([cdpContext.cdpInfo.recoverySecret isEqualToString:@"333333"], "recoverySecret should be 333333"); + + NSDictionary *translateBack = [OTEscrowTranslation CDPRecordContextToDictionary:cdpContext]; + XCTAssertNotNil(translateBack, "translateBack should not be nil"); + + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationAppleID"]) isEqualToString:@"anna.535.paid@icloud.com"], "SecureBackupAuthenticationAppleID should be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationAuthToken"]) isEqualToString:@"EAAbAAAABLwIAAAAAF5PHOERDmdzLmljbG91ZC5hdXRovQDwjwm2kXoklEtO/xeL3YCPlBr7IkVuV26y2BfLco+QhJFm4VhgFZSBFUg5l4g/uV2DG95xadgk0+rWLhyXDGZwHN2V9jju3eo6sRwGVj4g5iBFStuj4unTKylu3iFkNSKtTMXAyBXpn4EiRX+8dwumC2FKkA=="], "SecureBackupAuthenticationAuthToken should be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationDSID"]) isEqualToString:@"16187698960"], "SecureBackupAuthenticationDSIDshould be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationEscrowProxyURL"]) isEqualToString:@"https://p97-escrowproxy.icloud.com:443"], "SecureBackupAuthenticationEscrowProxyURL be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationPassword"]) isEqualToString:@"PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET"], "SecureBackupAuthenticationPassword be equal"); + XCTAssertTrue([((NSString*)translateBack[@"SecureBackupAuthenticationiCloudEnvironment"]) isEqualToString:@"PROD"], "SecureBackupAuthenticationiCloudEnvironment be equal"); + XCTAssertTrue(translateBack[@"SecureBackupContainsiCDPData"], "SecureBackupContainsiCDPData true"); + XCTAssertTrue([translateBack[@"SecureBackupFMiPRecoveryKey"] isEqualToNumber:@NO], "SecureBackupFMiPRecoveryKey is false"); + XCTAssertTrue([translateBack[@"SecureBackupIDMSRecovery"] isEqualToNumber:@NO], "SecureBackupIDMSRecovery false"); + XCTAssertTrue([translateBack[@"SecureBackupPassphrase"] isEqualToString: @"333333"], "SecureBackupPassphrase true"); + XCTAssertTrue([translateBack[@"SecureBackupSilentRecoveryAttempt"] isEqualToNumber:@YES], "SecureBackupSilentRecoveryAttempt true"); + XCTAssertTrue([translateBack[@"SecureBackupUseCachedPassphrase"] isEqualToNumber:@NO], "SecureBackupUseCachedPassphrase false"); + XCTAssertTrue([translateBack[@"SecureBackupUsesMultipleiCSCs"] isEqualToNumber:@YES], "SecureBackupUsesMultipleiCSCs true"); + XCTAssertTrue([translateBack[@"SecureBackupUsesRecoveryKey"] isEqualToNumber:@NO], "SecureBackupUsesRecoveryKey false"); +} + +@end + diff --git a/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowTestVectors.h b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowTestVectors.h new file mode 100644 index 00000000..aa9ddc7a --- /dev/null +++ b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-EscrowTestVectors.h @@ -0,0 +1,415 @@ +/* +* Copyright (c) 2020 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@ +*/ + +#if OCTAGON + +NSString *accountInfoWithInfoSample = @"\ +\ +\ +\ + SecureBackupAccountIsHighSecurity\ + \ + SecureBackupAlliCDPRecords\ + \ + \ + SecureBackupEscrowDate\ + 2020-01-31T03:07:40Z\ + SecureBackupRemainingAttempts\ + 10\ + encodedMetadata\ + YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ==\ + label\ + com.apple.icdp.record\ + metadata\ + \ + BackupKeybagDigest\ + \ + yFGtyxY2ZzDt0j/26GkNSmrgVnY=\ + \ + ClientMetadata\ + \ + SecureBackupMetadataTimestamp\ + 2020-01-31 03:07:40\ + SecureBackupNumericPassphraseLength\ + 6\ + SecureBackupUsesComplexPassphrase\ + \ + SecureBackupUsesNumericPassphrase\ + \ + device_color\ + 1\ + device_enclosure_color\ + 1\ + device_mid\ + yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X\ + device_model\ + iPhone 8 Plus\ + device_model_class\ + iPhone\ + device_model_version\ + iPhone10,5\ + device_name\ + iPhone\ + device_platform\ + 1\ + \ + SecureBackupUsesMultipleiCSCs\ + \ + bottleID\ + DD5E3F9F-3702-4789-8ACF-2D28BC86A94C\ + build\ + 18A214\ + com.apple.securebackup.timestamp\ + 2020-01-31 03:07:40\ + escrowedSPKI\ + \ + MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC\ + Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b\ + 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj\ + Ug+fyh0c0xABOXt2Kdup7IYTGrzn\ + \ + peerInfo\ + \ + MIIErjGCBGEwFAwPQ29uZmxpY3RWZXJzaW9uAgEDMCsM\ + D0FwcGxpY2F0aW9uRGF0ZQQYGBYyMDIwMDEzMDIyNDEy\ + Ni4yODAwNTdaMFUMEFB1YmxpY1NpZ25pbmdLZXkEQQTl\ + vn18gJwjGum8v3Chn9Yh5HM/VRLGuq6HAV4KyxlUm+w8\ + uF80+32tY3/l9nKOmU61691beekwSWcfF+mDTGPrMFgM\ + D0FwcGxpY2F0aW9uVXNpZwRFMEMCIGOIXWe83FnflHu+\ + yShdjivfTaPDFHvX+RYNgMy74iSnAh9OHeQzmDchZOi0\ + 81lbhw/9rjEe8wEmozXX126RUOe/MHAMDURldmljZUdl\ + c3RhbHQxXzATDAlNb2RlbE5hbWUMBmlQaG9uZTATDAlP\ + U1ZlcnNpb24MBjE4QTIxNDAWDAxDb21wdXRlck5hbWUM\ + BmlQaG9uZTAbDBZNZXNzYWdlUHJvdG9jb2xWZXJzaW9u\ + AgEAMHwMF09jdGFnb25QdWJsaWNTaWduaW5nS2V5BGEE\ + oLohYY3GpRSv20AT67jLJ1s2dKr+1bT8JoY23QkCeJgj\ + GNb+vutEQhLFjLPsENtNE7+NA7wgac0QAXLDO9H/LbpN\ + UP8DF1Q0NpFX4JiFZqG876jS8HEgR6VOOJzhJzUZMH8M\ + Gk9jdGFnb25QdWJsaWNFbmNyeXB0aW9uS2V5BGEEDRnS\ + sPQ/mTEl5dmMEYnQYhcm9hiPzBnQ0ghQzb70auYoPbCR\ + xjCoG7MCpbb+4JGM4L74OdbJZJbTtHeZ0JtCbqo93ZyI\ + fULWz131HsOyxowTSSI9yDiPAyXZz6nRnnvnMIIB+AwQ\ + VjJEaWN0aW9uYXJ5RGF0YQSCAeIxggHeMBAMDEVzY3Jv\ + d1JlY29yZAUAMBwMDFNlcmlhbE51bWJlcgwMQzM5VjIw\ + OUFKOUw1MC0MCUJhY2t1cEtleQQgZlnxFs5NJO9YlR/4\ + SDWH+e9rD/+Jf7lWWjMoTW9+n68wYAwMTWFjaGluZUlE\ + S2V5DFB5V25JOHZkTmc2RVdheWVXL0ZQNGNEWlJzZTNM\ + TW44UHhnL3gvc1B6WkpJUzVjczNSS280L3N0T1c0Nm5R\ + OThpTmxwU0hyblIwa2ZzYlIzWDCCARkMBVZpZXdz0YIB\ + DgwHQXBwbGVUVgwHSG9tZUtpdAwHUENTLUZERQwJUENT\ + LU5vdGVzDApQQ1MtQmFja3VwDApQQ1MtRXNjcm93DApQ\ + Q1MtUGhvdG9zDAtCYWNrdXBCYWdWMAwLUENTLVNoYXJp\ + bmcMDE5hbm9SZWdpc3RyeQwMUENTLUNsb3VkS2l0DAxQ\ + Q1MtRmVsZHNwYXIMDFBDUy1NYWlsZHJvcAwMUENTLWlN\ + ZXNzYWdlDA1QQ1MtTWFzdGVyS2V5DA5XYXRjaE1pZ3Jh\ + dGlvbgwOaUNsb3VkSWRlbnRpdHkMD1BDUy1pQ2xvdWRE\ + cml2ZQwQQWNjZXNzb3J5UGFpcmluZwwQQ29udGludWl0\ + eVVubG9jawRHMEUCIES5okyKP4YMZqDjIGRMoLE83SYh\ + zjEyOvGPA0BoF6ViAiEAh6/dd57K+JBWmGXd4v4qGELp\ + vAeSjqcRUfdLtQj4DxI=\ + \ + serial\ + C39V209AJ9L5\ + \ + osVersion\ + 18A214\ + peerInfoSerialNumber\ + C39V209AJ9L5\ + recordID\ + sNs6voV0N35D/T91SuGmJnGO29\ + recordStatus\ + valid\ + silentAttemptAllowed\ + \ + \ + \ + SecureBackupContainsiCloudIdentity\ + \ + SecureBackupEnabled\ + \ + SecureBackupEscrowTrustStatus\ + 0\ + SecureBackupRecoveryRequiresVerificationToken\ + \ + SecureBackupUsesRecoveryKey\ + \ + SecureBackupiCDPRecords\ + \ + \ + SecureBackupEscrowDate\ + 2020-01-31T03:07:40Z\ + SecureBackupRemainingAttempts\ + 10\ + encodedMetadata\ + YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ==\ + label\ + com.apple.icdp.record\ + metadata\ + \ + BackupKeybagDigest\ + \ + yFGtyxY2ZzDt0j/26GkNSmrgVnY=\ + \ + ClientMetadata\ + \ + SecureBackupMetadataTimestamp\ + 2020-01-31 03:07:40\ + SecureBackupNumericPassphraseLength\ + 6\ + SecureBackupUsesComplexPassphrase\ + \ + SecureBackupUsesNumericPassphrase\ + \ + device_color\ + 1\ + device_enclosure_color\ + 1\ + device_mid\ + yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X\ + device_model\ + iPhone 8 Plus\ + device_model_class\ + iPhone\ + device_model_version\ + iPhone10,5\ + device_name\ + iPhone\ + device_platform\ + 1\ + \ + SecureBackupUsesMultipleiCSCs\ + \ + bottleID\ + DD5E3F9F-3702-4789-8ACF-2D28BC86A94C\ + bottleValid\ + valid\ + build\ + 18A214\ + com.apple.securebackup.timestamp\ + 2020-01-31 03:07:40\ + escrowedSPKI\ + \ + MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC\ + Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b\ + 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj\ + Ug+fyh0c0xABOXt2Kdup7IYTGrzn\ + \ + peerInfo\ + \ + MIIErjGCBGEwFAwPQ29uZmxpY3RWZXJzaW9uAgEDMCsM\ + D0FwcGxpY2F0aW9uRGF0ZQQYGBYyMDIwMDEzMDIyNDEy\ + Ni4yODAwNTdaMFUMEFB1YmxpY1NpZ25pbmdLZXkEQQTl\ + vn18gJwjGum8v3Chn9Yh5HM/VRLGuq6HAV4KyxlUm+w8\ + uF80+32tY3/l9nKOmU61691beekwSWcfF+mDTGPrMFgM\ + D0FwcGxpY2F0aW9uVXNpZwRFMEMCIGOIXWe83FnflHu+\ + yShdjivfTaPDFHvX+RYNgMy74iSnAh9OHeQzmDchZOi0\ + 81lbhw/9rjEe8wEmozXX126RUOe/MHAMDURldmljZUdl\ + c3RhbHQxXzATDAlNb2RlbE5hbWUMBmlQaG9uZTATDAlP\ + U1ZlcnNpb24MBjE4QTIxNDAWDAxDb21wdXRlck5hbWUM\ + BmlQaG9uZTAbDBZNZXNzYWdlUHJvdG9jb2xWZXJzaW9u\ + AgEAMHwMF09jdGFnb25QdWJsaWNTaWduaW5nS2V5BGEE\ + oLohYY3GpRSv20AT67jLJ1s2dKr+1bT8JoY23QkCeJgj\ + GNb+vutEQhLFjLPsENtNE7+NA7wgac0QAXLDO9H/LbpN\ + UP8DF1Q0NpFX4JiFZqG876jS8HEgR6VOOJzhJzUZMH8M\ + Gk9jdGFnb25QdWJsaWNFbmNyeXB0aW9uS2V5BGEEDRnS\ + sPQ/mTEl5dmMEYnQYhcm9hiPzBnQ0ghQzb70auYoPbCR\ + xjCoG7MCpbb+4JGM4L74OdbJZJbTtHeZ0JtCbqo93ZyI\ + fULWz131HsOyxowTSSI9yDiPAyXZz6nRnnvnMIIB+AwQ\ + VjJEaWN0aW9uYXJ5RGF0YQSCAeIxggHeMBAMDEVzY3Jv\ + d1JlY29yZAUAMBwMDFNlcmlhbE51bWJlcgwMQzM5VjIw\ + OUFKOUw1MC0MCUJhY2t1cEtleQQgZlnxFs5NJO9YlR/4\ + SDWH+e9rD/+Jf7lWWjMoTW9+n68wYAwMTWFjaGluZUlE\ + S2V5DFB5V25JOHZkTmc2RVdheWVXL0ZQNGNEWlJzZTNM\ + TW44UHhnL3gvc1B6WkpJUzVjczNSS280L3N0T1c0Nm5R\ + OThpTmxwU0hyblIwa2ZzYlIzWDCCARkMBVZpZXdz0YIB\ + DgwHQXBwbGVUVgwHSG9tZUtpdAwHUENTLUZERQwJUENT\ + LU5vdGVzDApQQ1MtQmFja3VwDApQQ1MtRXNjcm93DApQ\ + Q1MtUGhvdG9zDAtCYWNrdXBCYWdWMAwLUENTLVNoYXJp\ + bmcMDE5hbm9SZWdpc3RyeQwMUENTLUNsb3VkS2l0DAxQ\ + Q1MtRmVsZHNwYXIMDFBDUy1NYWlsZHJvcAwMUENTLWlN\ + ZXNzYWdlDA1QQ1MtTWFzdGVyS2V5DA5XYXRjaE1pZ3Jh\ + dGlvbgwOaUNsb3VkSWRlbnRpdHkMD1BDUy1pQ2xvdWRE\ + cml2ZQwQQWNjZXNzb3J5UGFpcmluZwwQQ29udGludWl0\ + eVVubG9jawRHMEUCIES5okyKP4YMZqDjIGRMoLE83SYh\ + zjEyOvGPA0BoF6ViAiEAh6/dd57K+JBWmGXd4v4qGELp\ + vAeSjqcRUfdLtQj4DxI=\ + \ + serial\ + C39V209AJ9L5\ + \ + osVersion\ + 18A214\ + peerInfoSerialNumber\ + C39V209AJ9L5\ + recordID\ + sNs6voV0N35D/T91SuGmJnGO29\ + recordStatus\ + valid\ + silentAttemptAllowed\ + \ + \ + \ + SecureBackupiCloudDataProtectionEnabled\ + \ +\ +"; + +NSString *testCDPRemoteRecordContextTestVector = @"\ +\ +\ +\ + SecureBackupAuthenticationAppleID\ + anna.535.paid@icloud.com\ + SecureBackupAuthenticationAuthToken\ + EAAbAAAABLwIAAAAAF5PGvkRDmdzLmljbG91ZC5hdXRovQBx359KJvlZTwe1q6BwXvK4gQUYo2WQbKT8UDtn8rcA6FvEYBANaAk1ofWx/bcfB4pcLiXR3Y0kncELCwFCEEpqpZS+klD9AY1oT9zW6VtyOgQTZJ4mfWz103+FoMh8nLJAVpYVfM/UjsiNsLfTX+rUmevfeA==\ + SecureBackupAuthenticationDSID\ + 16187698960\ + SecureBackupAuthenticationEscrowProxyURL\ + https://p97-escrowproxy.icloud.com:443\ + SecureBackupAuthenticationPassword\ + PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET\ + SecureBackupAuthenticationiCloudEnvironment\ + PROD\ + SecureBackupContainsiCDPData\ + \ + SecureBackupMetadata\ + \ + BackupKeybagDigest\ + \ + uZ+vDf1JWIHh+MXIi487iENG2fk=\ + \ + ClientMetadata\ + \ + SecureBackupMetadataTimestamp\ + 2020-02-20 00:38:28\ + SecureBackupNumericPassphraseLength\ + 6\ + SecureBackupUsesComplexPassphrase\ + \ + SecureBackupUsesNumericPassphrase\ + 1\ + device_color\ + 1\ + device_enclosure_color\ + 1\ + device_mid\ + vsoWCkYtidlo3QGgt6jvLDfeTWqKKQwHITeUEuYM7ZoyWI6CRH/ZUqsdg1fT96TyAyxUuYUF3fjRs5b1\ + device_model\ + iPhone 8 Plus\ + device_model_class\ + iPhone\ + device_model_version\ + iPhone10,2\ + device_name\ + One\ + device_platform\ + 1\ + \ + SecureBackupUsesMultipleiCSCs\ + \ + bottleID\ + 0125E97E-B124-4556-881A-A355805EBE47\ + bottleValid\ + valid\ + build\ + 18A230\ + com.apple.securebackup.timestamp\ + 2020-02-20 00:38:28\ + escrowedSPKI\ + \ + MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEB48BVh0D++mTSm9ucXC/a5M0CxFm\ + 4QfFktDjGV0Oo3z7xLSBiqxOwvzl1Vt7m45Rbfk4YnyguNan7aDzD1X6S2zU\ + HhJ8nXro1aAn8tnUX6+EGV2v4iScbkeOrWkqQoWw\ + \ + peerInfo\ + \ + MIIEyjGCBHwwFAwPQ29uZmxpY3RWZXJzaW9uAgEDMCsMD0FwcGxpY2F0aW9u\ + RGF0ZQQYGBYyMDIwMDIyMDAwMzgyMi4yODc3NjNaMFUMEFB1YmxpY1NpZ25p\ + bmdLZXkEQQQCECkiqu2q7lmL+UUs1fzJWfI7ECo+3JsbiKsrXe8yr/JJC96U\ + oOz8qsdqgJOoA9pp4oaLtdGU9gzopNdRxTU8MFsMD0FwcGxpY2F0aW9uVXNp\ + ZwRIMEYCIQCNUy7VzU5erma8k0EgvXdo0YsuSgC9T4c6w3UM30vnSwIhAKsw\ + Sz6mVOEE3cVbv8WFlF88nb54MK51cyfI3pWp3rRlMG0MDURldmljZUdlc3Rh\ + bHQxXDATDAlNb2RlbE5hbWUMBmlQaG9uZTATDAlPU1ZlcnNpb24MBjE4QTIz\ + MDATDAxDb21wdXRlck5hbWUMA09uZTAbDBZNZXNzYWdlUHJvdG9jb2xWZXJz\ + aW9uAgEAMHwMF09jdGFnb25QdWJsaWNTaWduaW5nS2V5BGEErqcLz3k64Qla\ + asOxVOz9q6jNddI5ujH1zFYjhrTzkGvRCjfgTOK6cHbEbZS6/zgpXXXNMhj4\ + jsZR+scCcbv5yvRfyaZiGAIT5KrsnEiTXygR9hYmVdRqrjmk0ZQkgXOPMH8M\ + Gk9jdGFnb25QdWJsaWNFbmNyeXB0aW9uS2V5BGEEsP2N8X9uVz2lqLgeYCFE\ + 8kRIUduWj7rL0ioejawj10Qj2OqNhUGYZ0xPnnaGd0uSYFiSrMT04KYXPRqZ\ + NoExp4z9Xda9JvJXjqk2wUeo+EL/smGJmgklfcFkAlY8RheCMIICEwwQVjJE\ + aWN0aW9uYXJ5RGF0YQSCAf0xggH5MBwMDFNlcmlhbE51bWJlcgwMQzM5VjIw\ + RUtKOUtUMC0MCUJhY2t1cEtleQQg+5p8h4Sbq3rSHuA6eHvUGHlVKxvMvtSh\ + DsjZD/h9OBAwYAwMTWFjaGluZUlES2V5DFB2c29XQ2tZdGlkbG8zUUdndDZq\ + dkxEZmVUV3FLS1F3SElUZVVFdVlNN1pveVdJNkNSSC9aVXFzZGcxZlQ5NlR5\ + QXl4VXVZVUYzZmpSczViMTCCAUYMBVZpZXdz0YIBOwwEV2lGaQwHQXBwbGVU\ + VgwHSG9tZUtpdAwHUENTLUZERQwJUENTLU5vdGVzDAlQYXNzd29yZHMMClBD\ + Uy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1Yw\ + DAtDcmVkaXRDYXJkcwwLUENTLVNoYXJpbmcMDE5hbm9SZWdpc3RyeQwMUENT\ + LUNsb3VkS2l0DAxQQ1MtRmVsZHNwYXIMDFBDUy1NYWlsZHJvcAwMUENTLWlN\ + ZXNzYWdlDA1PdGhlclN5bmNhYmxlDA1QQ1MtTWFzdGVyS2V5DA5XYXRjaE1p\ + Z3JhdGlvbgwOaUNsb3VkSWRlbnRpdHkMD1BDUy1pQ2xvdWREcml2ZQwQQWNj\ + ZXNzb3J5UGFpcmluZwwQQ29udGludWl0eVVubG9jawRIMEYCIQC9IebK7hYO\ + N4bYG05pbavoyP3uVs2GrBTvaaxhNeO/WgIhAP/M+WSwsqzcUkg5zhT806au\ + Ax7U0AMhq4OkV2yIuQd8\ + \ + serial\ + C39V20EKJ9KT\ + \ + SecureBackupPassphrase\ + 333333\ + SecureBackupUsesMultipleiCSCs\ + \ + recordID\ + nDF7K/s5knTXbH6/+ERe2LPFZR\ +\ +"; + +NSString* CDPRecordContextSilentTestVector = @"\ +\ +\ +\ + SecureBackupAuthenticationAppleID\ + anna.535.paid@icloud.com\ + SecureBackupAuthenticationAuthToken\ + EAAbAAAABLwIAAAAAF5PHOERDmdzLmljbG91ZC5hdXRovQDwjwm2kXoklEtO/xeL3YCPlBr7IkVuV26y2BfLco+QhJFm4VhgFZSBFUg5l4g/uV2DG95xadgk0+rWLhyXDGZwHN2V9jju3eo6sRwGVj4g5iBFStuj4unTKylu3iFkNSKtTMXAyBXpn4EiRX+8dwumC2FKkA==\ + SecureBackupAuthenticationDSID\ + 16187698960\ + SecureBackupAuthenticationEscrowProxyURL\ + https://p97-escrowproxy.icloud.com:443\ + SecureBackupAuthenticationPassword\ + PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET\ + SecureBackupAuthenticationiCloudEnvironment\ + PROD\ + SecureBackupContainsiCDPData\ + \ + SecureBackupPassphrase\ + 333333\ + SecureBackupSilentRecoveryAttempt\ + \ + SecureBackupUsesMultipleiCSCs\ + \ +\ +"; + +#endif + diff --git a/keychain/ckks/tests/CKKSCloudKitTestsInfo.plist b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-Info.plist similarity index 94% rename from keychain/ckks/tests/CKKSCloudKitTestsInfo.plist rename to keychain/OctagonTrust/ot-tests/OctagonTrustTests-Info.plist index 6c6c23c4..6c40a6cd 100644 --- a/keychain/ckks/tests/CKKSCloudKitTestsInfo.plist +++ b/keychain/OctagonTrust/ot-tests/OctagonTrustTests-Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/keychain/OctagonTrust/ot-tests/OctagonTrustTests.h b/keychain/OctagonTrust/ot-tests/OctagonTrustTests.h new file mode 100644 index 00000000..84ee897c --- /dev/null +++ b/keychain/OctagonTrust/ot-tests/OctagonTrustTests.h @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2020 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@ +*/ + + +#ifndef OctagonTrustTests_h +#define OctagonTrustTests_h + +#import "keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h" +#import "keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.h" +#import "keychain/ot/OTControl.h" +#import "keychain/ot/OTControlProtocol.h" +#import "keychain/ot/OctagonControlServer.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ProxyXPCConnection : NSObject +@property NSXPCListener *listener; +@property (nonatomic) id obj; +@property (nonatomic) NSXPCInterface *serverInterface; +- (instancetype)initWithInterface:(NSXPCInterface*)interface obj:(id)obj; +- (BOOL)listener:(NSXPCListener*)listener newConnection:(NSXPCConnection*)newConnection; +@end + +@interface OctagonTrustTests : CloudKitKeychainSyncingTestsBase +@property (nonatomic) OTControl* otControl; +@property (nonatomic) ProxyXPCConnection* otXPCProxy; +@property (nonatomic) id mockClique; + +@end + + +@interface OctagonTrustTests (OctagonTrustTestsErrors) +@end + +NS_ASSUME_NONNULL_END +#endif /* OctagonTrustTests_h */ diff --git a/keychain/ResetCloudKeychainAccount/reset_ick_account b/keychain/ResetCloudKeychainAccount/reset_ick_account old mode 100644 new mode 100755 index 79e748bf..ceb378b8 --- a/keychain/ResetCloudKeychainAccount/reset_ick_account +++ b/keychain/ResetCloudKeychainAccount/reset_ick_account @@ -1,5 +1,4 @@ -#!/usr/bin/python -# +#!/usr/local/bin/python3 import sys from glob import glob @@ -25,9 +24,9 @@ def set_security_ios_cmd(): def security_cmd_by_platform(): swVers = subprocess.check_output(["sw_vers"]) - deviceInformation = str(swVers, 'utf-8') - if "Mac OS X" in deviceInformation: - print("using security2 command on macosx") + deviceInformation = swVers.decode('utf-8') + if "Mac OS X" in deviceInformation or "macOS" in deviceInformation: + print("using security2 command on macos") return set_security_mac_cmd() elif "iPhone OS" in deviceInformation: print("using security command on ios") @@ -38,19 +37,16 @@ def security_cmd_by_platform(): security_cmd = security_cmd_by_platform() -print("resetting octagon") -subprocess.check_output(["otctl", "resetoctagon"]) - -print("resetting ckks") -subprocess.check_output(["ckksctl", "reset-cloudkit"]) +print("deleting all escrow records") +subprocess.check_output(["stingrayutil", "--deleteAll", "ReallyDeleteAll"]) print("resetting SOS") subprocess.check_output([security_cmd, "sync", "-C"]) subprocess.check_output([security_cmd, "sync", "-P", "$iCloudPassword"]) subprocess.check_output([security_cmd, "sync", "-O"]) -print("deleting all escrow records") -subprocess.check_output(["stingrayutil", "--deleteAll", "ReallyDeleteAll"]) +print("resetting octagon") +subprocess.check_output(["otctl", "resetoctagon"]) print("creating new escrow record") subprocess.check_output(["sbdtool", "passcode_request_trigger"]) diff --git a/keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.c b/keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.c index f2412f5b..fa0acac2 100644 --- a/keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.c +++ b/keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.c @@ -145,7 +145,7 @@ static SOSCloudTransportRef SOSCloudTransportDefaultTransport(void) if (defaultTransport == NULL) { defaultTransport = SOSCloudTransportCreateXPCTransport(); // provide state handler to sysdiagnose and logging - os_state_add_handler(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), kvsStateBlock); + os_state_add_handler(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), kvsStateBlock); } }); return defaultTransport; @@ -490,7 +490,7 @@ static bool SOSCloudTransportHasPendingKey(SOSCloudTransportRef transport, CFStr SecXPCDictionarySetCFObject(xpcmessage, kMessageKeyKey, keyName); dispatch_semaphore_t kvsWait = dispatch_semaphore_create(0); - bool kvsSent = messageToProxy(xpcTransport, xpcmessage, error, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(xpc_object_t reply) { + bool kvsSent = messageToProxy(xpcTransport, xpcmessage, error, dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(xpc_object_t reply) { kvsHasMessage = xpc_dictionary_get_bool(reply, kMessageKeyValue); dispatch_semaphore_signal(kvsWait); }); diff --git a/keychain/SecureObjectSync/CKDSimulatedStore.h b/keychain/SecureObjectSync/CKDSimulatedStore.h index bcdc6f17..37fb187d 100644 --- a/keychain/SecureObjectSync/CKDSimulatedStore.h +++ b/keychain/SecureObjectSync/CKDSimulatedStore.h @@ -25,7 +25,7 @@ - (NSDictionary*) copyAsDictionary; -- (void)pushWrites; +- (void)pushWrites:(NSArray*)keys requiresForceSync:(BOOL)requiresForceSync; - (BOOL)pullUpdates:(NSError**) failure; - (void)addOneToOutGoing; diff --git a/keychain/SecureObjectSync/CKDSimulatedStore.m b/keychain/SecureObjectSync/CKDSimulatedStore.m index f42bc0cf..ffd82cbc 100644 --- a/keychain/SecureObjectSync/CKDSimulatedStore.m +++ b/keychain/SecureObjectSync/CKDSimulatedStore.m @@ -24,11 +24,10 @@ } - (instancetype)init { - self = [super init]; - - self.proxy = nil; - self.data = [NSMutableDictionary dictionary]; - + if ((self = [super init])) { + self.proxy = nil; + self.data = [NSMutableDictionary dictionary]; + } return self; } @@ -62,7 +61,8 @@ [self.data removeAllObjects]; } -- (void)pushWrites { +- (void)pushWrites:(NSArray*)keys requiresForceSync:(BOOL)requiresForceSync +{ } - (void)addOneToOutGoing{ diff --git a/keychain/SecureObjectSync/Regressions/CKDSimulatedAccount.m b/keychain/SecureObjectSync/Regressions/CKDSimulatedAccount.m index 311c75e9..a67e6cae 100644 --- a/keychain/SecureObjectSync/Regressions/CKDSimulatedAccount.m +++ b/keychain/SecureObjectSync/Regressions/CKDSimulatedAccount.m @@ -20,8 +20,7 @@ return [[CKDSimulatedAccount alloc] init]; } - (instancetype) init { - self = [super init]; - if (self) { + if ((self = [super init])) { self.keysToNotHandle = [NSMutableSet set]; self.keyChanges = [NSMutableDictionary dictionary]; diff --git a/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.h b/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.h index d4810cc2..e7199d16 100644 --- a/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.h +++ b/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.h @@ -34,9 +34,12 @@ #include #include #include "keychain/SecureObjectSync/SOSFullPeerInfo.h" +#include __BEGIN_DECLS +#define SOS_ENABLED (TARGET_OS_OSX || TARGET_OS_IOS) + CFStringRef myMacAddress(void); const char *cfabsoluteTimeToString(CFAbsoluteTime abstime); const char *cfabsoluteTimeToStringLocal(CFAbsoluteTime abstime); diff --git a/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.m b/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.m index 1d343706..405939c9 100644 --- a/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.m +++ b/keychain/SecureObjectSync/Regressions/SOSRegressionUtilities.m @@ -220,11 +220,12 @@ CFTypeRef testGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t process dispatch_semaphore_signal(waitSemaphore); }; - if (!keysToGet) + if (!keysToGet) { SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock); - else + } else { SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, replyBlock); - + } + dispatch_semaphore_wait(waitSemaphore, finishTime); if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull { @@ -315,7 +316,10 @@ SOSPeerInfoRef SOSCreatePeerInfoFromName(CFStringRef name, require(gestalt, exit); result = SOSPeerInfoCreate(NULL, gestalt, NULL, *outSigningKey, - *outOctagonSigningKey, *outOctagonEncryptionKey, error); + *outOctagonSigningKey, *outOctagonEncryptionKey, + // Always support CKKS4All for now + true, + error); exit: CFReleaseNull(gestalt); diff --git a/keychain/SecureObjectSync/Regressions/SOSTestDataSource.c b/keychain/SecureObjectSync/Regressions/SOSTestDataSource.c index e7e2ac8e..e27c713d 100644 --- a/keychain/SecureObjectSync/Regressions/SOSTestDataSource.c +++ b/keychain/SecureObjectSync/Regressions/SOSTestDataSource.c @@ -220,7 +220,7 @@ static SOSObjectRef copyMergedObject(SOSObjectRef object1, SOSObjectRef object2, // Return the item with the smallest digest. CFDataRef digest1 = copyDigest(object1, error); CFDataRef digest2 = copyDigest(object2, error); - if (digest1 && digest2) switch (CFDataCompare(digest1, digest2)) { + if (digest1 && digest2) switch (CFDataCompareDERData(digest1, digest2)) { case kCFCompareGreaterThan: case kCFCompareEqualTo: result = (SOSObjectRef)dict2; diff --git a/keychain/SecureObjectSync/Regressions/sc-130-resignationticket.c b/keychain/SecureObjectSync/Regressions/sc-130-resignationticket.c index 5ad7629b..b0ba179b 100644 --- a/keychain/SecureObjectSync/Regressions/sc-130-resignationticket.c +++ b/keychain/SecureObjectSync/Regressions/sc-130-resignationticket.c @@ -41,6 +41,8 @@ #include "SOSRegressionUtilities.h" +#if SOS_ENABLED + typedef struct piStuff_t { SecKeyRef signingKey; SecKeyRef octagonSigningKey; @@ -150,13 +152,15 @@ static void tests(void) freeSimplePeer(iDrone); } -static int kTestTestCount = 12; +#endif int sc_130_resignationticket(int argc, char *const *argv) { - plan_tests(kTestTestCount); - +#if SOS_ENABLED + plan_tests(12); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-150-backupkeyderivation.c b/keychain/SecureObjectSync/Regressions/sc-150-backupkeyderivation.c index 3120a20a..768fe6ae 100644 --- a/keychain/SecureObjectSync/Regressions/sc-150-backupkeyderivation.c +++ b/keychain/SecureObjectSync/Regressions/sc-150-backupkeyderivation.c @@ -40,6 +40,8 @@ #include "SOSRegressionUtilities.h" #include "keychain/SecureObjectSync/SOSInternal.h" +#if SOS_ENABLED + #if 0 static inline CFMutableDataRef CFDataCreateMutableWithRandom(CFAllocatorRef allocator, CFIndex size) { CFMutableDataRef result = NULL; @@ -68,8 +70,6 @@ static const uint8_t sEntropy2[] = { 0xef, 0xbd, 0x72, 0x57, 0x02, 0xe6, 0xbd, static const uint8_t sEntropy3[] = { 0xea, 0x06, 0x34, 0x93, 0xd7, 0x8b, 0xd6, 0x0d, 0xce, 0x83, 0x00 }; - -#define tests_count (6) static void tests(void) { ccec_const_cp_t cp = SOSGetBackupKeyCurveParameters(); @@ -112,14 +112,16 @@ static void tests(void) CFReleaseNull(entropy2); CFReleaseNull(entropy3); } +#endif -static int kTestTestCount = tests_count; int sc_150_backupkeyderivation(int argc, char *const *argv) { - plan_tests(kTestTestCount); - +#if SOS_ENABLED + plan_tests(6); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-153-backupslicekeybag.c b/keychain/SecureObjectSync/Regressions/sc-153-backupslicekeybag.c index a1cefeba..28983628 100644 --- a/keychain/SecureObjectSync/Regressions/sc-153-backupslicekeybag.c +++ b/keychain/SecureObjectSync/Regressions/sc-153-backupslicekeybag.c @@ -32,8 +32,10 @@ #include "SOSCircle_regressions.h" #include "SOSRegressionUtilities.h" +#if SOS_ENABLED + #define encode_decode_count 2 -#if !TARGET_OS_SIMULATOR + static CF_RETURNS_RETAINED SOSBackupSliceKeyBagRef EncodeDecode(SOSBackupSliceKeyBagRef bag) { SOSBackupSliceKeyBagRef result = NULL; @@ -54,17 +56,6 @@ static CF_RETURNS_RETAINED SOSBackupSliceKeyBagRef EncodeDecode(SOSBackupSliceKe return result; } -#endif - -#if 0 -static CFDataRef CFDataCreateWithRandom(CFAllocatorRef allocator, size_t size) { - CFMutableDataRef result = CFDataCreateMutableWithScratch(allocator, size); - - SecRandomCopyBytes(kSecRandomDefault, size, CFDataGetMutableBytePtr(result)); - - return result; -} -#endif static const uint8_t sEntropy1[] = { 0xc4, 0xb9, 0xa6, 0x6e, 0xeb, 0x56, 0xa1, 0x5c, 0x1d, 0x30, 0x09, 0x40, @@ -78,12 +69,6 @@ static const uint8_t sEntropy2[] = { 0x3a, 0x91, 0x0d, 0xc1, 0x5f, 0x57, 0x98, 0x44 }; -#if !TARGET_OS_SIMULATOR - #define tests_count (8 + encode_decode_count) -#else - #define tests_count (6) -#endif - static void tests(void) { CFErrorRef localError = NULL; @@ -132,7 +117,6 @@ static void tests(void) SOSBackupSliceKeyBagRef vb2 = NULL; -#if !TARGET_OS_SIMULATOR vb = SOSBackupSliceKeyBagCreate(kCFAllocatorDefault, piSet, &localError); ok(vb != NULL, "Allocation: (%@)", localError); CFReleaseNull(localError); @@ -140,20 +124,6 @@ static void tests(void) vb2 = EncodeDecode(vb); ok(vb2 != NULL, "transcoded"); -#endif -#if 0 - // Have helper functions for new security object that load bags - keybag_handle_t ourHandle = SOSBSKBLoadAndUnlockWithPeerSecret(vb, peer2WithBackup, entropy2, &localError); - ok(ourHandle != bad_keybag_handle, "loaded with peer secret, handle %d (%@)", ourHandle, localError); - CFReleaseNull(localError); - - aks_unload_bag(ourHandle); -#else -TODO:{ - todo("no simulator supprt"); - ok(false); - } -#endif CFReleaseNull(vb); CFReleaseNull(vb2); @@ -172,14 +142,15 @@ TODO:{ CFReleaseNull(entropy1); CFReleaseNull(entropy2); } - -static int kTestTestCount = tests_count; +#endif int sc_153_backupslicekeybag(int argc, char *const *argv) { - plan_tests(kTestTestCount); - +#if SOS_ENABLED + plan_tests(12); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-20-keynames.m b/keychain/SecureObjectSync/Regressions/sc-20-keynames.m index a3722490..ad74dbc8 100644 --- a/keychain/SecureObjectSync/Regressions/sc-20-keynames.m +++ b/keychain/SecureObjectSync/Regressions/sc-20-keynames.m @@ -43,6 +43,8 @@ #include "SOSRegressionUtilities.h" +#if SOS_ENABLED + static int kTestTestCount = 15; static void tests(void) @@ -130,12 +132,15 @@ static void tests(void) CFReleaseNull(retirement_peer_id); } +#endif int sc_20_keynames(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-25-soskeygen.c b/keychain/SecureObjectSync/Regressions/sc-25-soskeygen.c index 42859409..bce07903 100644 --- a/keychain/SecureObjectSync/Regressions/sc-25-soskeygen.c +++ b/keychain/SecureObjectSync/Regressions/sc-25-soskeygen.c @@ -48,6 +48,9 @@ #include "SOSCircle_regressions.h" #include "SOSRegressionUtilities.h" + +#if SOS_ENABLED + #include #include #include @@ -185,7 +188,6 @@ static SecKeyRef SOSOldUserKeygen(CFDataRef password, CFDataRef parameters, CFEr return NULL; } - debugDumpUserParameters(CFSTR("params-keygen"), parameters); const uint8_t *password_bytes = CFDataGetBytePtr(password); @@ -198,7 +200,7 @@ static SecKeyRef SOSOldUserKeygen(CFDataRef password, CFDataRef parameters, CFEr ccec_full_ctx_decl_cp(cp, tmpkey); - secnotice("circleOps", "Generating key for: iterations %zd, keysize %zd: %@", iterations, keysize, parameters); + debugDumpUserParameters(CFSTR("sc_25_soskeygen: Generating key for:"), parameters); if (ccrng_pbkdf2_prng_init(&pbkdf2_prng, maxbytes, password_length, password_bytes, @@ -275,15 +277,15 @@ static void tests(void) { CFReleaseNull(cfpassword); } +#endif + int sc_25_soskeygen(int argc, char *const *argv) { -#if TARGET_OS_WATCH - plan_tests(NKEYS*(4+NPARMS*4)); -#else +#if SOS_ENABLED plan_tests(850); -#endif - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-30-peerinfo.c b/keychain/SecureObjectSync/Regressions/sc-30-peerinfo.c index 66c95929..4efa2918 100644 --- a/keychain/SecureObjectSync/Regressions/sc-30-peerinfo.c +++ b/keychain/SecureObjectSync/Regressions/sc-30-peerinfo.c @@ -46,6 +46,8 @@ #include "SOSRegressionUtilities.h" +#if SOS_ENABLED + #if TARGET_OS_IPHONE #include #endif @@ -152,12 +154,15 @@ static void tests(void) CFReleaseNull(octagonEncryptionKey); CFReleaseNull(fpi); } +#endif int sc_30_peerinfo(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-31-peerinfo-simplefuzz.c b/keychain/SecureObjectSync/Regressions/sc-31-peerinfo-simplefuzz.c index 800a241d..2774cbd9 100644 --- a/keychain/SecureObjectSync/Regressions/sc-31-peerinfo-simplefuzz.c +++ b/keychain/SecureObjectSync/Regressions/sc-31-peerinfo-simplefuzz.c @@ -28,6 +28,7 @@ #include "SOSCircle_regressions.h" #include "SOSRegressionUtilities.h" +#if SOS_ENABLED #if TARGET_OS_IPHONE #include @@ -79,12 +80,15 @@ errOut: CFReleaseNull(octagonEncryptionKey); CFReleaseNull(fpi); } +#endif int sc_31_peerinfo(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests((int)(kTestCount + kTestFuzzerCount)); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-40-circle.c b/keychain/SecureObjectSync/Regressions/sc-40-circle.c index 6f516bd1..a4687f81 100644 --- a/keychain/SecureObjectSync/Regressions/sc-40-circle.c +++ b/keychain/SecureObjectSync/Regressions/sc-40-circle.c @@ -47,6 +47,8 @@ #include "SOSRegressionUtilities.h" +#if SOS_ENABLED + static int kTestGenerationCount = 2; static void test_generation(void) { @@ -182,14 +184,16 @@ static void tests(void) CFReleaseNull(user_privkey); CFReleaseNull(circle); } +#endif int sc_40_circle(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestGenerationCount + kTestTestCount); - test_generation(); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-42-circlegencount.c b/keychain/SecureObjectSync/Regressions/sc-42-circlegencount.c index 7ee15736..f3ba599d 100644 --- a/keychain/SecureObjectSync/Regressions/sc-42-circlegencount.c +++ b/keychain/SecureObjectSync/Regressions/sc-42-circlegencount.c @@ -31,8 +31,7 @@ #include "SOSCircle_regressions.h" #include "SOSRegressionUtilities.h" - -static int kTestTestCount = 7; +#if SOS_ENABLED static void tests(void) { @@ -66,12 +65,15 @@ static void tests(void) CFReleaseNull(circle); } +#endif int sc_42_circlegencount(int argc, char *const *argv) { - plan_tests(kTestTestCount); - +#if SOS_ENABLED + plan_tests(7); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/Regressions/sc-45-digestvector.c b/keychain/SecureObjectSync/Regressions/sc-45-digestvector.c index 7f86e643..8c177bcc 100644 --- a/keychain/SecureObjectSync/Regressions/sc-45-digestvector.c +++ b/keychain/SecureObjectSync/Regressions/sc-45-digestvector.c @@ -28,8 +28,7 @@ #include #include - -static int kTestTestCount = 15; +#include "SOSRegressionUtilities.h" static void testNullDigestVector(void) { @@ -158,9 +157,11 @@ static void tests(void) int sc_45_digestvector(int argc, char *const *argv) { - plan_tests(kTestTestCount); - +#if SOS_ENABLED + plan_tests(15); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/SecureObjectSync/SOSAccount.h b/keychain/SecureObjectSync/SOSAccount.h index 7d888102..b2bf94a2 100644 --- a/keychain/SecureObjectSync/SOSAccount.h +++ b/keychain/SecureObjectSync/SOSAccount.h @@ -44,6 +44,10 @@ #import "keychain/SecureObjectSync/SOSAccountTransaction.h" #include +extern NSString* const kSOSIdentityStatusCompleteIdentity; +extern NSString* const kSOSIdentityStatusKeyOnly; +extern NSString* const kSOSIdentityStatusPeerOnly; + @class SOSAccount; __BEGIN_DECLS @@ -105,9 +109,9 @@ void SOSTransportEachMessage(SOSAccount* account, CFDictionaryRef updates, CFEr CFStringRef SOSAccountGetSOSCCStatusString(SOSCCStatus status); SOSCCStatus SOSAccountGetSOSCCStatusFromString(CFStringRef status); -bool SOSAccountJoinCircles(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error); -bool SOSAccountJoinCirclesAfterRestore(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error); -bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, NSData* parentEvent, CFErrorRef* error); +bool SOSAccountJoinCircles(SOSAccountTransaction* aTxn, CFErrorRef* error); +bool SOSAccountJoinCirclesAfterRestore(SOSAccountTransaction* aTxn, CFErrorRef* error); +bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, CFErrorRef* error); bool SOSAccountBail(SOSAccount* account, uint64_t limit_in_seconds, CFErrorRef* error); bool SOSAccountAcceptApplicants(SOSAccount* account, CFArrayRef applicants, CFErrorRef* error); bool SOSAccountRejectApplicants(SOSAccount* account, CFArrayRef applicants, CFErrorRef* error); @@ -158,6 +162,12 @@ void SOSAccountPeerGotInSync(SOSAccountTransaction* aTxn, CFStringRef peerID, CF bool SOSAccountHandleParametersChange(SOSAccount* account, CFDataRef updates, CFErrorRef *error); +// +// MARK: Local device key access from account object - can call without lock without endangering peerinfo. +// +SecKeyRef SOSAccountCopyDevicePrivateKey(SOSAccount* account, CFErrorRef *error); +SecKeyRef SOSAccountCopyDevicePublicKey(SOSAccount* account, CFErrorRef *error); + // // MARK: Requests for syncing later // @@ -192,7 +202,7 @@ CF_RETURNS_RETAINED SOSCircleRef SOSAccountCloneCircleWithRetirement(SOSAccount* bool SOSAccountIsBackupRingEmpty(SOSAccount* account, CFStringRef viewName); bool SOSAccountNewBKSBForView(SOSAccount* account, CFStringRef viewName, CFErrorRef *error); -void SOSAccountProcessBackupRings(SOSAccount* account, CFErrorRef *error); +void SOSAccountProcessBackupRings(SOSAccount* account); bool SOSAccountValidateBackupRingForView(SOSAccount* account, CFStringRef viewName, CFErrorRef *error); bool SOSAccountSetBackupPublicKey(SOSAccountTransaction* aTxn, CFDataRef backupKey, CFErrorRef *error); bool SOSAccountRemoveBackupPublickey(SOSAccountTransaction* aTxn, CFErrorRef *error); @@ -281,6 +291,8 @@ void SOSAccountResetOTRNegotiationCoder(SOSAccount* account, CFStringRef peerid) void SOSAccountTimerFiredSendNextMessage(SOSAccountTransaction* txn, NSString* peerid, NSString* accessGroup); NSArray* SOSAccountGetAllTLKs(void); +NSArray* SOSAccountGetSelectedTLKs(void); + CF_RETURNS_RETAINED CFMutableArrayRef SOSAccountCopyiCloudIdentities(SOSAccount* account); bool SOSAccountEvaluateKeysAndCircle(SOSAccountTransaction *txn, CFErrorRef *block_error); diff --git a/keychain/SecureObjectSync/SOSAccount.m b/keychain/SecureObjectSync/SOSAccount.m index 9976962f..c68ab63b 100644 --- a/keychain/SecureObjectSync/SOSAccount.m +++ b/keychain/SecureObjectSync/SOSAccount.m @@ -63,7 +63,6 @@ #include #include -#include #include #include @@ -94,6 +93,10 @@ const CFStringRef kOTRConfigVersion = CFSTR("OTRConfigVersion"); NSString* const SecSOSAggdReattemptOTRNegotiation = @"com.apple.security.sos.otrretry"; NSString* const SOSAccountUserDefaultsSuite = @"com.apple.security.sosaccount"; NSString* const SOSAccountLastKVSCleanup = @"lastKVSCleanup"; +NSString* const kSOSIdentityStatusCompleteIdentity = @"completeIdentity"; +NSString* const kSOSIdentityStatusKeyOnly = @"keyOnly"; +NSString* const kSOSIdentityStatusPeerOnly = @"peerOnly"; + const uint64_t max_packet_size_over_idms = 500; @@ -113,6 +116,7 @@ static NSDictionary* SOSStateMap(void); @property (readwrite) CKKSPBFileStorage* accountConfiguration; @property CKKSNearFutureScheduler *performBackups; +@property CKKSNearFutureScheduler *performRingUpdates; @end #endif @@ -123,6 +127,14 @@ static NSDictionary* SOSStateMap(void); CFReleaseNull(self->_accountKey); CFReleaseNull(self->_accountPrivateKey); CFReleaseNull(self->_previousAccountKey); + CFReleaseNull(self->_peerPublicKey); + CFReleaseNull(self->_octagonSigningFullKeyRef); + CFReleaseNull(self->_octagonEncryptionFullKeyRef); +#if OCTAGON + [self.performBackups cancel]; + [self.performRingUpdates cancel]; + [self.stateMachine haltOperation]; +#endif } } @@ -132,16 +144,22 @@ static NSDictionary* SOSStateMap(void); CFRetainAssign(self->_accountKey, key); } +@synthesize accountPrivateKey = _accountPrivateKey; + +- (void) setAccountPrivateKey: (SecKeyRef) key { + CFRetainAssign(self->_accountPrivateKey, key); +} + @synthesize previousAccountKey = _previousAccountKey; - (void) setPreviousAccountKey: (SecKeyRef) key { CFRetainAssign(self->_previousAccountKey, key); } -@synthesize accountPrivateKey = _accountPrivateKey; +@synthesize peerPublicKey = _peerPublicKey; -- (void) setAccountPrivateKey: (SecKeyRef) key { - CFRetainAssign(self->_accountPrivateKey, key); +- (void) setPeerPublicKey: (SecKeyRef) key { + CFRetainAssign(self->_peerPublicKey, key); } // Syntactic sugar getters @@ -164,16 +182,11 @@ static NSDictionary* SOSStateMap(void); -(bool) ensureFactoryCircles { - if (!self){ - return false; - } - - if (!self.factory){ + if (self.factory == nil){ return false; } - NSString* circle_name = (__bridge_transfer NSString*)SOSDataSourceFactoryCopyName(self.factory); - + NSString* circle_name = CFBridgingRelease(SOSDataSourceFactoryCopyName(self.factory)); if (!circle_name){ return false; } @@ -195,8 +208,7 @@ static NSDictionary* SOSStateMap(void); -(id) initWithGestalt:(CFDictionaryRef)newGestalt factory:(SOSDataSourceFactoryRef)f { - self = [super init]; - if(self){ + if ((self = [super init])) { self.queue = dispatch_queue_create("Account Queue", DISPATCH_QUEUE_SERIAL); self.gestalt = [[NSDictionary alloc] initWithDictionary:(__bridge NSDictionary * _Nonnull)(newGestalt)]; @@ -223,20 +235,26 @@ static NSDictionary* SOSStateMap(void); self.circle_rings_retirements_need_attention = false; self.engine_peer_state_needs_repair = false; self.key_interests_need_updating = false; + self.need_backup_peers_created_after_backup_key_set = false; self.backup_key =nil; self.deviceID = nil; self.waitForInitialSync_blocks = [NSMutableDictionary dictionary]; self.accountKeyIsTrusted = false; - self.accountKeyDerivationParamters = NULL; + self.accountKeyDerivationParameters = NULL; self.accountKey = NULL; self.previousAccountKey = NULL; + self.peerPublicKey = NULL; self.saveBlock = nil; self.settings = [[NSUserDefaults alloc] initWithSuiteName:SOSAccountUserDefaultsSuite]; + [self ensureFactoryCircles]; + SOSAccountEnsureUUID(self); + self.accountIsChanging = false; + #if OCTAGON [self setupStateMachine]; #endif @@ -244,6 +262,13 @@ static NSDictionary* SOSStateMap(void); return self; } +- (void)startStateMachine +{ +#if OCTAGON + [self.stateMachine startOperation]; +#endif +} + -(BOOL)isEqual:(id) object { if(![object isKindOfClass:[SOSAccount class]]) @@ -283,7 +308,7 @@ static NSDictionary* SOSStateMap(void); - (void)kvsPerformanceCounters:(void(^)(NSDictionary *))reply { /* Need to collect performance counters from all subsystems, not just circle transport, don't have counters yet though */ - SOSCloudKeychainRequestPerfCounters(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef error) + SOSCloudKeychainRequestPerfCounters(dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0), ^(CFDictionaryRef returnedValues, CFErrorRef error) { reply((__bridge NSDictionary *)returnedValues); }); @@ -332,7 +357,7 @@ static bool SyncKVSAndWait(CFErrorRef *error) { secnoticeq("fresh", "EFP calling SOSCloudKeychainSynchronizeAndWait"); os_activity_initiate("CloudCircle EFRESH", OS_ACTIVITY_FLAG_DEFAULT, ^(void) { - SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(__unused CFDictionaryRef returnedValues, CFErrorRef sync_error) { + SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(__unused CFDictionaryRef returnedValues, CFErrorRef sync_error) { secnotice("fresh", "EFP returned, callback error: %@", sync_error); success = (sync_error == NULL); @@ -357,7 +382,7 @@ static bool Flush(CFErrorRef *error) { dispatch_semaphore_t wait_for = dispatch_semaphore_create(0); secnotice("flush", "Starting"); - SOSCloudKeychainFlush(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { + SOSCloudKeychainFlush(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { success = (sync_error == NULL); if (error) { CFRetainAssign(*error, sync_error); @@ -422,57 +447,63 @@ static bool Flush(CFErrorRef *error) { CFReleaseNull(error); }); } - - (void)stashAccountCredential:(NSData *)credential complete:(void(^)(bool success, NSError *error))complete { - CFErrorRef syncerror = NULL; - - if (![self syncWaitAndFlush:&syncerror]) { - complete(NULL, (__bridge NSError *)syncerror); - CFReleaseNull(syncerror); - return; - } - sleep(1); // make up for keygen time in password based version - let syncdefaults catch up + dispatch_sync(SOSCCCredentialQueue(), ^{ + CFErrorRef syncerror = NULL; - [self performTransaction:^(SOSAccountTransaction * _Nonnull txn) { - SecKeyRef accountPrivateKey = NULL; - CFErrorRef error = NULL; - NSDictionary *attributes = @{ - (__bridge id)kSecAttrKeyClass : (__bridge id)kSecAttrKeyClassPrivate, - (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeEC, - }; + if (![self syncWaitAndFlush:&syncerror]) { + complete(NULL, (__bridge NSError *)syncerror); + CFReleaseNull(syncerror); + } else { + __block bool success = false; + sleep(1); // make up for keygen time in password based version - let syncdefaults catch up + + [self performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + SecKeyRef accountPrivateKey = NULL; + CFErrorRef error = NULL; + NSDictionary *attributes = @{ + (__bridge id)kSecAttrKeyClass : (__bridge id)kSecAttrKeyClassPrivate, + (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeEC, + }; + + accountPrivateKey = SecKeyCreateWithData((__bridge CFDataRef)credential, (__bridge CFDictionaryRef)attributes, &error); + if (accountPrivateKey == NULL) { + complete(false, (__bridge NSError *)error); + secnotice("pairing", "SecKeyCreateWithData failed: %@", error); + CFReleaseNull(error); + return; + } - accountPrivateKey = SecKeyCreateWithData((__bridge CFDataRef)credential, (__bridge CFDictionaryRef)attributes, &error); - if (accountPrivateKey == NULL) { - complete(false, (__bridge NSError *)error); - secnotice("pairing", "SecKeyCreateWithData failed: %@", error); - CFReleaseNull(error); - return; - } + if (!SOSAccountTryUserPrivateKey(self, accountPrivateKey, &error)) { + CFReleaseNull(accountPrivateKey); + complete(false, (__bridge NSError *)error); + secnotice("pairing", "SOSAccountTryUserPrivateKey failed: %@", error); + CFReleaseNull(error); + return; + } + + success = true; + secnotice("pairing", "SOSAccountTryUserPrivateKey succeeded"); - if (!SOSAccountTryUserPrivateKey(self, accountPrivateKey, &error)) { - CFReleaseNull(accountPrivateKey); - complete(false, (__bridge NSError *)error); - secnotice("pairing", "SOSAccountTryUserPrivateKey failed: %@", error); - CFReleaseNull(error); - return; + CFReleaseNull(accountPrivateKey); + complete(true, NULL); + }]; + + // This makes getting the private key the same as Asserting the password - we read all the other things + // that we just expressed interest in. + + if(success) { + CFErrorRef localError = NULL; + if (!Flush(&localError)) { + // we're still setup with the private key - just report this. + secnotice("pairing", "failed final flush: %@", localError); + } + CFReleaseNull(localError); + } } - - secnotice("pairing", "SOSAccountTryUserPrivateKey succeeded"); - - CFReleaseNull(accountPrivateKey); - complete(true, NULL); - }]; - - // This makes getting the private key the same as Asserting the password - we read all the other things - // that we just expressed interest in. - CFErrorRef error = NULL; - if (!Flush(&error)) { - secnotice("pairing", "failed final flush: %@", error ? error : NULL); - return; - } - CFReleaseNull(error); + }); } - (void)myPeerInfo:(void (^)(NSData *, NSError *))complete @@ -613,6 +644,75 @@ static bool Flush(CFErrorRef *error) { complete(json, err); } +- (void) iCloudIdentityStatus_internal: (void(^)(NSDictionary *tableSpid, NSError *error))complete { + CFErrorRef localError = NULL; + NSMutableDictionary *tableSPID = [NSMutableDictionary new]; + + if(![self isInCircle: &localError]) { + complete(tableSPID, (__bridge NSError *)localError); + return; + } + + // Make set of SPIDs for iCloud Identity PeerInfos + NSMutableSet *peerInfoSPIDs = [[NSMutableSet alloc] init]; + SOSCircleForEachiCloudIdentityPeer(self.trust.trustedCircle , ^(SOSPeerInfoRef peer) { + NSString *peerID = CFBridgingRelease(CFStringCreateCopy(kCFAllocatorDefault, SOSPeerInfoGetPeerID(peer))); + if(peerID) { + [ peerInfoSPIDs addObject:peerID]; + } + }); + + // Make set of SPIDs for iCloud Identity Private Keys + NSMutableSet *privateKeySPIDs = [[NSMutableSet alloc] init]; + SOSiCloudIdentityPrivateKeyForEach(^(SecKeyRef privKey) { + CFErrorRef localError = NULL; + CFStringRef keyID = SOSCopyIDOfKey(privKey, &localError); + if(keyID) { + NSString *peerID = CFBridgingRelease(keyID); + [ privateKeySPIDs addObject:peerID]; + } else { + secnotice("iCloudIdentity", "couldn't make ID from key (%@)", localError); + } + CFReleaseNull(localError); + }); + + NSMutableSet *completeIdentity = [peerInfoSPIDs mutableCopy]; + if([peerInfoSPIDs count] > 0 && [privateKeySPIDs count] > 0) { + [ completeIdentity intersectSet:privateKeySPIDs]; + } else { + completeIdentity = nil; + } + + NSMutableSet *keyOnly = [privateKeySPIDs mutableCopy]; + if([peerInfoSPIDs count] > 0 && [keyOnly count] > 0) { + [ keyOnly minusSet: peerInfoSPIDs ]; + } + + NSMutableSet *peerOnly = [peerInfoSPIDs mutableCopy]; + if([peerOnly count] > 0 && [privateKeySPIDs count] > 0) { + [ peerOnly minusSet: privateKeySPIDs ]; + } + + tableSPID[kSOSIdentityStatusCompleteIdentity] = [completeIdentity allObjects]; + tableSPID[kSOSIdentityStatusKeyOnly] = [keyOnly allObjects]; + tableSPID[kSOSIdentityStatusPeerOnly] = [peerOnly allObjects]; + + complete(tableSPID, nil); +} + +- (void)iCloudIdentityStatus: (void (^)(NSData *json, NSError *error))complete { + [self iCloudIdentityStatus_internal:^(NSDictionary *tableSpid, NSError *error) { + NSError *err = nil; + NSData *json = [NSJSONSerialization dataWithJSONObject:tableSpid + options:(NSJSONWritingPrettyPrinted | NSJSONWritingSortedKeys) + error:&err]; + if (!json) { + secnotice("iCloudIdentity", "Error during iCloudIdentityStatus JSONification: %@", err.localizedDescription); + } + complete(json, err); + }]; +} + #else + (SOSAccountGhostBustingOptions) ghostBustGetRampSettings { @@ -649,7 +749,16 @@ static bool Flush(CFErrorRef *error) { return false; } -#endif +- (void)iCloudIdentityStatus:(void (^)(NSData *, NSError *))complete { + complete(nil, nil); +} + + +- (void)iCloudIdentityStatus_internal:(void (^)(NSDictionary *, NSError *))complete { + complete(nil, nil); +} + +#endif // !(TARGET_OS_OSX || TARGET_OS_IOS) - (void)circleJoiningBlob:(NSData *)applicant complete:(void (^)(NSData *blob, NSError *))complete { @@ -715,7 +824,7 @@ static bool Flush(CFErrorRef *error) { CFReleaseNull(error); } -- (void)triggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete +- (void)rpcTriggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete { __block CFErrorRef localError = NULL; __block bool res = false; @@ -740,7 +849,7 @@ static bool Flush(CFErrorRef *error) { CFReleaseNull(localError); } -- (void)triggerBackup:(NSArray* _Nullable)backupPeers complete:(void (^)(NSError *error))complete +- (void)rpcTriggerBackup:(NSArray* _Nullable)backupPeers complete:(void (^)(NSError *error))complete { __block CFErrorRef localError = NULL; @@ -757,6 +866,14 @@ static bool Flush(CFErrorRef *error) { CFReleaseNull(localError); } +- (void)rpcTriggerRingUpdate:(void (^)(NSError *error))complete +{ +#if OCTAGON + [self triggerRingUpdate]; +#endif + complete(NULL); +} + - (void)getWatchdogParameters:(void (^)(NSDictionary* parameters, NSError* error))complete { // SecdWatchdog is only available in the secd/securityd - no other binary will contain that class @@ -832,6 +949,17 @@ void SOSAccountAssertDSID(SOSAccount* account, CFStringRef dsid) { } } +SecKeyRef SOSAccountCopyDevicePrivateKey(SOSAccount* account, CFErrorRef *error) { + if(account.peerPublicKey) { + return SecKeyCopyMatchingPrivateKey(account.peerPublicKey, error); + } + return NULL; +} + +SecKeyRef SOSAccountCopyDevicePublicKey(SOSAccount* account, CFErrorRef *error) { + return SecKeyCopyPublicKey(account.peerPublicKey); +} + void SOSAccountPendDisableViewSet(SOSAccount* account, CFSetRef disabledViews) { @@ -862,10 +990,10 @@ SOSAccount* SOSAccountCreate(CFAllocatorRef allocator, SOSDataSourceFactoryRef factory) { SOSAccount* a = [[SOSAccount alloc] initWithGestalt:gestalt factory:factory]; - [a ensureFactoryCircles]; - SOSAccountEnsureUUID(a); - secnotice("circleop", "Setting account.key_interests_need_updating to true in SOSAccountCreate"); - a.key_interests_need_updating = true; + dispatch_sync(a.queue, ^{ + secnotice("circleop", "Setting account.key_interests_need_updating to true in SOSAccountCreate"); + a.key_interests_need_updating = true; + }); return a; } @@ -970,7 +1098,6 @@ void SOSAccountSetToNew(SOSAccount* a) result = do_keychain_delete_sbd(); (void) result; secdebug("set to new", "result for deleting sbd: %d", result); - a.accountKeyIsTrusted = false; if (a.user_private_timer) { dispatch_source_cancel(a.user_private_timer); @@ -995,11 +1122,30 @@ void SOSAccountSetToNew(SOSAccount* a) a.circle_transport = NULL; a.kvs_message_transport = nil; + a._password_tmp = nil; + a.circle_rings_retirements_need_attention = true; + a.engine_peer_state_needs_repair = true; + a.key_interests_need_updating = true; + a.need_backup_peers_created_after_backup_key_set = true; + + a.accountKeyIsTrusted = false; + a.accountKeyDerivationParameters = nil; + a.accountPrivateKey = NULL; + a.accountKey = NULL; + a.previousAccountKey = NULL; + a.peerPublicKey = NULL; + a.backup_key = nil; + a.notifyCircleChangeOnExit = true; + a.notifyViewChangeOnExit = true; + a.notifyBackupOnExit = true; + + a.octagonSigningFullKeyRef = NULL; + a.octagonEncryptionFullKeyRef = NULL; a.trust = nil; + // setting a new trust object resets all the rings from this peer's point of view - they're in the SOSAccountTrustClassic dictionary a.trust = [[SOSAccountTrustClassic alloc]initWithRetirees:[NSMutableSet set] fpi:NULL circle:NULL departureCode:kSOSDepartureReasonError peerExpansion:[NSMutableDictionary dictionary]]; - - [a ensureFactoryCircles]; // Does rings too + [a ensureFactoryCircles]; // By resetting our expansion dictionary we've reset our UUID, so we'll be notified properly SOSAccountEnsureUUID(a); @@ -1121,50 +1267,24 @@ void SOSAccountRemoveChangeBlock(SOSAccount* a, SOSAccountCircleMembershipChang void SOSAccountPurgeIdentity(SOSAccount* account) { SOSAccountTrustClassic *trust = account.trust; - SOSFullPeerInfoRef identity = trust.fullPeerInfo; - - if (identity) { - // Purge private key but don't return error if we can't. - CFErrorRef purgeError = NULL; - if (!SOSFullPeerInfoPurgePersistentKey(identity, &purgeError)) { - secwarning("Couldn't purge persistent key for %@ [%@]", identity, purgeError); - } - CFReleaseNull(purgeError); - - trust.fullPeerInfo = nil; - } + [trust purgeIdentity]; } -bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, NSData* parentData, CFErrorRef* error) { +bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, CFErrorRef* error) { SOSAccountTrustClassic *trust = account.trust; SOSFullPeerInfoRef identity = trust.fullPeerInfo; NSMutableSet* retirees = trust.retirees; NSError* localError = nil; - SFSignInAnalytics* parent = nil; - - if(parentData) { - parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentData error:&localError]; - } - SOSFullPeerInfoRef fpi = identity; if(!fpi) return false; CFErrorRef retiredError = NULL; bool retval = false; - - SFSignInAnalytics *promoteToRetiredEvent = nil; - - if(parent) { - promoteToRetiredEvent = [parent newSubTaskForEvent:@"promoteToRetiredEvent"]; - } SOSPeerInfoRef retire_peer = SOSFullPeerInfoPromoteToRetiredAndCopy(fpi, &retiredError); if(retiredError){ - if(promoteToRetiredEvent) { - [promoteToRetiredEvent logRecoverableError:(__bridge NSError*)retiredError]; - } secerror("SOSFullPeerInfoPromoteToRetiredAndCopy error: %@", retiredError); if(error){ *error = retiredError; @@ -1172,9 +1292,6 @@ bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, NSData* par CFReleaseNull(retiredError); } } - if(promoteToRetiredEvent) { - [promoteToRetiredEvent stopWithAttributes:nil]; - } if (!retire_peer) { secerror("Create ticket failed for peer %@: %@", fpi, localError); @@ -1186,17 +1303,9 @@ bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, NSData* par } else if (SOSCircleHasPeer(circle, retire_peer, NULL)) { if (SOSCircleUpdatePeerInfo(circle, retire_peer)) { CFErrorRef cleanupError = NULL; - SFSignInAnalytics *cleanupEvent = nil; - - if(parent) { - cleanupEvent = [parent newSubTaskForEvent:@"cleanupAfterPeerEvent"]; - } if (![account.trust cleanupAfterPeer:account.kvs_message_transport circleTransport:account.circle_transport seconds:RETIREMENT_FINALIZATION_SECONDS circle:circle cleanupPeer:retire_peer err:&cleanupError]) { secerror("Error cleanup up after peer (%@): %@", retire_peer, cleanupError); } - if(cleanupEvent) { - [cleanupEvent stopWithAttributes:nil]; - } CFReleaseSafe(cleanupError); } } @@ -1208,46 +1317,22 @@ bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, NSData* par // Write retirement to Transport CFErrorRef postError = NULL; - SFSignInAnalytics *postRetirementEvent = nil; - - if(parent) { - postRetirementEvent = [parent newSubTaskForEvent:@"postRestirementEvent"]; - } - if(![account.circle_transport postRetirement:SOSCircleGetName(circle) peer:retire_peer err:&postError]){ - if(postRetirementEvent) { - [postRetirementEvent logRecoverableError:(__bridge NSError*)postError]; - } + secwarning("Couldn't post retirement (%@)", postError); } - if(postRetirementEvent) { - [postRetirementEvent stopWithAttributes:nil]; - } - SFSignInAnalytics *flushChangesEvent = nil; - if(parent) { - flushChangesEvent = [parent newSubTaskForEvent:@"flushChangesEvent"]; - } + if(![account.circle_transport flushChanges:&postError]){ - if(flushChangesEvent) { - [flushChangesEvent logRecoverableError:(__bridge NSError*)postError]; - } secwarning("Couldn't flush retirement data (%@)", postError); } - if(flushChangesEvent) { - [flushChangesEvent stopWithAttributes:nil]; - } + CFReleaseNull(postError); } - SFSignInAnalytics *purgeIdentityEvent = nil; - if(parent) { - purgeIdentityEvent = [parent newSubTaskForEvent:@"purgeIdentityEvent"]; - } + SOSAccountPurgeIdentity(account); - if(purgeIdentityEvent) { - [purgeIdentityEvent stopWithAttributes:nil]; - } + retval = true; CFReleaseNull(retire_peer); @@ -1345,26 +1430,28 @@ bool SOSAccountRemoveIncompleteiCloudIdentities(SOSAccount* account, SOSCircleR // -bool SOSAccountEnsureInBackupRings(SOSAccount* account) { +- (bool)_onQueueEnsureInBackupRings { __block bool result = false; __block CFErrorRef error = NULL; secnotice("backup", "Ensuring in rings"); - if(!account.backup_key){ + dispatch_assert_queue(self.queue); + + if(!self.backup_key){ return true; } - if(!SOSBSKBIsGoodBackupPublic((__bridge CFDataRef)account.backup_key, &error)){ + if(!SOSBSKBIsGoodBackupPublic((__bridge CFDataRef)self.backup_key, &error)){ secnotice("backupkey", "account backup key isn't valid: %@", error); - account.backup_key = nil; + self.backup_key = nil; CFReleaseNull(error); return false; } - NSData *peerBackupKey = (__bridge_transfer NSData*)SOSPeerInfoCopyBackupKey(account.peerInfo); - if(![peerBackupKey isEqual:account.backup_key]) { - result = SOSAccountUpdatePeerInfo(account, CFSTR("Backup public key"), &error, ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *error) { - return SOSFullPeerInfoUpdateBackupKey(fpi, (__bridge CFDataRef)(account.backup_key), error); + NSData *peerBackupKey = (__bridge_transfer NSData*)SOSPeerInfoCopyBackupKey(self.peerInfo); + if(![peerBackupKey isEqual:self.backup_key]) { + result = SOSAccountUpdatePeerInfo(self, CFSTR("Backup public key"), &error, ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *error) { + return SOSFullPeerInfoUpdateBackupKey(fpi, (__bridge CFDataRef)(self.backup_key), error); }); if (!result) { secnotice("backupkey", "Failed to setup backup public key in peerInfo from account: %@", error); @@ -1381,12 +1468,12 @@ bool SOSAccountEnsureInBackupRings(SOSAccount* account) { CFReleaseNull(localError); // Setup backups the new way. - SOSAccountForEachBackupView(account, ^(const void *value) { + SOSAccountForEachBackupView(self, ^(const void *value) { CFStringRef viewName = asString(value, NULL); - bool resetRing = SOSAccountValidateBackupRingForView(account, viewName, NULL); + bool resetRing = SOSAccountValidateBackupRingForView(self, viewName, NULL); if(resetRing) { - SOSAccountUpdateBackupRing(account, viewName, NULL, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) { - SOSRingRef newRing = SOSAccountCreateBackupRingForView(account, viewName, error); + SOSAccountUpdateBackupRing(self, viewName, NULL, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) { + SOSRingRef newRing = SOSAccountCreateBackupRingForView(self, viewName, error); return newRing; }); } @@ -1436,27 +1523,14 @@ CFDataRef SOSAccountCopyRecoveryPublicKey(SOSAccountTransaction* txn, CFErrorRef // MARK: Joining // -static bool SOSAccountJoinCircle(SOSAccountTransaction* aTxn, SecKeyRef user_key, bool use_cloud_peer, NSData* parentEvent, CFErrorRef* error) { +static bool SOSAccountJoinCircle(SOSAccountTransaction* aTxn, SecKeyRef user_key, bool use_cloud_peer, CFErrorRef* error) { SOSAccount* account = aTxn.account; SOSAccountTrustClassic *trust = account.trust; __block bool result = false; __block SOSFullPeerInfoRef cloud_full_peer = NULL; - SFSignInAnalytics *ensureFullPeerAvailableEvent = nil; - NSError* localError = nil; - SFSignInAnalytics* parent = nil; - - if(parentEvent) { - parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError]; - } - require_action_quiet(trust.trustedCircle, fail, SOSCreateErrorWithFormat(kSOSErrorPeerNotFound, NULL, error, NULL, CFSTR("Don't have circle when joining???"))); - if(parent) { - ensureFullPeerAvailableEvent = [parent newSubTaskForEvent:@"ensureFullPeerAvailableEvent"]; - } - require_quiet([account.trust ensureFullPeerAvailable:(__bridge CFDictionaryRef)account.gestalt deviceID:(__bridge CFStringRef)account.deviceID backupKey:(__bridge CFDataRef)account.backup_key err:error], fail); - if(ensureFullPeerAvailableEvent) { - [ensureFullPeerAvailableEvent stopWithAttributes:nil]; - } + + require_quiet([account.trust ensureFullPeerAvailable: account err:error], fail); SOSFullPeerInfoRef myCirclePeer = trust.fullPeerInfo; if (SOSCircleCountPeers(trust.trustedCircle) == 0 || SOSAccountGhostResultsInReset(account)) { @@ -1464,15 +1538,11 @@ static bool SOSAccountJoinCircle(SOSAccountTransaction* aTxn, SecKeyRef user_key // this also clears initial sync data result = [account.trust resetCircleToOffering:aTxn userKey:user_key err:error]; } else { - SFSignInAnalytics *acceptApplicantEvent = nil; - SOSAccountInitializeInitialSync(account); if (use_cloud_peer) { cloud_full_peer = SOSCircleCopyiCloudFullPeerInfoRef(trust.trustedCircle, NULL); } - if(parent) { - acceptApplicantEvent = [parent newSubTaskForEvent:@"acceptApplicantEvent"]; - } + [account.trust modifyCircle:account.circle_transport err:error action:^bool(SOSCircleRef circle) { result = SOSAccountAddEscrowToPeerInfo(account, myCirclePeer, error); result &= SOSCircleRequestAdmission(circle, user_key, myCirclePeer, error); @@ -1485,24 +1555,15 @@ static bool SOSAccountJoinCircle(SOSAccountTransaction* aTxn, SecKeyRef user_key require_quiet(SOSCircleAcceptRequest(circle, user_key, cloud_full_peer, SOSFullPeerInfoGetPeerInfo(myCirclePeer), &localError), finish); finish: if (localError){ - if(acceptApplicantEvent) { - [acceptApplicantEvent logRecoverableError:(__bridge NSError *)(localError)]; - } secerror("Failed to join with cloud identity: %@", localError); CFReleaseNull(localError); } } return result; }]; - if(acceptApplicantEvent) { - [acceptApplicantEvent stopWithAttributes:nil]; - } + if (use_cloud_peer) { SOSAccountUpdateOutOfSyncViews(aTxn, SOSViewsGetAllCurrent()); - if(acceptApplicantEvent) { - SFSignInAnalytics *updateOutOfDateSyncViewsEvent = [acceptApplicantEvent newSubTaskForEvent:@"updateOutOfDateSyncViewsEvent"]; - [updateOutOfDateSyncViewsEvent stopWithAttributes:nil]; - } } } fail: @@ -1510,7 +1571,7 @@ fail: return result; } -static bool SOSAccountJoinCircles_internal(SOSAccountTransaction* aTxn, bool use_cloud_identity, NSData* parentEvent, CFErrorRef* error) { +static bool SOSAccountJoinCircles_internal(SOSAccountTransaction* aTxn, bool use_cloud_identity, CFErrorRef* error) { SOSAccount* account = aTxn.account; SOSAccountTrustClassic *trust = account.trust; bool success = false; @@ -1548,7 +1609,7 @@ static bool SOSAccountJoinCircles_internal(SOSAccountTransaction* aTxn, bool use } } - success = SOSAccountJoinCircle(aTxn, user_key, use_cloud_identity, parentEvent, error); + success = SOSAccountJoinCircle(aTxn, user_key, use_cloud_identity, error); require_quiet(success, done); @@ -1558,37 +1619,29 @@ done: return success; } -bool SOSAccountJoinCircles(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error) { +bool SOSAccountJoinCircles(SOSAccountTransaction* aTxn, CFErrorRef* error) { secnotice("circleOps", "Normal path circle join (SOSAccountJoinCircles)"); - return SOSAccountJoinCircles_internal(aTxn, false, parentEvent, error); + return SOSAccountJoinCircles_internal(aTxn, false, error); } -bool SOSAccountJoinCirclesAfterRestore(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error) { +bool SOSAccountJoinCirclesAfterRestore(SOSAccountTransaction* aTxn, CFErrorRef* error) { secnotice("circleOps", "Joining after restore (SOSAccountJoinCirclesAfterRestore)"); - return SOSAccountJoinCircles_internal(aTxn, true, parentEvent, error); + return SOSAccountJoinCircles_internal(aTxn, true, error); } -bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, NSData* parentEvent, CFErrorRef* error) +bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, CFErrorRef* error) { - - NSError* localError = nil; - SFSignInAnalytics* parent = nil; - - if(parentEvent) { - parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError]; - } - bool result = false; CFMutableSetRef peersToRemove = NULL; SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); - if(!user_key){ + if (!user_key) { secnotice("circleOps", "Can't remove without userKey"); return result; } + SOSFullPeerInfoRef me_full = account.fullPeerInfo; SOSPeerInfoRef me = account.peerInfo; - if(!(me_full && me)) - { + if (!(me_full && me)) { secnotice("circleOps", "Can't remove without being active peer"); SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("Can't remove without being active peer")); return result; @@ -1597,8 +1650,7 @@ bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, NSD result = true; // beyond this point failures would be rolled up in AccountModifyCircle. peersToRemove = CFSetCreateMutableForSOSPeerInfosByIDWithArray(kCFAllocatorDefault, peers); - if(!peersToRemove) - { + if (!peersToRemove) { CFReleaseNull(peersToRemove); secnotice("circleOps", "No peerSet to remove"); return result; @@ -1611,29 +1663,16 @@ bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, NSD result &= [account.trust modifyCircle:account.circle_transport err:error action:^(SOSCircleRef circle) { bool success = false; - if(CFSetGetCount(peersToRemove) != 0) { + if (CFSetGetCount(peersToRemove) != 0) { require_quiet(SOSCircleRemovePeers(circle, user_key, me_full, peersToRemove, error), done); - - SFSignInAnalytics *generationSignatureUpdateEvent = nil; - if(parent) { - generationSignatureUpdateEvent = [parent newSubTaskForEvent:@"generationSignatureUpdateEvent"]; - } - success = SOSAccountGenerationSignatureUpdate(account, error); - if(error && *error){ - NSError* signatureUpdateError = (__bridge NSError*)*error; - if(generationSignatureUpdateEvent) { - [generationSignatureUpdateEvent logUnrecoverableError:signatureUpdateError]; - } - } - if(generationSignatureUpdateEvent) { - [generationSignatureUpdateEvent stopWithAttributes:nil]; - } - } else success = true; + } else { + success = true; + } if (success && leaveCircle) { secnotice("circleOps", "Leaving circle by client request (SOSAccountRemovePeersFromCircle)"); - success = sosAccountLeaveCircle(account, circle, parentEvent, error); + success = sosAccountLeaveCircle(account, circle, error); } done: @@ -1641,7 +1680,7 @@ bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, NSD }]; - if(result) { + if (result) { CFStringSetPerformWithDescription(peersToRemove, ^(CFStringRef description) { secnotice("circleOps", "Removed Peers from circle %@", description); }); @@ -1652,7 +1691,7 @@ bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, NSD } bool SOSAccountBail(SOSAccount* account, uint64_t limit_in_seconds, CFErrorRef* error) { - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_queue_t queue = dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0); dispatch_group_t group = dispatch_group_create(); SOSAccountTrustClassic *trust = account.trust; __block bool result = false; @@ -1661,7 +1700,7 @@ bool SOSAccountBail(SOSAccount* account, uint64_t limit_in_seconds, CFErrorRef* dispatch_group_async(group, queue, ^{ [trust modifyCircle:account.circle_transport err:error action:^(SOSCircleRef circle) { secnotice("circleOps", "Leaving circle by client request (Bail)"); - return sosAccountLeaveCircle(account, circle, nil, error); + return sosAccountLeaveCircle(account, circle, error); }]; }); dispatch_time_t milestone = dispatch_time(DISPATCH_TIME_NOW, limit_in_seconds * NSEC_PER_SEC); @@ -1672,7 +1711,6 @@ bool SOSAccountBail(SOSAccount* account, uint64_t limit_in_seconds, CFErrorRef* return result; } - // // MARK: Application // @@ -1806,7 +1844,7 @@ bool SOSAccountEnsurePeerRegistration(SOSAccount* account, CFErrorRef *error) { SOSEngineInitializePeerCoder((SOSEngineRef)[account.kvs_message_transport SOSTransportMessageGetEngine], trust.fullPeerInfo, peer, &localError); if (localError) secnotice("updates", "can't initialize transport for peer %@ with %@ (%@)", peer, trust.fullPeerInfo, localError); - CFReleaseSafe(localError); + CFReleaseNull(localError); } }); @@ -1825,8 +1863,6 @@ CFTypeRef SOSAccountGetValue(SOSAccount* account, CFStringRef key, CFErrorRef * return (__bridge CFTypeRef)([trust.expansion objectForKey:(__bridge NSString* _Nonnull)(key)]); } - - bool SOSAccountAddEscrowToPeerInfo(SOSAccount* account, SOSFullPeerInfoRef myPeer, CFErrorRef *error){ bool success = false; @@ -1836,13 +1872,16 @@ bool SOSAccountAddEscrowToPeerInfo(SOSAccount* account, SOSFullPeerInfoRef myPe return success; } -void SOSAccountRecordRetiredPeersInCircle(SOSAccount* account) { - if (![account isInCircle:NULL]) { +- (void)_onQueueRecordRetiredPeersInCircle { + + dispatch_assert_queue(self.queue); + + if (![self isInCircle:NULL]) { return; } __block bool updateRings = false; - SOSAccountTrustClassic *trust = account.trust; - [trust modifyCircle:account.circle_transport err:NULL action:^bool (SOSCircleRef circle) { + SOSAccountTrustClassic *trust = self.trust; + [trust modifyCircle:self.circle_transport err:NULL action:^bool (SOSCircleRef circle) { __block bool updated = false; CFSetForEach((__bridge CFMutableSetRef)trust.retirees, ^(CFTypeRef element){ SOSPeerInfoRef retiree = asSOSPeerInfo(element); @@ -1851,7 +1890,7 @@ void SOSAccountRecordRetiredPeersInCircle(SOSAccount* account) { updated = true; secnotice("retirement", "Updated retired peer %@ in %@", retiree, circle); CFErrorRef cleanupError = NULL; - if (![account.trust cleanupAfterPeer:account.kvs_message_transport circleTransport:account.circle_transport seconds:RETIREMENT_FINALIZATION_SECONDS circle:circle cleanupPeer:retiree err:&cleanupError]) + if (![self.trust cleanupAfterPeer:self.kvs_message_transport circleTransport:self.circle_transport seconds:RETIREMENT_FINALIZATION_SECONDS circle:circle cleanupPeer:retiree err:&cleanupError]) secerror("Error cleanup up after peer (%@): %@", retiree, cleanupError); CFReleaseSafe(cleanupError); updateRings = true; @@ -1860,7 +1899,7 @@ void SOSAccountRecordRetiredPeersInCircle(SOSAccount* account) { return updated; }]; if(updateRings) { - SOSAccountProcessBackupRings(account, NULL); + SOSAccountProcessBackupRings(self); } } @@ -1937,7 +1976,7 @@ static void SOSAccountWriteLastCleanupTimestampToKVS(SOSAccount* account) dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); - dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_queue_t processQueue = dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0); CloudKeychainReplyBlock replyBlock = ^ (CFDictionaryRef returnedValues, CFErrorRef error){ if (error){ @@ -1965,7 +2004,7 @@ bool SOSAccountCleanupAllKVSKeys(SOSAccount* account, CFErrorRef* error) return true; } - dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_queue_t processQueue = dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0); NSDictionary *keysAndValues = (__bridge_transfer NSDictionary*)SOSAccountGetObjectsFromCloud(processQueue, error); NSMutableArray *peerIDs = [NSMutableArray array]; @@ -2014,7 +2053,7 @@ SOSPeerInfoRef SOSAccountCopyApplication(SOSAccount* account, CFErrorRef* error SOSAccountTrustClassic *trust = account.trust; SecKeyRef userKey = SOSAccountGetPrivateCredential(account, error); if(!userKey) return false; - if(![trust ensureFullPeerAvailable:(__bridge CFDictionaryRef)(account.gestalt) deviceID:(__bridge CFStringRef)(account.deviceID) backupKey:(__bridge CFDataRef)(account.backup_key) err:error]) + if(![trust ensureFullPeerAvailable:account err:error]) return applicant; if(!SOSFullPeerInfoPromoteToApplication(trust.fullPeerInfo, userKey, error)) return applicant; @@ -2023,6 +2062,36 @@ SOSPeerInfoRef SOSAccountCopyApplication(SOSAccount* account, CFErrorRef* error return applicant; } +#if OCTAGON +static void +AddStrippedTLKs(NSMutableArray* results, NSArray* tlks, NSMutableSet *seenUUID, bool authoritative) +{ + for(CKKSKeychainBackedKey* tlk in tlks) { + NSError* localerror = nil; + CKKSAESSIVKey* keyBytes = [tlk ensureKeyLoaded:&localerror]; + + if(!keyBytes || localerror) { + secnotice("piggy", "Failed to load TLK %@: %@", tlk, localerror); + continue; + } + + NSMutableDictionary* strippedDown = [@{ + (id)kSecValueData : [keyBytes keyMaterial], + (id)kSecAttrServer : tlk.zoneID.zoneName, + (id)kSecAttrAccount : tlk.uuid, + } mutableCopy]; + + if (authoritative) { + strippedDown[@"auth"] = @YES; + } + + secnotice("piggy", "sending TLK %@", tlk); + + [results addObject:strippedDown]; + [seenUUID addObject:tlk.uuid]; + } +} +#endif static void AddStrippedResults(NSMutableArray *results, NSArray *keychainItems, NSMutableSet *seenUUID, bool authoriative) @@ -2064,34 +2133,32 @@ AddStrippedResults(NSMutableArray *results, NSArray *keychainItems, NSMutableSet } static void -AddViewManagerResults(NSMutableArray *results, NSMutableSet *seenUUID) +AddViewManagerResults(NSMutableArray *results, NSMutableSet *seenUUID, bool selectedTLKsOnly) { #if OCTAGON - CKKSViewManager* manager = [CKKSViewManager manager]; - - NSDictionary *items = [manager activeTLKs]; - - for (NSString *view in items) { - NSString *uuid = items[view]; - NSDictionary *query = @{ - (id)kSecClass : (id)kSecClassInternetPassword, - (id)kSecUseDataProtectionKeychain : @YES, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccount : uuid, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - (id)kSecMatchLimit : (id)kSecMatchLimitAll, - (id)kSecReturnAttributes: @YES, - (id)kSecReturnData: @YES, - }; - CFTypeRef result = NULL; - if (SecItemCopyMatching((__bridge CFDictionaryRef)query, &result) == 0) { - AddStrippedResults(results, (__bridge NSArray*)result, seenUUID, true); - } - CFReleaseNull(result); + NSError* localError = nil; + NSArray* tlks = [[CKKSViewManager manager] currentTLKsFilteredByPolicy:selectedTLKsOnly error:&localError]; + + if(localError) { + secnotice("piggy", "unable to fetch TLKs: %@", localError); + return; } + + AddStrippedTLKs(results, tlks, seenUUID, true); #endif } +NSArray* +SOSAccountGetSelectedTLKs(void) +{ + NSMutableArray* results = [NSMutableArray array]; + NSMutableSet *seenUUID = [NSMutableSet set]; + + AddViewManagerResults(results, seenUUID, true); + + return results; +} + NSArray* SOSAccountGetAllTLKs(void) @@ -2100,8 +2167,8 @@ SOSAccountGetAllTLKs(void) NSMutableArray* results = [NSMutableArray array]; NSMutableSet *seenUUID = [NSMutableSet set]; - // first use the TLK from the view manager - AddViewManagerResults(results, seenUUID); + // first use all TLKs from the view manager + AddViewManagerResults(results, seenUUID, false); //try to grab tlk-piggy items NSDictionary* query = @{ @@ -2386,22 +2453,27 @@ CFDataRef SOSAccountCopyInitialSyncData(SOSAccount* account, SOSInitialSyncFlags NSMutableArray* encodedIdenities = [NSMutableArray array]; NSArray* tlks = nil; - if (flags & kSOSInitialSyncFlagiCloudIdentity) { - CFMutableArrayRef identities = SOSAccountCopyiCloudIdentities(account); - secnotice("piggy", "identities: %@", identities); - - CFIndex i, count = CFArrayGetCount(identities); - for (i = 0; i < count; i++) { - SOSPeerInfoRef fpi = (SOSPeerInfoRef)CFArrayGetValueAtIndex(identities, i); - NSData *data = CFBridgingRelease(SOSPeerInfoCopyData(fpi, error)); - if (data) - [encodedIdenities addObject:data]; + if (flags & kSOSInitialSyncFlagTLKsRequestOnly) { + tlks = SOSAccountGetSelectedTLKs(); + } else { + if (flags & kSOSInitialSyncFlagiCloudIdentity) { + CFMutableArrayRef identities = SOSAccountCopyiCloudIdentities(account); + secnotice("piggy", "identities: %@", identities); + + CFIndex i, count = CFArrayGetCount(identities); + for (i = 0; i < count; i++) { + SOSPeerInfoRef fpi = (SOSPeerInfoRef)CFArrayGetValueAtIndex(identities, i); + NSData *data = CFBridgingRelease(SOSPeerInfoCopyData(fpi, error)); + if (data) + [encodedIdenities addObject:data]; + } + CFRelease(identities); } - CFRelease(identities); - } - if (flags & kSOSInitialSyncFlagTLKs) { - tlks = SOSAccountGetAllTLKs(); + + if (flags & kSOSInitialSyncFlagTLKs) { + tlks = SOSAccountGetAllTLKs(); + } } return CFBridgingRetain(SOSPiggyCreateInitialSyncData(encodedIdenities, tlks)); @@ -2552,10 +2624,10 @@ void SOSAccountLogState(SOSAccount* account) { secnotice(ACCOUNTLOGSTATE, "Start"); - secnotice(ACCOUNTLOGSTATE, "ACCOUNT: [keyStatus: %c%c%c hpub %@] [SOSCCStatus: %@]", + secnotice(ACCOUNTLOGSTATE, "ACCOUNT: [keyStatus: %c%c%c hpub %@] [SOSCCStatus: %@] [UID: %d EUID: %d]", boolToChars(hasPubKey, 'U', 'u'), boolToChars(pubTrusted, 'T', 't'), boolToChars(hasPriv, 'I', 'i'), userPubKeyID, - SOSAccountGetSOSCCStatusString(stat) + SOSAccountGetSOSCCStatusString(stat), getuid(), geteuid() ); CFReleaseNull(userPubKeyID); if(trust.trustedCircle) SOSCircleLogState(ACCOUNTLOGSTATE, trust.trustedCircle, account.accountKey, (__bridge CFStringRef)(account.peerID)); @@ -2601,7 +2673,6 @@ void SOSAccountResetOTRNegotiationCoder(SOSAccount* account, CFStringRef peerid) { secnotice("otrtimer", "timer fired!"); CFErrorRef error = NULL; - SecADAddValueForScalarKey((__bridge CFStringRef) SecSOSAggdReattemptOTRNegotiation,1); SOSEngineRef engine = SOSDataSourceFactoryGetEngineForDataSourceName(account.factory, SOSCircleGetName(account.trust.trustedCircle), NULL); SOSEngineWithPeerID(engine, peerid, &error, ^(SOSPeerRef peer, SOSCoderRef coder, SOSDataSourceRef dataSource, SOSTransactionRef txn, bool *forceSaveState) { @@ -2674,10 +2745,12 @@ void SOSAccountTimerFiredSendNextMessage(SOSAccountTransaction* txn, NSString* p */ OctagonFlag* SOSFlagTriggerBackup = (OctagonFlag*)@"trigger_backup"; +OctagonFlag* SOSFlagTriggerRingUpdate = (OctagonFlag*)@"trigger_ring_update"; OctagonState* SOSStateReady = (OctagonState*)@"ready"; OctagonState* SOSStateError = (OctagonState*)@"error"; OctagonState* SOSStatePerformBackup = (OctagonState*)@"perform_backup"; +OctagonState* SOSStatePerformRingUpdate = (OctagonState*)@"perform_ring_update"; static NSDictionary* SOSStateMap(void) { static NSDictionary* map = nil; @@ -2687,6 +2760,7 @@ static NSDictionary* SOSStateMap(void) { SOSStateReady: @0U, SOSStateError: @1U, SOSStatePerformBackup: @2U, + SOSStatePerformRingUpdate: @3U, }; }); return map; @@ -2697,7 +2771,8 @@ static NSSet* SOSFlagsSet(void) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ set = [NSSet setWithArray:@[ - SOSFlagTriggerBackup + SOSFlagTriggerBackup, + SOSFlagTriggerRingUpdate, ]]; }); return set; @@ -2706,7 +2781,7 @@ static NSSet* SOSFlagsSet(void) { + (NSURL *)urlForSOSAccountSettings { - return (__bridge NSURL *)SecCopyURLForFileInKeychainDirectory(CFSTR("SOSAccountSettings.pb")); + return (__bridge_transfer NSURL *)SecCopyURLForFileInKeychainDirectory(CFSTR("SOSAccountSettings.pb")); } @@ -2714,9 +2789,9 @@ static NSSet* SOSFlagsSet(void) { WEAKIFY(self); self.accountConfiguration = [[CKKSPBFileStorage alloc] initWithStoragePath:[[self class] urlForSOSAccountSettings] - storageClass:[SOSAccountConfiguration class]]; + storageClass:[SOSAccountConfiguration class]]; - NSAssert(self.stateMachine == nil, @"cant bootstrap more the once"); + NSAssert(self.stateMachine == nil, @"can't bootstrap more than once"); self.stateMachineQueue = dispatch_queue_create("SOS-statemachine", NULL); @@ -2739,50 +2814,155 @@ static NSSet* SOSFlagsSet(void) { [self addBackupFlag]; }]; + self.performRingUpdates = [[CKKSNearFutureScheduler alloc] initWithName:@"performRingUpdates" + initialDelay:5*NSEC_PER_SEC + expontialBackoff:2.0 + maximumDelay:15*60*NSEC_PER_SEC + keepProcessAlive:YES + dependencyDescriptionCode:CKKSResultDescriptionNone + block:^{ + STRONGIFY(self); + [self addRingUpdateFlag]; + }]; + SOSAccountConfiguration *conf = self.accountConfiguration.storage; if (conf.pendingBackupPeers.count) { [self addBackupFlag]; } - - [self.stateMachine startOperation]; + if (conf.ringUpdateFlag) { + [self addRingUpdateFlag]; + } } +/* + * Flag adding to state machine + */ + - (void)addBackupFlag { OctagonPendingFlag *pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:SOSFlagTriggerBackup conditions:OctagonPendingConditionsDeviceUnlocked]; [self.stateMachine handlePendingFlag:pendingFlag]; } +- (void)addRingUpdateFlag { + OctagonPendingFlag *pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:SOSFlagTriggerRingUpdate + conditions:OctagonPendingConditionsDeviceUnlocked]; + [self.stateMachine handlePendingFlag:pendingFlag]; +} + +//Mark: -- Set up state for state machine + + - (void)triggerBackupForPeers:(NSArray*)backupPeers { - dispatch_sync(self.stateMachineQueue, ^{ + NSMutableSet *pending = [NSMutableSet set]; + if (backupPeers) { + [pending addObjectsFromArray:backupPeers]; + } + + WEAKIFY(self); + dispatch_async(self.stateMachineQueue, ^{ + STRONGIFY(self); + SOSAccountConfiguration *storage = self.accountConfiguration.storage; - NSMutableSet *pending = [NSMutableSet set]; if (storage.pendingBackupPeers) { [pending addObjectsFromArray:storage.pendingBackupPeers]; } - if (backupPeers) { - [pending addObjectsFromArray:backupPeers]; - } storage.pendingBackupPeers = [[pending allObjects] mutableCopy]; [self.accountConfiguration setStorage:storage]; [self.performBackups trigger]; - secnotice("sos-sm", "trigger backup for peers: %@", backupPeers); + secnotice("sos-sm", "trigger backup for peers: %@ at %@", + backupPeers, self.performBackups.nextFireTime); }); } +- (void)triggerRingUpdate +{ + WEAKIFY(self); + dispatch_async(self.stateMachineQueue, ^{ + STRONGIFY(self); + SOSAccountConfiguration *storage = self.accountConfiguration.storage; + storage.ringUpdateFlag = YES; + [self.accountConfiguration setStorage:storage]; + [self.performRingUpdates trigger]; + secnotice("sos-sm", "trigger ring update at %@", + self.performRingUpdates.nextFireTime); + }); +} + +//Mark: -- State machine and opertions + +- (OctagonStateTransitionOperation *)performBackup { + + WEAKIFY(self); + return [OctagonStateTransitionOperation named:@"perform-backup-state" + intending:SOSStateReady + errorState:SOSStateError + withBlockTakingSelf:^void(OctagonStateTransitionOperation * _Nonnull op) { + STRONGIFY(self); + SOSAccountConfiguration *storage = self.accountConfiguration.storage; + + secnotice("sos-sm", "performing backup for %@", storage.pendingBackupPeers); + + if (storage.pendingBackupPeers.count) { + SOSCCRequestSyncWithBackupPeerList((__bridge CFArrayRef)storage.pendingBackupPeers); + [storage clearPendingBackupPeers]; + } + [self.accountConfiguration setStorage:storage]; + + op.nextState = SOSStateReady; + }]; +} + +- (OctagonStateTransitionOperation *)performRingUpdate { + + WEAKIFY(self); + return [OctagonStateTransitionOperation named:@"perform-ring-update" + intending:SOSStateReady + errorState:SOSStateError + withBlockTakingSelf:^void(OctagonStateTransitionOperation * _Nonnull op) { + STRONGIFY(self); + + SOSAccountConfiguration *storage = self.accountConfiguration.storage; + storage.ringUpdateFlag = NO; + [self.accountConfiguration setStorage:storage]; + + [self performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + if([self accountKeyIsTrusted] && [self isInCircle:NULL]) { + + [self _onQueueRecordRetiredPeersInCircle]; + + SOSAccountEnsureRecoveryRing(self); + [self _onQueueEnsureInBackupRings]; + + CFErrorRef localError = NULL; + if(![self.circle_transport flushChanges:&localError]){ + secerror("flush circle failed %@", localError); + } + CFReleaseNull(localError); + + if(!SecCKKSTestDisableSOS()) { + SOSAccountNotifyEngines(self); + } + } + }]; + + op.nextState = SOSStateReady; + }]; + +} + + - (CKKSResultOperation* _Nullable)_onqueueNextStateMachineTransition:(OctagonState*)currentState flags:(nonnull OctagonFlags *)flags pendingFlags:(nonnull id)pendingFlagHandler { dispatch_assert_queue(self.stateMachineQueue); - WEAKIFY(self); - - secnotice("sos-sm", "currentState: %@ [flags: %@]", currentState, flags); + secnotice("sos-sm", "Entering state: %@ [flags: %@]", currentState, flags); if ([currentState isEqualToString:SOSStateReady]) { if([flags _onqueueContains:SOSFlagTriggerBackup]) { @@ -2790,30 +2970,21 @@ static NSSet* SOSFlagsSet(void) { return [OctagonStateTransitionOperation named:@"perform-backup-flag" entering:SOSStatePerformBackup]; } - secnotice("sos-sm", "Entering state ready"); + + if ([flags _onqueueContains:SOSFlagTriggerRingUpdate]) { + [flags _onqueueRemoveFlag:SOSFlagTriggerRingUpdate]; + return [OctagonStateTransitionOperation named:@"perform-ring-update-flag" + entering:SOSStatePerformRingUpdate]; + } return nil; + } else if ([currentState isEqualToString:SOSStateError]) { - secnotice("sos-sm", "Entering state error"); return nil; - } else if ([currentState isEqualToString:SOSStatePerformBackup]) { - - return [OctagonStateTransitionOperation named:@"perform-backup-state" - intending:SOSStateReady - errorState:SOSStateError - withBlockTakingSelf:^void(OctagonStateTransitionOperation * _Nonnull op) { - STRONGIFY(self); - SOSAccountConfiguration *storage = self.accountConfiguration.storage; - - secnotice("sos-sm", "performing backup for %@", storage.pendingBackupPeers); + } else if ([currentState isEqualToString:SOSStatePerformRingUpdate]) { + return [self performRingUpdate]; - if (storage.pendingBackupPeers.count) { - SOSCCRequestSyncWithBackupPeerList((__bridge CFArrayRef)storage.pendingBackupPeers); - [storage clearPendingBackupPeers]; - } - [self.accountConfiguration setStorage:storage]; - - op.nextState = SOSStateReady; - }]; + } else if ([currentState isEqualToString:SOSStatePerformBackup]) { + return [self performBackup]; } return nil; diff --git a/keychain/SecureObjectSync/SOSAccountBackup.m b/keychain/SecureObjectSync/SOSAccountBackup.m index 17c724d5..c9f52dc3 100644 --- a/keychain/SecureObjectSync/SOSAccountBackup.m +++ b/keychain/SecureObjectSync/SOSAccountBackup.m @@ -458,13 +458,18 @@ SOSRingRef SOSAccountCreateBackupRingForView(SOSAccount* account, CFStringRef ri return newRing; } -void SOSAccountProcessBackupRings(SOSAccount* account, CFErrorRef *error) { +void SOSAccountProcessBackupRings(SOSAccount* account) { SOSAccountForEachBackupView(account, ^(const void *value) { + CFErrorRef localError = NULL; CFStringRef viewName = (CFStringRef)value; - SOSAccountUpdateBackupRing(account, viewName, error, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) { + SOSAccountUpdateBackupRing(account, viewName, &localError, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) { SOSRingRef newRing = SOSAccountCreateBackupRingForView(account, viewName, error); return newRing; }); + if(localError) { + secnotice("ring", "Error during SOSAccountProcessBackupRings (%@)", localError); + CFReleaseNull(localError); + } }); } @@ -524,7 +529,9 @@ bool SOSAccountSetBackupPublicKey(SOSAccountTransaction* aTxn, CFDataRef cfBacku })){ return result; } - SOSAccountProcessBackupRings(account, NULL); + SOSAccountProcessBackupRings(account); + account.need_backup_peers_created_after_backup_key_set = true; + account.circle_rings_retirements_need_attention = true; return true; } diff --git a/keychain/SecureObjectSync/SOSAccountCloudParameters.m b/keychain/SecureObjectSync/SOSAccountCloudParameters.m index 9da7355e..ae1f9b91 100644 --- a/keychain/SecureObjectSync/SOSAccountCloudParameters.m +++ b/keychain/SecureObjectSync/SOSAccountCloudParameters.m @@ -30,14 +30,14 @@ static uint8_t* der_encode_cloud_parameters(SecKeyRef publicKey, CFDataRef param const uint8_t* der_decode_cloud_parameters(CFAllocatorRef allocator, CFIndex algorithmID, SecKeyRef* publicKey, - CFDataRef *parameters, + CFDataRef *pbkdfParams, CFErrorRef* error, const uint8_t* der, const uint8_t* der_end) { const uint8_t *sequence_end; der = ccder_decode_sequence_tl(&sequence_end, der, der_end); der = der_decode_public_bytes(allocator, algorithmID, publicKey, error, der, sequence_end); - der = der_decode_data_or_null(allocator, parameters, error, der, sequence_end); + der = der_decode_data_or_null(allocator, pbkdfParams, error, der, sequence_end); return der; } @@ -46,12 +46,12 @@ const uint8_t* der_decode_cloud_parameters(CFAllocatorRef allocator, bool SOSAccountPublishCloudParameters(SOSAccount* account, CFErrorRef* error){ bool success = false; CFIndex cloud_der_len = der_sizeof_cloud_parameters(account.accountKey, - (__bridge CFDataRef)(account.accountKeyDerivationParamters), + (__bridge CFDataRef)(account.accountKeyDerivationParameters), error); CFMutableDataRef cloudParameters = CFDataCreateMutableWithScratch(kCFAllocatorDefault, cloud_der_len); - if (der_encode_cloud_parameters(account.accountKey, (__bridge CFDataRef)(account.accountKeyDerivationParamters), error, + if (der_encode_cloud_parameters(account.accountKey, (__bridge CFDataRef)(account.accountKeyDerivationParameters), error, CFDataGetMutableBytePtr(cloudParameters), CFDataGetMutablePastEndPtr(cloudParameters)) != NULL) { @@ -75,9 +75,9 @@ bool SOSAccountPublishCloudParameters(SOSAccount* account, CFErrorRef* error){ bool SOSAccountRetrieveCloudParameters(SOSAccount* account, SecKeyRef *newKey, CFDataRef derparms, - CFDataRef *newParameters, CFErrorRef* error) { + CFDataRef *pbkdfParams, CFErrorRef* error) { const uint8_t *parse_end = der_decode_cloud_parameters(kCFAllocatorDefault, kSecECDSAAlgorithmID, - newKey, newParameters, error, + newKey, pbkdfParams, error, CFDataGetBytePtr(derparms), CFDataGetPastEndPtr(derparms)); if (parse_end == CFDataGetPastEndPtr(derparms)) return true; diff --git a/keychain/SecureObjectSync/SOSAccountConfiguration.proto b/keychain/SecureObjectSync/SOSAccountConfiguration.proto index 8bba993c..bb26993a 100644 --- a/keychain/SecureObjectSync/SOSAccountConfiguration.proto +++ b/keychain/SecureObjectSync/SOSAccountConfiguration.proto @@ -8,4 +8,5 @@ package SOS; message AccountConfiguration { repeated string pendingBackupPeers = 1; + optional bool ringUpdateFlag = 2; } diff --git a/keychain/SecureObjectSync/SOSAccountCredentials.m b/keychain/SecureObjectSync/SOSAccountCredentials.m index efe75070..4297b789 100644 --- a/keychain/SecureObjectSync/SOSAccountCredentials.m +++ b/keychain/SecureObjectSync/SOSAccountCredentials.m @@ -111,7 +111,9 @@ static void SOSAccountSetTrustedUserPublicKey(SOSAccount* account, bool public_w CFReleaseNull(publicKey); - secnotice("circleOps", "trusting new public key: %@", account.accountKey); + CFStringRef keyid = SOSCopyIDOfKeyWithLength(account.accountKey, 8, NULL); + secnotice("circleOps", "trusting new public key: %@", keyid); + CFReleaseNull(keyid); notify_post(kPublicKeyAvailable); } @@ -127,8 +129,9 @@ void SOSAccountSetUnTrustedUserPublicKey(SOSAccount* account, SecKeyRef publicKe if(!account.previousAccountKey) { account.previousAccountKey = account.accountKey; } - - secnotice("circleOps", "not trusting new public key: %@", account.accountKey); + CFStringRef keyid = SOSCopyIDOfKeyWithLength(account.accountKey, 8, NULL); + secnotice("circleOps", "not trusting new public key: %@", keyid); + CFReleaseNull(keyid); } @@ -310,8 +313,8 @@ static void sosAccountSetTrustedCredentials(SOSAccount* account, CFDataRef user_ static SecKeyRef sosAccountCreateKeyIfPasswordIsCorrect(SOSAccount* account, CFDataRef user_password, CFErrorRef *error) { SecKeyRef user_private = NULL; - require_quiet(account.accountKey && account.accountKeyDerivationParamters, errOut); - user_private = SOSUserKeygen(user_password, (__bridge CFDataRef)(account.accountKeyDerivationParamters), error); + require_quiet(account.accountKey && account.accountKeyDerivationParameters, errOut); + user_private = SOSUserKeygen(user_password, (__bridge CFDataRef)(account.accountKeyDerivationParameters), error); require_quiet(user_private, errOut); require_action_quiet(SOSAccountValidateAccountCredential(account, user_private, error), errOut, CFReleaseNull(user_private)); @@ -322,7 +325,21 @@ errOut: static bool sosAccountValidatePasswordOrFail(SOSAccount* account, CFDataRef user_password, CFErrorRef *error) { SecKeyRef privKey = sosAccountCreateKeyIfPasswordIsCorrect(account, user_password, error); if(!privKey) { - if(account.accountKeyDerivationParamters) debugDumpUserParameters(CFSTR("sosAccountValidatePasswordOrFail"), (__bridge CFDataRef)(account.accountKeyDerivationParamters)); + if(account.accountKeyDerivationParameters) { + SecKeyRef newKey = NULL; + CFDataRef pbkdfParams = NULL; + CFErrorRef localError = NULL; + if(SOSAccountRetrieveCloudParameters(account, &newKey, (__bridge CFDataRef)(account.accountKeyDerivationParameters), &pbkdfParams, &localError)) { + debugDumpUserParameters(CFSTR("sosAccountValidatePasswordOrFail"), pbkdfParams); + } else { + secnotice("circleOps", "Failed to retrieve cloud parameters - %@", localError); + if(error) { + CFTransferRetained(*error, localError); + } + } + CFReleaseNull(newKey); + CFReleaseNull(pbkdfParams); + } SOSCreateError(kSOSErrorWrongPassword, CFSTR("Could not create correct key with password."), NULL, error); return false; } @@ -332,7 +349,7 @@ static bool sosAccountValidatePasswordOrFail(SOSAccount* account, CFDataRef user } void SOSAccountSetParameters(SOSAccount* account, CFDataRef parameters) { - account.accountKeyDerivationParamters = (__bridge NSData *) parameters; + account.accountKeyDerivationParameters = (__bridge NSData *) parameters; } bool SOSAccountValidateAccountCredential(SOSAccount* account, SecKeyRef accountPrivateKey, CFErrorRef *error) @@ -347,7 +364,7 @@ bool SOSAccountValidateAccountCredential(SOSAccount* account, SecKeyRef accountP CFStringRef accountHpub = SOSCopyIDOfKey(account.accountKey, NULL); CFStringRef candidateHpub = SOSCopyIDOfKey(publicCandidate, NULL); SOSCreateErrorWithFormat(kSOSErrorWrongPassword, NULL, &localError, NULL, CFSTR("Password generated pubkey doesn't match - candidate: %@ known: %@"), candidateHpub, accountHpub); - secnotice("circleop", "%@", localError); + secnotice("circleop", "Password generated pubkey doesn't match - candidate: %@ known: %@", candidateHpub, accountHpub); if (error) { *error = localError; localError = NULL; diff --git a/keychain/SecureObjectSync/SOSAccountFullPeerInfo.m b/keychain/SecureObjectSync/SOSAccountFullPeerInfo.m index 834c75d7..100433b1 100644 --- a/keychain/SecureObjectSync/SOSAccountFullPeerInfo.m +++ b/keychain/SecureObjectSync/SOSAccountFullPeerInfo.m @@ -39,15 +39,11 @@ static CFStringRef kicloud_identity_name = CFSTR("Cloud Identity"); SecKeyRef SOSAccountCopyDeviceKey(SOSAccount* account, CFErrorRef *error) { SecKeyRef privateKey = NULL; - SOSFullPeerInfoRef identity = NULL; - - SOSAccountTrustClassic *trust = account.trust; - identity = trust.fullPeerInfo; - require_action_quiet(identity, fail, SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("No identity to get key from"))); - - privateKey = SOSFullPeerInfoCopyDeviceKey(identity, error); - -fail: + if(account.peerPublicKey) { + privateKey = SecKeyCopyMatchingPrivateKey(account.peerPublicKey, error); + } else { + SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("No identity to get key from")); + } return privateKey; } @@ -59,13 +55,13 @@ SOSFullPeerInfoRef CopyCloudKeychainIdentity(SOSPeerInfoRef cloudPeer, CFErrorRe static CF_RETURNS_RETAINED SecKeyRef GeneratePermanentFullECKey_internal(int keySize, CFStringRef name, CFTypeRef accessibility, CFBooleanRef sync, CFErrorRef* error) { SecKeyRef full_key = NULL; - + CFNumberRef key_size_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keySize); - + CFDictionaryRef priv_key_attrs = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecAttrIsPermanent, kCFBooleanTrue, NULL); - + CFDictionaryRef keygen_parameters = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecAttrKeyType, kSecAttrKeyTypeEC, kSecAttrKeySizeInBits, key_size_num, @@ -76,19 +72,19 @@ static CF_RETURNS_RETAINED SecKeyRef GeneratePermanentFullECKey_internal(int key kSecAttrSynchronizable, sync, kSecUseTombstones, kCFBooleanTrue, NULL); - + CFReleaseNull(priv_key_attrs); - + CFReleaseNull(key_size_num); OSStatus status = SecKeyGeneratePair(keygen_parameters, NULL, &full_key); CFReleaseNull(keygen_parameters); - + if (status) secerror("status: %ld", (long)status); if (status != errSecSuccess && error != NULL && *error == NULL) { *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, status, NULL); } - + return full_key; } @@ -100,6 +96,69 @@ static CF_RETURNS_RETAINED SecKeyRef GeneratePermanentFullECKeyForCloudIdentity( return GeneratePermanentFullECKey_internal(keySize, name, kSecAttrAccessibleWhenUnlocked, kCFBooleanTrue, error); } +static SecKeyRef sosKeyForLabel(CFStringRef label) { + CFTypeRef queryResult = NULL; + SecKeyRef retval = NULL; + CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecMatchLimit, kSecMatchLimitOne, + kSecClass, kSecClassKey, + kSecAttrKeyClass, kSecAttrKeyClassPrivate, + kSecAttrSynchronizable, kSecAttrSynchronizableAny, + kSecAttrAccessGroup, kSOSInternalAccessGroup, + kSecAttrLabel, label, + kSecReturnRef, kCFBooleanTrue, + NULL); + OSStatus stat = SecItemCopyMatching(query, &queryResult); + if(errSecSuccess == stat) { + retval = (SecKeyRef) queryResult; + secnotice("iCloudIdentity", "Got key for label (%@)", label); + } else { + secnotice("iCloudIdentity", "Failed query(%d) for %@", (int) stat, label); + } + CFReleaseNull(query); + return retval; +} + +void SOSiCloudIdentityPrivateKeyForEach(void (^complete)(SecKeyRef privKey)) { + CFTypeRef queryResult = NULL; + CFArrayRef iCloudPrivKeys = NULL; + + CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecMatchLimit, kSecMatchLimitAll, + kSecClass, kSecClassKey, + kSecAttrKeyClass, kSecAttrKeyClassPrivate, + kSecAttrSynchronizable, kSecAttrSynchronizableAny, + kSecAttrAccessGroup, kSOSInternalAccessGroup, + kSecReturnAttributes, kCFBooleanTrue, + NULL); + + if((errSecSuccess == SecItemCopyMatching(query, &queryResult)) && (iCloudPrivKeys = asArray(queryResult, NULL))) { + secnotice("iCloudIdentity", "Screening %ld icloud private key candidates", (long)CFArrayGetCount(iCloudPrivKeys)); + CFReleaseNull(query); + } else { + secnotice("iCloudIdentity", "Can't get iCloud Identity private key candidates"); + CFReleaseNull(query); + CFReleaseNull(queryResult); + return; + } + + CFArrayForEach(iCloudPrivKeys, ^(const void *value) { + CFDictionaryRef privKeyDict = (CFDictionaryRef) value; + CFStringRef label = CFDictionaryGetValue(privKeyDict, kSecAttrLabel); + if(!label) { + return; + } + if(CFStringHasPrefix(label, CFSTR("Cloud Identity"))) { + SecKeyRef privKey = sosKeyForLabel(label); + if(privKey) { + complete(privKey); + CFReleaseNull(privKey); + } + } + }); + CFReleaseNull(queryResult); +} + bool SOSAccountHasCircle(SOSAccount* account, CFErrorRef* error) { SOSAccountTrustClassic *trust = account.trust; SOSCircleRef circle = trust.trustedCircle; diff --git a/keychain/SecureObjectSync/SOSAccountGhost.m b/keychain/SecureObjectSync/SOSAccountGhost.m index f8de69c2..6a65ebf5 100644 --- a/keychain/SecureObjectSync/SOSAccountGhost.m +++ b/keychain/SecureObjectSync/SOSAccountGhost.m @@ -18,6 +18,7 @@ #include "keychain/SecureObjectSync/SOSPeerInfoPriv.h" #include "keychain/SecureObjectSync/SOSAuthKitHelpers.h" #import "Analytics/Clients/SOSAnalytics.h" +#import #include "utilities/SecTrace.h" @@ -32,9 +33,9 @@ static bool sosGhostCheckValid(SOSPeerInfoRef pi) { case SOSPeerInfo_iOS: case SOSPeerInfo_tvOS: case SOSPeerInfo_watchOS: - case SOSPeerInfo_macOS: retval = true; break; + case SOSPeerInfo_macOS: // go back and quit killing macos ghosts so people can multi-boot case SOSPeerInfo_iCloud: case SOSPeerInfo_unknown: default: @@ -140,28 +141,27 @@ static NSUInteger SOSGhostBustThinSerialClones(SOSCircleRef circle, NSString *my for(CFIndex i = CFArrayGetCount(sortPeers); i > 0; i--) { SOSPeerInfoRef pi = (SOSPeerInfoRef) CFArrayGetValueAtIndex(sortPeers, i-1); - - if(sosGhostCheckValid(pi)) { + NSString *peerID = (__bridge NSString *)SOSPeerInfoGetPeerID(pi); + + if(![peerID isEqualToString: myPeerID] && sosGhostCheckValid(pi)) { NSString *serial = CFBridgingRelease(SOSPeerInfoV2DictionaryCopyString(pi, sSerialNumberKey)); - NSString *peerID = (__bridge NSString *)SOSPeerInfoGetPeerID(pi); if(serial != nil) { if([latestPeers objectForKey:serial] != nil) { - if(peerID != myPeerID) { - [removals addObject:peerID]; - } else { - secnotice("ghostBust", "There is a more recent peer for this serial number"); - } + secnotice("ghostBust", "There is a more recent peer than %@ for this serial number", SOSPeerInfoGetSPID(pi)); + [removals addObject:peerID]; } else { [latestPeers setObject:peerID forKey:serial]; } } else { - secnotice("ghostBust", "Removing peerID (%@) with no serial number", peerID); + secnotice("ghostBust", "Removing peerID (%@) with no serial number", SOSPeerInfoGetSPID(pi)); [removals addObject:peerID]; } } } - SOSCircleRemovePeersByIDUnsigned(circle, (__bridge CFSetRef)(removals)); gbcount = [removals count]; + if(gbcount > 0) { + SOSCircleRemovePeersByIDUnsigned(circle, (__bridge CFSetRef)(removals)); + } CFReleaseNull(sortPeers); return gbcount; } @@ -175,6 +175,42 @@ static void SOSCircleRemoveiCloudIdentities(SOSCircleRef circle) { SOSCircleRemovePeersByIDUnsigned(circle, (__bridge CFSetRef)(removals)); } +// this is only used to determine if we have a circle that can't accept new peers because of ghosts. +static void SOSCircleRemoveWindowsPeers(SOSCircleRef circle) { + NSMutableSet *removals = [[NSMutableSet alloc] init]; + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + NSString *devType = (__bridge NSString *)SOSPeerInfoGetPeerDeviceType(peer); + if([devType hasPrefix: @"Windows"]) { + NSString *peerID = (__bridge NSString *)SOSPeerInfoGetPeerID(peer); + [removals addObject:peerID]; + } + }); + SOSCircleRemovePeersByIDUnsigned(circle, (__bridge CFSetRef)(removals)); +} + +static void SOSCircleRemovePeersNotInMidlist(SOSCircleRef circle) { + __block SOSAuthKitHelpers *akh = nil; + + if([SOSAuthKitHelpers accountIsHSA2]) { + [SOSAuthKitHelpers activeMIDs:^(NSSet * _Nullable activeMIDs, NSError * _Nullable error) { + akh = [[SOSAuthKitHelpers alloc] initWithActiveMIDS:activeMIDs]; + }]; + } + + NSMutableSet *removals = [[NSMutableSet alloc] init]; + if(akh) { + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + NSString *mid = CFBridgingRelease(SOSPeerInfoV2DictionaryCopyString(peer, sMachineIDKey)); + if(![akh midIsValidInList:mid]) { + NSString *peerID = (__bridge NSString *)SOSPeerInfoGetPeerID(peer); + [removals addObject:peerID]; + } + }); + SOSCircleRemovePeersByIDUnsigned(circle, (__bridge CFSetRef)(removals)); + } +} + + bool SOSAccountGhostResultsInReset(SOSAccount* account) { if(!account.peerID || !account.trust.trustedCircle) return false; SOSCircleRef newCircle = SOSCircleCopyCircle(kCFAllocatorDefault, account.trust.trustedCircle, NULL); @@ -182,6 +218,8 @@ bool SOSAccountGhostResultsInReset(SOSAccount* account) { SOSCircleClearMyGhosts(newCircle, account.peerInfo); SOSCircleRemoveRetired(newCircle, NULL); SOSCircleRemoveiCloudIdentities(newCircle); + SOSCircleRemoveWindowsPeers(newCircle); + SOSCircleRemovePeersNotInMidlist(newCircle); int npeers = SOSCircleCountPeers(newCircle); CFReleaseNull(newCircle); return npeers == 0; @@ -200,6 +238,7 @@ static NSUInteger SOSGhostBustThinByMIDList(SOSCircleRef circle, NSString *myPee if(options & SOSGhostBustByMID) { NSString *mid = CFBridgingRelease(SOSPeerInfoV2DictionaryCopyString(peer, sMachineIDKey)); if(![akh midIsValidInList:mid]) { + secnotice("ghostBust", "Removing peerInfo %@ - mid is not in list", SOSPeerInfoGetSPID(peer)); [removals addObject:peerID]; gbmid++; return; @@ -208,6 +247,7 @@ static NSUInteger SOSGhostBustThinByMIDList(SOSCircleRef circle, NSString *myPee if(options & SOSGhostBustBySerialNumber) { NSString *serial = CFBridgingRelease(SOSPeerInfoV2DictionaryCopyString(peer, sSerialNumberKey)); if(![akh serialIsValidInList: serial]) { + secnotice("ghostBust", "Removing peerInfo %@ - serial# is not in list", SOSPeerInfoGetSPID(peer)); [removals addObject:peerID]; gbserial++; return; @@ -222,92 +262,86 @@ static NSUInteger SOSGhostBustThinByMIDList(SOSCircleRef circle, NSString *myPee return [removals count]; } -static bool SOSGhostBustiCloudIdentityPrivateKeys(SOSAccount *account) { - __block bool cleaned = false; - SecKeyRef pubKey = NULL; - CFTypeRef queryResult = NULL; - CFDataRef pubKeyHash = NULL; - CFDictionaryRef query = NULL; - __block int removed = 0; - - SOSFullPeerInfoRef iCloudIdentity = SOSCircleCopyiCloudFullPeerInfoVerifier(account.trust.trustedCircle, NULL); - require_action_quiet(iCloudIdentity, retOut, secnotice("ghostBust", "No iCloud Identity FPI")); - pubKey = SOSFullPeerInfoCopyPubKey(iCloudIdentity, NULL); - require_action_quiet(pubKey, retOut, secnotice("ghostBust", "Can't get iCloud Identity pubkey")); - pubKeyHash = SecKeyCopyPublicKeyHash(pubKey); - require_action_quiet(pubKeyHash, retOut, secnotice("ghostBust", "Can't get iCloud Identity pubkey hash")); - query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecMatchLimit, kSecMatchLimitAll, - kSecClass, kSecClassKey, - kSecAttrKeyClass, kSecAttrKeyClassPrivate, - kSecAttrSynchronizable, kSecAttrSynchronizableAny, - kSecReturnAttributes, kCFBooleanTrue, - kSecAttrAccessGroup, kSOSInternalAccessGroup, - NULL); - require_action_quiet(errSecSuccess == SecItemCopyMatching(query, &queryResult), retOut, secnotice("ghostBust", "Can't get iCloud Identity private keys")); - require_action_quiet(CFGetTypeID(queryResult) == CFArrayGetTypeID(), retOut, cleaned = true); - CFArrayRef iCloudPrivKeys = queryResult; - secnotice("ghostBust", "Screening %ld icloud private keys", (long)CFArrayGetCount(iCloudPrivKeys)); - CFArrayForEach(iCloudPrivKeys, ^(const void *value) { - CFDictionaryRef privkey = asDictionary(value, NULL); - if(privkey) { - CFDataRef candidate = asData(CFDictionaryGetValue(privkey, kSecAttrApplicationLabel), NULL); - if(candidate && !CFEqual(pubKeyHash, candidate)) { - CFStringRef label = asString(CFDictionaryGetValue(privkey, kSecAttrLabel), NULL); - if(label) { - if(CFStringHasPrefix(label, CFSTR("Cloud Identity"))) { - - CFDictionaryRef delQuery = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecClass, kSecClassKey, - kSecAttrKeyClass, kSecAttrKeyClassPrivate, - kSecAttrSynchronizable, kSecAttrSynchronizableAny, - kSecAttrApplicationLabel, candidate, - NULL); - - OSStatus status = SecItemDelete(delQuery); - if(errSecSuccess == status) { - secnotice("ghostBust", "removed %@", label); - removed++; - cleaned = true; - } else { - secnotice("ghostbust", "Search for %@ returned %d", candidate, (int) status); - } - CFReleaseNull(delQuery); - } +static NSUInteger SOSGhostBustiCloudIdentityPrivateKeys(SOSAccount *account) { + __block NSUInteger cleaned = 0; + + [ account iCloudIdentityStatus_internal:^(NSDictionary *tableSpid, NSError *error) { + if(!tableSpid) { + secnotice("ghostBust", "Couldn't work on iCloud Identities (%@)", error); + } + + size_t keysToRemove = [tableSpid[kSOSIdentityStatusKeyOnly] count]; + + if(keysToRemove == 0) { + return; + } + + if([tableSpid[kSOSIdentityStatusCompleteIdentity] count] == 0) { + secnotice("ghostBust", "No iCloud Identity FPI, can't remove iCloudIdentity extra keys"); + return; + } + + for (NSString *pid in tableSpid[kSOSIdentityStatusKeyOnly]) { + CFStringRef fullKeyLabel = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Cloud Identity - '%@'"), pid); + + if(fullKeyLabel) { + CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecClass, kSecClassKey, + kSecAttrKeyClass, kSecAttrKeyClassPrivate, + kSecAttrSynchronizable, kSecAttrSynchronizableAny, + kSecUseTombstones, kCFBooleanTrue, + kSecAttrLabel, fullKeyLabel, + NULL); + OSStatus status = SecItemDelete(query); + if(errSecSuccess == status) { + secnotice("ghostBust", "removed %@", pid); + cleaned++; + } else { + secnotice("ghostbust", "Delete for %@ returned %d", pid, (int) status); } + CFReleaseNull(query); + CFReleaseNull(fullKeyLabel); } } - }); - secnotice("ghostBust", "Removed %d icloud private keys", removed); -retOut: - CFReleaseNull(query); - CFReleaseNull(queryResult); - CFReleaseNull(pubKeyHash); - CFReleaseNull(pubKey); - CFReleaseNull(iCloudIdentity); + secnotice("ghostBust", "Removed %zu of %zu deserted icloud private keys", cleaned, keysToRemove); + }]; return cleaned; } bool SOSAccountGhostBustCircle(SOSAccount *account, SOSAuthKitHelpers *akh, SOSAccountGhostBustingOptions options, int mincount) { __block bool result = false; + __block bool actionTaken = false; CFErrorRef localError = NULL; __block NSUInteger nbusted = 9999; NSMutableDictionary *attributes =[NSMutableDictionary new]; + int circleSize = SOSCircleCountPeers(account.trust.trustedCircle); - if ([akh isUseful] && [account isInCircle:nil] && circleSize > mincount) { - if(options & SOSGhostBustiCloudIdentities) { - secnotice("ghostBust", "Callout to cleanup icloud identities"); - result = SOSGhostBustiCloudIdentityPrivateKeys(account); - } else { + if(options & SOSGhostBustiCloudIdentities && [account isInCircle:nil]) { + secnotice("ghostBust", "Callout to cleanup icloud identities"); + nbusted = SOSGhostBustiCloudIdentityPrivateKeys(account); + if(nbusted) { + attributes[@"iCloudPrivKeysBusted"] = @(nbusted); + [[SOSAnalytics logger] logSoftFailureForEventNamed:@"GhostBust" withAttributes:attributes]; + result = true; + } + actionTaken = true; + } + + if(options & (~SOSGhostBustiCloudIdentities)) { + if ([akh isUseful] && [account isInCircle:nil] && circleSize > mincount) { [account.trust modifyCircle:account.circle_transport err:&localError action:^(SOSCircleRef circle) { - nbusted = SOSGhostBustThinByMIDList(circle, account.peerID, akh, options, attributes); - secnotice("ghostbust", "Removed %lu ghosts from circle by midlist && serialNumber", (unsigned long)nbusted); + if((options & SOSGhostBustByMID) || (options & SOSGhostBustBySerialNumber)) { + nbusted = SOSGhostBustThinByMIDList(circle, account.peerID, akh, options, attributes); + secnotice("ghostbust", "Removed %lu ghosts from circle by midlist && serialNumber", (unsigned long)nbusted); + actionTaken = true; + } if(options & SOSGhostBustSerialByAge) { NSUInteger thinBusted = 9999; thinBusted = SOSGhostBustThinSerialClones(circle, account.peerID); nbusted += thinBusted; attributes[@"byAge"] = @(thinBusted); + actionTaken = true; } attributes[@"total"] = @(SecBucket1Significant(nbusted)); attributes[@"startCircleSize"] = @(SecBucket1Significant(circleSize)); @@ -324,17 +358,17 @@ bool SOSAccountGhostBustCircle(SOSAccount *account, SOSAuthKitHelpers *akh, SOSA }]; secnotice("circleOps", "Ghostbusting %@ (%@)", result ? CFSTR("Performed") : CFSTR("Not Performed"), localError); } - } else { - secnotice("circleOps", "Ghostbusting skipped"); } CFReleaseNull(localError); - - if(result) { - [[SOSAnalytics logger] logSoftFailureForEventNamed:@"GhostBust" withAttributes:attributes]; - } else if(nbusted == 0){ - [[SOSAnalytics logger] logSuccessForEventNamed:@"GhostBust"]; - } else { - [[SOSAnalytics logger] logHardFailureForEventNamed:@"GhostBust" withAttributes:nil]; + + if(actionTaken) { + if(result) { + [[SOSAnalytics logger] logSoftFailureForEventNamed:@"GhostBust" withAttributes:attributes]; + } else if(nbusted == 0){ + [[SOSAnalytics logger] logSuccessForEventNamed:@"GhostBust"]; + } else { + [[SOSAnalytics logger] logHardFailureForEventNamed:@"GhostBust" withAttributes:nil]; + } } return result; } diff --git a/keychain/SecureObjectSync/SOSAccountLog.m b/keychain/SecureObjectSync/SOSAccountLog.m index 1eed7078..26d6261f 100644 --- a/keychain/SecureObjectSync/SOSAccountLog.m +++ b/keychain/SecureObjectSync/SOSAccountLog.m @@ -6,7 +6,6 @@ #include "SOSAccountLog.h" #include #include -#include #include #include "SOSAccountPriv.h" #include "SOSViews.h" diff --git a/keychain/SecureObjectSync/SOSAccountPersistence.m b/keychain/SecureObjectSync/SOSAccountPersistence.m index 5b63e744..758fcfb0 100644 --- a/keychain/SecureObjectSync/SOSAccountPersistence.m +++ b/keychain/SecureObjectSync/SOSAccountPersistence.m @@ -24,7 +24,6 @@ #include #include -#include #include #include "SOSViews.h" @@ -65,7 +64,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v6(CFAllocatorRef allocator, { CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, + *der_p = der_decode_dictionary(kCFAllocatorDefault, &decoded_gestalt, error, *der_p, der_end); if (*der_p == 0) @@ -77,7 +76,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v6(CFAllocatorRef allocator, } SOSAccountTrustClassic *trust = account.trust; - *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, der_end); + *der_p = der_decode_array(kCFAllocatorDefault, &array, error, *der_p, der_end); uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, der_end); @@ -99,10 +98,10 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v6(CFAllocatorRef allocator, { CFDataRef parms = NULL; *der_p = der_decode_data_or_null(kCFAllocatorDefault, &parms, error, *der_p, der_end); - [account setAccountKeyDerivationParamters:(__bridge_transfer NSData*) parms]; + [account setAccountKeyDerivationParameters:(__bridge_transfer NSData*) parms]; } - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &retiredPeers, error, *der_p, der_end); + *der_p = der_decode_dictionary(kCFAllocatorDefault, (CFDictionaryRef *) &retiredPeers, error, *der_p, der_end); if(*der_p != der_end) { *der_p = NULL; @@ -173,11 +172,11 @@ fail: return result; } -static const uint8_t* der_decode_data_optional(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_data_optional(CFAllocatorRef allocator, CFDataRef* data, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { - const uint8_t *dt_end = der_decode_data(allocator, mutability, data, NULL, der, der_end); + const uint8_t *dt_end = der_decode_data(allocator, data, NULL, der, der_end); return dt_end ? dt_end : der; } @@ -192,7 +191,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v7(CFAllocatorRef allocator, { CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, + *der_p = der_decode_dictionary(kCFAllocatorDefault, &decoded_gestalt, error, *der_p, der_end); if (*der_p == 0) @@ -242,7 +241,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v7(CFAllocatorRef allocator, { CFDataRef parms = NULL; *der_p = der_decode_data_or_null(kCFAllocatorDefault, &parms, error, *der_p, der_end); - account.accountKeyDerivationParamters = (__bridge_transfer NSData*)parms; + account.accountKeyDerivationParameters = (__bridge_transfer NSData*)parms; } { @@ -252,7 +251,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v7(CFAllocatorRef allocator, { CFDataRef bKey = NULL; - *der_p = der_decode_data_optional(kCFAllocatorDefault, kCFPropertyListImmutable, &bKey, error, *der_p, der_end); + *der_p = der_decode_data_optional(kCFAllocatorDefault, &bKey, error, *der_p, der_end); if(bKey != NULL) [account setBackup_key:(__bridge_transfer NSData *)bKey]; } @@ -280,7 +279,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v8(CFAllocatorRef allocator, { CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, + *der_p = der_decode_dictionary(kCFAllocatorDefault, &decoded_gestalt, error, *der_p, der_end); if (*der_p == 0) { @@ -332,7 +331,7 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v8(CFAllocatorRef allocator, { CFDataRef parms; *der_p = der_decode_data_or_null(kCFAllocatorDefault, &parms, error, *der_p, der_end); - account.accountKeyDerivationParamters = (__bridge_transfer NSData*)parms; + account.accountKeyDerivationParameters = (__bridge_transfer NSData*)parms; parms = NULL; } @@ -343,10 +342,10 @@ static SOSAccount* SOSAccountCreateFromRemainingDER_v8(CFAllocatorRef allocator, } CFDataRef bKey = NULL; - *der_p = der_decode_data_optional(kCFAllocatorDefault, kCFPropertyListImmutable, &bKey, error, *der_p, der_end); + *der_p = der_decode_data_optional(kCFAllocatorDefault, &bKey, error, *der_p, der_end); { CFDictionaryRef expansion = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &expansion, error, + *der_p = der_decode_dictionary(kCFAllocatorDefault, &expansion, error, *der_p, der_end); if (*der_p == 0) { @@ -440,9 +439,12 @@ static SOSAccount* SOSAccountCreateFromDER(CFAllocatorRef allocator, SOSUnregisterTransportKeyParameter(account.key_transport); SOSUnregisterTransportCircle((SOSCircleStorageTransport*)account.circle_transport); SOSUnregisterTransportMessage(account.kvs_message_transport); - secnotice("account", "No private key associated with my_identity, resetting"); return nil; + } else { + SecKeyRef ppk = SOSFullPeerInfoCopyPubKey(identity, NULL); + account.peerPublicKey = ppk; + CFReleaseNull(ppk); } } @@ -457,9 +459,10 @@ static SOSAccount* SOSAccountCreateFromDER(CFAllocatorRef allocator, } CFReleaseNull(oldPI); - SOSAccountEnsureRecoveryRing(account); [account performTransaction:^(SOSAccountTransaction * _Nonnull txn) { + SOSAccountEnsureRecoveryRing(account); + secnotice("circleop", "Setting account.key_interests_need_updating to true in SOSAccountCreateFromDER"); account.key_interests_need_updating = true; }]; diff --git a/keychain/SecureObjectSync/SOSAccountPriv.h b/keychain/SecureObjectSync/SOSAccountPriv.h index d90657db..b73f7487 100644 --- a/keychain/SecureObjectSync/SOSAccountPriv.h +++ b/keychain/SecureObjectSync/SOSAccountPriv.h @@ -21,7 +21,6 @@ #include #include -#include #import @@ -97,16 +96,19 @@ typedef void (^SOSAccountSaveBlock)(CFDataRef flattenedAccount, CFErrorRef flatt @property (nonatomic, assign) BOOL circle_rings_retirements_need_attention; @property (nonatomic, assign) BOOL engine_peer_state_needs_repair; @property (nonatomic, assign) BOOL key_interests_need_updating; +@property (nonatomic, assign) BOOL need_backup_peers_created_after_backup_key_set; + @property (nonatomic, retain) NSMutableArray *change_blocks; @property (nonatomic, retain) NSMutableDictionary *waitForInitialSync_blocks; -@property (nonatomic, retain) NSData* accountKeyDerivationParamters; +@property (nonatomic, retain) NSData* accountKeyDerivationParameters; @property (nonatomic, assign) BOOL accountKeyIsTrusted; @property (nonatomic) SecKeyRef accountKey; @property (nonatomic) SecKeyRef previousAccountKey; +@property (nonatomic) SecKeyRef peerPublicKey; @property (copy) SOSAccountSaveBlock saveBlock; @@ -121,14 +123,18 @@ typedef void (^SOSAccountSaveBlock)(CFDataRef flattenedAccount, CFErrorRef flatt @property (nonatomic, assign) BOOL notifyViewChangeOnExit; @property (nonatomic, assign) BOOL notifyBackupOnExit; -@property (nonatomic, retain) NSUserDefaults* settings; +@property (nonatomic, retain) NSUserDefaults* settings; + +@property (nonatomic) SecKeyRef octagonSigningFullKeyRef; +@property (nonatomic) SecKeyRef octagonEncryptionFullKeyRef; +@property (nonatomic, assign) BOOL accountIsChanging; -(id) init NS_UNAVAILABLE; -(id) initWithGestalt:(CFDictionaryRef)gestalt factory:(SOSDataSourceFactoryRef)factory; -//- (void)startStateMachine; +- (void)startStateMachine; void SOSAccountAddSyncablePeerBlock(SOSAccount* a, CFStringRef ds_name, @@ -145,6 +151,7 @@ void SOSAccountAddSyncablePeerBlock(SOSAccount* a, #if OCTAGON - (void)triggerBackupForPeers:(NSArray*)backupPeer; +- (void)triggerRingUpdate; #endif @@ -205,8 +212,6 @@ bool SOSAccountHandleCircleMessage(SOSAccount* account, CF_RETURNS_RETAINED CFDictionaryRef SOSAccountHandleRetirementMessages(SOSAccount* account, CFDictionaryRef circle_retirement_messages, CFErrorRef *error); -void SOSAccountRecordRetiredPeersInCircle(SOSAccount* account); - bool SOSAccountHandleUpdateCircle(SOSAccount* account, SOSCircleRef prospective_circle, bool writeUpdate, @@ -247,6 +252,8 @@ bool SOSAccountIsAccountIdentity(SOSAccount* account, SOSPeerInfoRef peer_info, bool SOSAccountFullPeerInfoVerify(SOSAccount* account, SecKeyRef privKey, CFErrorRef *error); CF_RETURNS_RETAINED SOSPeerInfoRef GenerateNewCloudIdentityPeerInfo(CFErrorRef *error); +void SOSiCloudIdentityPrivateKeyForEach(void (^complete)(SecKeyRef privKey)); + // Credentials bool SOSAccountHasPublicKey(SOSAccount* account, CFErrorRef* error); bool SOSAccountPublishCloudParameters(SOSAccount* account, CFErrorRef* error); @@ -269,12 +276,11 @@ void SOSAccountSetLastDepartureReason(SOSAccount* account, enum DepartureReason void SOSAccountSetUserPublicTrustedForTesting(SOSAccount* account); void SOSAccountPurgeIdentity(SOSAccount*); -bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, NSData* parentData, CFErrorRef* error); +bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, CFErrorRef* error); bool SOSAccountForEachRing(SOSAccount* account, SOSRingRef (^action)(CFStringRef name, SOSRingRef ring)); bool SOSAccountUpdateBackUp(SOSAccount* account, CFStringRef viewname, CFErrorRef *error); void SOSAccountEnsureRecoveryRing(SOSAccount* account); -bool SOSAccountEnsureInBackupRings(SOSAccount* account); bool SOSAccountEnsurePeerRegistration(SOSAccount* account, CFErrorRef *error); diff --git a/keychain/SecureObjectSync/SOSAccountRecovery.m b/keychain/SecureObjectSync/SOSAccountRecovery.m index cd272013..a477f5c4 100644 --- a/keychain/SecureObjectSync/SOSAccountRecovery.m +++ b/keychain/SecureObjectSync/SOSAccountRecovery.m @@ -36,7 +36,6 @@ #include "keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h" #include "keychain/SecureObjectSync/SOSInternal.h" -#include "SecADWrapper.h" #include "keychain/SecureObjectSync/SOSRecoveryKeyBag.h" #include "keychain/SecureObjectSync/SOSRingRecovery.h" @@ -139,7 +138,7 @@ bool SOSAccountSetRecoveryKey(SOSAccount* account, CFDataRef pubData, CFErrorRef CFReleaseNull(rkbg); if(SOSPeerInfoHasBackupKey(account.trust.peerInfo)) { - SOSAccountProcessBackupRings(account, error); + SOSAccountProcessBackupRings(account); } account.circle_rings_retirements_need_attention = true; result = true; @@ -196,6 +195,8 @@ static void sosRecoveryAlertAndNotify(SOSAccount* account, SOSRecoveryKeyBagRef } void SOSAccountEnsureRecoveryRing(SOSAccount* account) { + dispatch_assert_queue(account.queue); + static SOSRecoveryKeyBagRef oldRingRKBG = NULL; SOSRecoveryKeyBagRef acctRKBG = SOSAccountCopyRecoveryKeyBagEntry(kCFAllocatorDefault, account, NULL); if(!CFEqualSafe(acctRKBG, oldRingRKBG)) { diff --git a/keychain/SecureObjectSync/SOSAccountRings.m b/keychain/SecureObjectSync/SOSAccountRings.m index 2ebcd729..708940da 100644 --- a/keychain/SecureObjectSync/SOSAccountRings.m +++ b/keychain/SecureObjectSync/SOSAccountRings.m @@ -116,6 +116,11 @@ SOSRingRef SOSAccountCopyRingNamed(SOSAccount* a, CFStringRef ringName, CFErrorR } bool SOSAccountUpdateRingFromRemote(SOSAccount* account, SOSRingRef newRing, CFErrorRef *error) { + if(account && account.accountIsChanging) { + secnotice("circleOps", "SOSAccountUpdateRingFromRemote called before signing in to new account"); + return true; // we want to drop circle notifications when account is changing + } + require_quiet(SOSAccountHasPublicKey(account, error), errOut); return [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:false err:error]; @@ -135,25 +140,22 @@ errOut: bool SOSAccountUpdateNamedRing(SOSAccount* account, CFStringRef ringName, CFErrorRef *error, SOSRingRef (^create)(CFStringRef ringName, CFErrorRef *error), SOSRingRef (^copyModified)(SOSRingRef existing, CFErrorRef *error)) { + if(![account isInCircle:NULL]) { + return false; + } bool result = false; - SOSRingRef found = [account.trust copyRing:ringName err:error]; - + SOSRingRef found = NULL; SOSRingRef newRing = NULL; + found = [account.trust copyRing:ringName err:error]; if(!found) { found = create(ringName, error); } - require_quiet(found, errOut); - newRing = copyModified(found, error); - CFReleaseNull(found); - - require_quiet(newRing, errOut); - - require_quiet(SOSAccountHasPublicKey(account, error), errOut); - require_quiet(SOSAccountHasCircle(account, error), errOut); - - result = [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:true err:error]; - -errOut: + if(found) { + newRing = copyModified(found, error); + if(newRing) { + result = [account.trust handleUpdateRing:account prospectiveRing:newRing transport:account.circle_transport userPublicKey:account.accountKey writeUpdate:true err:error]; + } + } CFReleaseNull(found); CFReleaseNull(newRing); return result; diff --git a/keychain/SecureObjectSync/SOSAccountTransaction.m b/keychain/SecureObjectSync/SOSAccountTransaction.m index 1c014b29..7e85439a 100644 --- a/keychain/SecureObjectSync/SOSAccountTransaction.m +++ b/keychain/SecureObjectSync/SOSAccountTransaction.m @@ -73,6 +73,10 @@ return circleStatus; } +static inline SOSCCStatus reportAsSOSCCStatus(uint64_t x) { + return (SOSCCStatus) x & CC_MASK; +} + - (void) updateSOSCircleCachedStatus { // clearly invalid, overwritten by cached value in notify_get_state() // if its the second time we are launchded @@ -92,7 +96,7 @@ } return true; }); - secnotice("sosnotify", "initial last circle status is: %llu", (unsigned long long)lastStatus); + secnotice("sosnotify", "initial last circle status is: %d", reportAsSOSCCStatus(lastStatus)); }); uint64_t currentStatus = [self currentTrustBitmask]; @@ -114,8 +118,8 @@ lastStatus = currentStatus; - secnotice("sosnotify", "new last circle status is: %llu (notify: %s)", - (unsigned long long)lastStatus, + secnotice("sosnotify", "new last circle status is: %d (notify: %s)", + reportAsSOSCCStatus(lastStatus), circleStatusChanged ? "yes" : "no"); SOSCachedNotificationOperation(kSOSCCCircleChangedNotification, ^bool(int token, bool gtg) { @@ -198,7 +202,7 @@ static void SOSViewsSetCachedStatus(SOSAccount *account) { } self.initialUnsyncedViews = (__bridge_transfer NSMutableSet*)SOSAccountCopyOutstandingViews(self.account); - self.initialKeyParameters = self.account.accountKeyDerivationParamters ? [NSData dataWithData:self.account.accountKeyDerivationParamters] : nil; + self.initialKeyParameters = self.account.accountKeyDerivationParameters ? [NSData dataWithData:self.account.accountKeyDerivationParameters] : nil; SOSPeerInfoRef mpi = self.account.peerInfo; if (mpi) { @@ -238,9 +242,10 @@ static void SOSViewsSetCachedStatus(SOSAccount *account) { bool isInCircle = [self.account isInCircle:NULL]; if (isInCircle && self.peersToRequestSync) { - SOSCCRequestSyncWithPeers((__bridge CFSetRef)(self.peersToRequestSync)); + NSMutableSet* worklist = self.peersToRequestSync; + self.peersToRequestSync = nil; + SOSCCRequestSyncWithPeers((__bridge CFSetRef)(worklist)); } - self.peersToRequestSync = nil; if (isInCircle) { SOSAccountEnsureSyncChecking(self.account); @@ -277,19 +282,23 @@ static void SOSViewsSetCachedStatus(SOSAccount *account) { } if(self.account.circle_rings_retirements_need_attention){ - SOSAccountRecordRetiredPeersInCircle(self.account); - - SOSAccountEnsureRecoveryRing(self.account); - SOSAccountEnsureInBackupRings(self.account); - - CFErrorRef localError = NULL; - if(![self.account.circle_transport flushChanges:&localError]){ - secerror("flush circle failed %@", localError); - } - CFReleaseSafe(localError); - + self.account.circle_rings_retirements_need_attention = false; +#if OCTAGON + [self.account triggerRingUpdate]; +#endif + // Also, there might be some view set change. Ensure that the engine knows... notifyEngines = true; } + if(self.account.need_backup_peers_created_after_backup_key_set){ + self.account.need_backup_peers_created_after_backup_key_set = false; + notifyEngines = true; + } + + // Always notify the engines if the view set has changed + CFSetRef currentViews = self.account.peerInfo ? SOSPeerInfoCopyEnabledViews(self.account.peerInfo) : NULL; + BOOL viewSetChanged = !NSIsEqualSafe(self.initialViews, (__bridge NSSet*)currentViews); + CFReleaseNull(currentViews); + notifyEngines |= viewSetChanged; if (notifyEngines) { #if OCTAGON @@ -305,7 +314,6 @@ static void SOSViewsSetCachedStatus(SOSAccount *account) { SOSUpdateKeyInterest(self.account); } - self.account.circle_rings_retirements_need_attention = false; self.account.engine_peer_state_needs_repair = false; [self.account flattenToSaveBlock]; @@ -332,7 +340,7 @@ static void SOSViewsSetCachedStatus(SOSAccount *account) { } // This is the logic to detect a new userKey: - bool userKeyChanged = !NSIsEqualSafe(self.initialKeyParameters, self.account.accountKeyDerivationParamters); + bool userKeyChanged = !NSIsEqualSafe(self.initialKeyParameters, self.account.accountKeyDerivationParameters); // This indicates we initiated a password change. bool weInitiatedKeyChange = (self.initialTrusted && diff --git a/keychain/SecureObjectSync/SOSAccountTrust.m b/keychain/SecureObjectSync/SOSAccountTrust.m index 8aafe173..c7303592 100644 --- a/keychain/SecureObjectSync/SOSAccountTrust.m +++ b/keychain/SecureObjectSync/SOSAccountTrust.m @@ -16,9 +16,7 @@ -(id)init { - self = [super init]; - if(self) - { + if ((self = [super init])) { self.retirees = [NSMutableSet set]; self.fullPeerInfo = NULL; self.trustedCircle = NULL; @@ -32,9 +30,7 @@ departureCode:(enum DepartureReason)code peerExpansion:(NSMutableDictionary*)e { - self = [super init]; - if(self) - { + if ((self = [super init])) { self.retirees = r; self.fullPeerInfo = fpi; self.trustedCircle = trusted_circle; diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h b/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h index 624badd0..e3815966 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h @@ -20,12 +20,11 @@ -(bool) isInCircleOnly:(CFErrorRef *)error; -(void) forEachCirclePeerExceptMe:(SOSIteratePeerBlock)block; -(bool) leaveCircle:(SOSAccount*)account err:(CFErrorRef*) error; --(bool) leaveCircleWithAccount:(SOSAccount*)account withAnalytics:(NSData*)parentEvent err:(CFErrorRef*) error; +-(bool) leaveCircleWithAccount:(SOSAccount*)account err:(CFErrorRef*) error; -(bool) resetToOffering:(SOSAccountTransaction*) aTxn key:(SecKeyRef)userKey err:(CFErrorRef*) error; -(bool) resetCircleToOffering:(SOSAccountTransaction*) aTxn userKey:(SecKeyRef) user_key err:(CFErrorRef *)error; -(SOSCCStatus) thisDeviceStatusInCircle:(SOSCircleRef) circle peer:(SOSPeerInfoRef) this_peer; -(bool) updateCircle:(SOSCircleStorageTransport*)circleTransport newCircle:(SOSCircleRef) newCircle err:(CFErrorRef*)error; --(bool) updateCircleWithAnalytics:(SOSCircleStorageTransport*)circleTransport newCircle:(SOSCircleRef) newCircle parentEvent:(NSData*)parentEvent err:(CFErrorRef*)error; -(bool) updateCircleFromRemote:(SOSCircleStorageTransport*)circleTransport newCircle:(SOSCircleRef)newCircle err:(CFErrorRef*)error; diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.m b/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.m index ec3b5664..3507aa1a 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.m +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.m @@ -348,44 +348,44 @@ static bool SOSCircleHasUpdatedPeerInfoWithOctagonKey(SOSCircleRef oldCircle, SO old_circle_key, account.accountKey, me, error); - CFStringRef concStr = NULL; - switch(concstat) { - case kSOSConcordanceTrusted: - circle_action = countersign; - concStr = CFSTR("Trusted"); - break; - case kSOSConcordanceGenOld: - circle_action = userTrustedOldCircle ? revert : ignore; - concStr = CFSTR("Generation Old"); - break; - case kSOSConcordanceBadUserSig: - case kSOSConcordanceBadPeerSig: - circle_action = userTrustedOldCircle ? revert : accept; - concStr = CFSTR("Bad Signature"); - break; - case kSOSConcordanceNoUserSig: - circle_action = userTrustedOldCircle ? revert : accept; - concStr = CFSTR("No User Signature"); - break; - case kSOSConcordanceNoPeerSig: - circle_action = accept; // We might like this one eventually but don't countersign. - concStr = CFSTR("No trusted peer signature"); - secnotice("signing", "##### No trusted peer signature found, accepting hoping for concordance later"); - break; - case kSOSConcordanceNoPeer: - circle_action = leave; - leave_reason = kSOSLeftUntrustedCircle; - concStr = CFSTR("No trusted peer left"); - break; - case kSOSConcordanceNoUserKey: - secerror("##### No User Public Key Available, this shouldn't ever happen!!!"); - abort(); - break; - default: - secerror("##### Bad Error Return from ConcordanceTrust"); - abort(); - break; - } + CFStringRef concStr = NULL; + switch(concstat) { + case kSOSConcordanceTrusted: + circle_action = countersign; + concStr = CFSTR("Trusted"); + break; + case kSOSConcordanceGenOld: + circle_action = userTrustedOldCircle ? revert : ignore; + concStr = CFSTR("Generation Old"); + break; + case kSOSConcordanceBadUserSig: + case kSOSConcordanceBadPeerSig: + circle_action = userTrustedOldCircle ? revert : accept; + concStr = CFSTR("Bad Signature"); + break; + case kSOSConcordanceNoUserSig: + circle_action = userTrustedOldCircle ? revert : accept; + concStr = CFSTR("No User Signature"); + break; + case kSOSConcordanceNoPeerSig: + circle_action = accept; // We might like this one eventually but don't countersign. + concStr = CFSTR("No trusted peer signature"); + secnotice("signing", "##### No trusted peer signature found, accepting hoping for concordance later"); + break; + case kSOSConcordanceNoPeer: + circle_action = leave; + leave_reason = kSOSLeftUntrustedCircle; + concStr = CFSTR("No trusted peer left"); + break; + case kSOSConcordanceNoUserKey: + secerror("##### No User Public Key Available, this shouldn't ever happen!!!"); + abort(); + break; + default: + secerror("##### Bad Error Return from ConcordanceTrust"); + abort(); + break; + } secnotice("signing", "Decided on action [%s] based on concordance state [%@] and [%s] circle. My PeerID is %@", actionstring[circle_action], concStr, userTrustedOldCircle ? "trusted" : "untrusted", myPeerID); @@ -402,7 +402,7 @@ static bool SOSCircleHasUpdatedPeerInfoWithOctagonKey(SOSCircleRef oldCircle, SO secnotice("account", "Key state: accountKey %@, previousAccountKey %@, old_circle_key %@", account.accountKey, account.previousAccountKey, old_circle_key); - if (sosAccountLeaveCircle(account, newCircle, nil, error)) { + if (sosAccountLeaveCircle(account, newCircle, error)) { secnotice("circleOps", "Leaving circle by newcircle state"); circleToPush = newCircle; } else { @@ -464,8 +464,7 @@ static bool SOSCircleHasUpdatedPeerInfoWithOctagonKey(SOSCircleRef oldCircle, SO && !(SOSCircleCountPeers(oldCircle) == 1 && SOSCircleHasPeer(oldCircle, me, NULL)) // If it was our offering, don't change ID to avoid ghosts && !SOSCircleHasPeer(newCircle, me, NULL) && !SOSCircleHasApplicant(newCircle, me, NULL)) { secnotice("circle", "Purging my peer (ID: %@) for circle '%@'!!!", SOSPeerInfoGetPeerID(me), SOSCircleGetName(oldCircle)); - if (self.fullPeerInfo) - SOSFullPeerInfoPurgePersistentKey(self.fullPeerInfo, NULL); + [self purgeIdentity]; me = NULL; me_full = NULL; } @@ -476,8 +475,7 @@ static bool SOSCircleHasUpdatedPeerInfoWithOctagonKey(SOSCircleRef oldCircle, SO secnotice("circle", "Rejected, Purging my applicant peer (ID: %@) for circle '%@'", SOSPeerInfoGetPeerID(me), SOSCircleGetName(oldCircle)); debugDumpCircle(CFSTR("oldCircle"), oldCircle); debugDumpCircle(CFSTR("newCircle"), newCircle); - if (self.fullPeerInfo) - SOSFullPeerInfoPurgePersistentKey(self.fullPeerInfo, NULL); + [self purgeIdentity]; me = NULL; me_full = NULL; } else { @@ -657,7 +655,7 @@ fail: // rdar://51233857 - don't gensign if there isn't a change in the userKey // also don't rebake the circle to fix the icloud identity if there isn't // a change as that will mess up piggybacking. - if(SOSAccountFullPeerInfoVerify(account, privKey, NULL) && SOSCircleVerify(account.trust.trustedCircle, account.accountKey, NULL)) { + if(account.trust.trustedCircle && SOSAccountFullPeerInfoVerify(account, privKey, NULL) && SOSCircleVerify(account.trust.trustedCircle, account.accountKey, NULL)) { secnotice("updatingGenSignature", "no change to userKey - skipping gensign"); return; } @@ -696,12 +694,12 @@ fail: } } --(bool) leaveCircleWithAccount:(SOSAccount*)account withAnalytics:(NSData*)parentEvent err:(CFErrorRef*) error +-(bool) leaveCircleWithAccount:(SOSAccount*)account err:(CFErrorRef*) error { bool result = true; secnotice("circleOps", "leaveCircleWithAccount: Leaving circle by client request"); result &= [self modifyCircle:account.circle_transport err:error action:^(SOSCircleRef circle) { - return sosAccountLeaveCircle(account, circle, parentEvent, error); + return sosAccountLeaveCircle(account, circle, error); }]; self.departureCode = kSOSWithdrewMembership; @@ -714,7 +712,7 @@ fail: bool result = true; secnotice("circleOps", "Leaving circle by client request"); result &= [self modifyCircle:account.circle_transport err:error action:^(SOSCircleRef circle) { - return sosAccountLeaveCircle(account, circle, nil, error); + return sosAccountLeaveCircle(account, circle, error); }]; account.backup_key = nil; self.departureCode = kSOSWithdrewMembership; @@ -724,9 +722,8 @@ fail: -(bool) resetToOffering:(SOSAccountTransaction*) aTxn key:(SecKeyRef)userKey err:(CFErrorRef*) error { - SOSFullPeerInfoPurgePersistentKey(self.fullPeerInfo, NULL); - self.fullPeerInfo = nil; - + [self purgeIdentity]; + secnotice("resetToOffering", "Resetting circle to offering by request from client"); return userKey && [self resetCircleToOffering:aTxn userKey:userKey err:error]; @@ -741,7 +738,7 @@ fail: if(![self hasCircle:error]) return result; - if(![self ensureFullPeerAvailable:(__bridge CFDictionaryRef)(account.gestalt) deviceID:(__bridge CFStringRef)(account.deviceID) backupKey:(__bridge CFDataRef)(account.backup_key) err:error]) + if(![self ensureFullPeerAvailable:account err:error]) return result; (void)[self resetAllRings:account err:error]; @@ -807,7 +804,7 @@ void SOSAccountForEachCirclePeerExceptMe(SOSAccount* account, void (^action)(SOS __block SOSFullPeerInfoRef cloud_full_peer = NULL; __block SOSAccount* account = aTxn.account; require_action_quiet(self.trustedCircle, fail, SOSCreateErrorWithFormat(kSOSErrorPeerNotFound, NULL, error, NULL, CFSTR("Don't have circle when joining???"))); - require_quiet([self ensureFullPeerAvailable:(__bridge CFDictionaryRef)account.gestalt deviceID:(__bridge CFStringRef)account.deviceID backupKey:(__bridge CFDataRef)account.backup_key err:error], fail); + require_quiet([self ensureFullPeerAvailable:account err:error], fail); if (SOSCircleCountPeers(self.trustedCircle) == 0 || SOSAccountGhostResultsInReset(account)) { secnotice("resetToOffering", "Resetting circle to offering since there are no peers"); diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h b/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h index 5d716757..e6855c86 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h @@ -21,7 +21,6 @@ -(bool) handleUpdateRing:(SOSAccount*)account prospectiveRing:(SOSRingRef)prospectiveRing transport:(SOSKVSCircleStorageTransport*)circleTransport userPublicKey:(SecKeyRef)userPublic writeUpdate:(bool)writeUpdate err:(CFErrorRef *)error; -(bool) resetRing:(SOSAccount*)account ringName:(CFStringRef) ringName err:(CFErrorRef *)error; -(bool) resetAccountToEmpty:(SOSAccount*)account transport: (SOSCircleStorageTransport*)circleTransport err:(CFErrorRef*) error; --(bool) resetAccountToEmptyWithAnalytics:(SOSAccount*)account transport: (SOSCircleStorageTransport*)circleTransport parentEvent:(NSData*)parentEvent err:(CFErrorRef*) error; -(SOSRingRef) copyRing:(CFStringRef) ringName err:(CFErrorRef *)error; -(CFMutableDictionaryRef) getRings:(CFErrorRef *)error; diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.m b/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.m index b6273573..7eaba5a1 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.m +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.m @@ -15,7 +15,6 @@ #import "keychain/SecureObjectSync/SOSPeerInfoCollections.h" #import "keychain/SecureObjectSync/SOSTransportCircleKVS.h" #import "keychain/SecureObjectSync/SOSRingRecovery.h" -#import "keychain/SigninMetrics/SFSignInAnalytics.h" @implementation SOSAccountTrustClassic (Expansion) typedef enum { @@ -202,29 +201,12 @@ errOut: } -(bool) resetAccountToEmpty:(SOSAccount*)account transport: (SOSCircleStorageTransport*)circleTransport err:(CFErrorRef*) error -{ - return [self resetAccountToEmptyWithAnalytics:account transport:circleTransport parentEvent:nil err:error ]; -} - --(bool) resetAccountToEmptyWithAnalytics:(SOSAccount*)account transport: (SOSCircleStorageTransport*)circleTransport parentEvent:(NSData*)parentEvent err:(CFErrorRef*) error { __block bool result = true; CFErrorRef resetError = NULL; - NSError* localError = nil; - SFSignInAnalytics* parent = nil; - SFSignInAnalytics *resetAllRingsEvent = nil; - bool doingAnalytics = parentEvent != nil; - - if(doingAnalytics) { - parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError]; - resetAllRingsEvent = [parent newSubTaskForEvent:@"resetAllRingsEvent"]; - } result &= [self resetAllRings:account err:&resetError]; if(resetError){ - if(doingAnalytics) { - [resetAllRingsEvent logRecoverableError:(__bridge NSError*)resetError]; - } secerror("reset all rings error: %@", resetError); if(error){ *error = resetError; @@ -232,29 +214,17 @@ errOut: CFReleaseNull(resetError); } } - if(doingAnalytics) { - [resetAllRingsEvent stopWithAttributes:nil]; - } self.fullPeerInfo = nil; self.departureCode = kSOSWithdrewMembership; secnotice("circleOps", "Reset Rings to empty by client request"); - SFSignInAnalytics *resetCircleToEmptyEvent = nil; - if(doingAnalytics) { - resetCircleToEmptyEvent = [parent newSubTaskForEvent:@"resetCircleToEmptyEvent"]; - } - result &= [self modifyCircle:circleTransport err:error action:^bool(SOSCircleRef circle) { result = SOSCircleResetToEmpty(circle, error); return result; }]; - if(doingAnalytics) { - [resetCircleToEmptyEvent stopWithAttributes:nil]; - } - if (!result) { secerror("error: %@", error ? *error : NULL); } else { @@ -332,6 +302,14 @@ errOut: CFStringRef modifierPeerID = CFStringCreateTruncatedCopy(SOSRingGetLastModifier(prospectiveRing), 8); secnotice("ring", "start:[%s] modifier: %@", localRemote, modifierPeerID); CFReleaseNull(modifierPeerID); + + // don't act on our own echos from KVS (remote ring, our peerID as modifier) + if(!localUpdate && CFEqualSafe(peerID, SOSRingGetLastModifier(prospectiveRing))) { + secnotice("ring", "Ceasing ring handling for an echo of our own posted ring"); + success = true; + goto errOut; + } + require_quiet(SOSAccountHasPublicKey(account, error), errOut); require_action_quiet(peerPubKey, errOut, SOSCreateError(kSOSErrorPublicKeyAbsent, CFSTR("No device public key to work with"), NULL, error)); require_action_quiet(peerPrivKey, errOut, SOSCreateError(kSOSErrorPrivateKeyAbsent, CFSTR("No device private key to work with"), NULL, error)); @@ -424,6 +402,7 @@ errOut: // This will take care of modify, but we're always going to do this scan if we get this far CFSetRef ringPeerIDSet = SOSRingCopyPeerIDs(newRing); if(CFSetGetCount(ringPeerIDSet) == 0) { // this is a reset ring + secnotice("ring", "changing state to accept - we have a reset ring"); ringAction = accept; } else { // Get the peerIDs appropriate for the ring @@ -440,6 +419,9 @@ errOut: } if(!CFEqual(filteredPeerIDs, ringPeerIDSet)) { + secnotice("ring", "mismatch between filteredPeerIDs and ringPeerIDSet, fixing ring and gensigning"); + secnotice("ring", "filteredPeerIDs %@", filteredPeerIDs); + secnotice("ring", " ringPeerIDSet %@", ringPeerIDSet); SOSRingSetPeerIDs(newRing, filteredPeerIDs); SOSRingRemoveSignatures(newRing, NULL); ringAction = countersign; @@ -457,14 +439,27 @@ errOut: __block bool fixBSKB = false; CFDataRef recoveryKeyData = SOSAccountCopyRecoveryPublic(kCFAllocatorDefault, account, NULL); SOSBackupSliceKeyBagRef currentBSKB = SOSRingCopyBackupSliceKeyBag(newRing, NULL); + + if(currentBSKB == NULL) { + secnotice("ring", "Backup ring contains no BSKB"); + fixBSKB = true; + } + + if(SOSBSKBAllPeersBackupKeysAreInKeyBag(currentBSKB, filteredPeerInfos) == false) { + secnotice("ring", "BSKB is missing some backup keys"); + fixBSKB = true; + } - fixBSKB = !currentBSKB || - !SOSBSKBAllPeersBackupKeysAreInKeyBag(currentBSKB, filteredPeerInfos) || - !SOSBSKBHasThisRecoveryKey(currentBSKB, recoveryKeyData); + if(SOSBSKBHasThisRecoveryKey(currentBSKB, recoveryKeyData) == false) { + secnotice("ring", "BSKB is missing recovery key"); + fixBSKB = true; + } if(fixBSKB) { CFErrorRef localError = NULL; CFSetRef viewSet = SOSRingGetBackupViewset(newRing, NULL); + secnotice("ring", "Need to fix BSKB - this will prompt a gensign"); + SOSBackupSliceKeyBagRef bskb = NULL; if(recoveryKeyData) { CFMutableDictionaryRef additionalKeys = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); @@ -498,6 +493,7 @@ errOut: } else { CFErrorRef signingError = NULL; if (fpi && SOSRingConcordanceSign(newRing, fpi, &signingError)) { + secnotice("ring", "concordance signed"); ringToPush = newRing; ringAction = accept; } else { @@ -515,10 +511,12 @@ leaveAndAccept: if(ringIsRecovery) { if(!localUpdate) { // processing a remote ring - we accept the new recovery key here if(SOSRingIsEmpty_Internal(newRing)) { // Reset ring will reset the recovery key + secnotice("ring", "Reset ring for recovery from remote peer"); SOSRecoveryKeyBagRef ringRKBG = SOSRecoveryKeyBagCreateForAccount(kCFAllocatorDefault, (__bridge CFTypeRef)account, SOSRKNullKey(), error); SOSAccountSetRecoveryKeyBagEntry(kCFAllocatorDefault, account, ringRKBG, error); CFReleaseNull(ringRKBG); } else { // normal ring recovery key harvest + secnotice("ring", "normal ring recovery key harvest"); SOSRecoveryKeyBagRef ringRKBG = SOSRingCopyRecoveryKeyBag(newRing, NULL); SOSAccountSetRecoveryKeyBagEntry(kCFAllocatorDefault, account, ringRKBG, error); CFReleaseNull(ringRKBG); diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h b/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h index 0bd9cd22..07890687 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h @@ -17,7 +17,7 @@ -(bool) fullPeerInfoVerify:(SecKeyRef) privKey err:(CFErrorRef *)error; -(bool) hasFullPeerInfo:(CFErrorRef*) error; -(SOSFullPeerInfoRef) CopyAccountIdentityPeerInfo CF_RETURNS_RETAINED; --(bool) ensureFullPeerAvailable:(CFDictionaryRef)gestalt deviceID:(CFStringRef)deviceID backupKey:(CFDataRef)backup err:(CFErrorRef *) error; +-(bool) ensureFullPeerAvailable:(SOSAccount*)account err:(CFErrorRef *) error; -(bool) isMyPeerActive:(CFErrorRef*) error; -(void) purgeIdentity; diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.m b/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.m index d72bd125..1cca6e06 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.m +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.m @@ -10,6 +10,10 @@ #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h" #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h" #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" +#import +#import +#import +#import #if __OBJC2__ #import "Analytics/Clients/SOSAnalytics.h" #endif // __OBJC2__ @@ -135,6 +139,10 @@ secnotice("circleChange", "Already have Octagon signing key"); CFReleaseNull(self->_cachedOctagonSigningKey); _cachedOctagonSigningKey = SecKeyCopyPublicKey(octagonSigningFullKey); + + // Ensure that the agrp is correct. + SOSCCEnsureAccessGroupOfKey(_cachedOctagonSigningKey, @"sync", (__bridge NSString*)kSOSInternalAccessGroup); + } else if (octagonSigningFullKey == NULL && copyError && ((CFEqualSafe(CFErrorGetDomain(copyError), kCFErrorDomainOSStatus) && CFErrorGetCode(copyError) == errSecItemNotFound) || (CFEqualSafe(CFErrorGetDomain(copyError), kCFErrorDomainOSStatus) && CFErrorGetCode(copyError) == errSecDecode) || @@ -178,6 +186,8 @@ secnotice("circleChange", "Already have Octagon encryption key"); CFReleaseNull(self->_cachedOctagonEncryptionKey); _cachedOctagonEncryptionKey = SecKeyCopyPublicKey(octagonEncryptionFullKey); + + SOSCCEnsureAccessGroupOfKey(_cachedOctagonEncryptionKey, @"sync", (__bridge NSString*)kSOSInternalAccessGroup); } else if (octagonEncryptionFullKey == NULL && copyError && ((CFEqualSafe(CFErrorGetDomain(copyError), kCFErrorDomainOSStatus) && CFErrorGetCode(copyError) == errSecItemNotFound) || (CFEqualSafe(CFErrorGetDomain(copyError), kCFErrorDomainOSStatus) && CFErrorGetCode(copyError) == errSecDecode) || @@ -217,23 +227,44 @@ #endif /* OCTAGON */ } --(bool) ensureFullPeerAvailable:(CFDictionaryRef)gestalt deviceID:(CFStringRef)deviceID backupKey:(CFDataRef)backup err:(CFErrorRef *) error +-(bool) ensureFullPeerAvailable:(SOSAccount*) account err:(CFErrorRef *) error { require_action_quiet(self.trustedCircle, fail, SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("Don't have circle"))); - - if (self.fullPeerInfo == NULL) { + + if (self.fullPeerInfo == NULL || !SOSFullPeerInfoPrivKeyExists(self.fullPeerInfo)) { + if(self.fullPeerInfo) { // fullPeerInfo where privkey is gone + secnotice("circleOps", "FullPeerInfo has no matching private key - resetting FPI and attendant keys"); + CFReleaseNull(self->fullPeerInfo); + if(self->peerInfo) CFReleaseNull(self->peerInfo); + if(self->_cachedOctagonSigningKey) CFReleaseNull(self->_cachedOctagonSigningKey); + if(self->_cachedOctagonEncryptionKey) CFReleaseNull(self->_cachedOctagonEncryptionKey); + } + + SecKeyRef fullKey = NULL; bool skipInitialSync = false; // This will be set if the set of initial sync views is empty NSString* octagonKeyName; - CFStringRef keyName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("ID for %@-%@"), SOSPeerGestaltGetName(gestalt), SOSCircleGetName(self.trustedCircle)); - SecKeyRef full_key = [self randomPermanentFullECKey:256 name:(__bridge NSString *)keyName error:NULL]; + CFStringRef keyName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("ID for %@-%@"), SOSPeerGestaltGetName((__bridge CFDictionaryRef)(account.gestalt)), SOSCircleGetName(self.trustedCircle)); + fullKey = [self randomPermanentFullECKey:256 name:(__bridge NSString *)keyName error:NULL]; octagonKeyName = [@"Octagon Peer Signing " stringByAppendingString:(__bridge NSString*)keyName]; - SecKeyRef octagonSigningFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:NULL]; + + SecKeyRef octagonSigningFullKey = NULL; + if (account.octagonSigningFullKeyRef != NULL) { + octagonSigningFullKey = CFRetainSafe(account.octagonSigningFullKeyRef); + } else { + octagonSigningFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:NULL]; + } octagonKeyName = [@"Octagon Peer Encryption " stringByAppendingString:(__bridge NSString*)keyName]; - SecKeyRef octagonEncryptionFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:NULL]; - if (full_key && octagonSigningFullKey && octagonEncryptionFullKey) { + SecKeyRef octagonEncryptionFullKey = NULL; + if (account.octagonEncryptionFullKeyRef != NULL){ + octagonEncryptionFullKey = CFRetainSafe(account.octagonEncryptionFullKeyRef); + } else { + octagonEncryptionFullKey = [self randomPermanentFullECKey:384 name:octagonKeyName error:NULL]; + } + + if (fullKey && octagonSigningFullKey && octagonEncryptionFullKey) { CFMutableSetRef initialViews = SOSViewCopyViewSet(kViewSetInitial); CFMutableSetRef initialSyncDoneViews = SOSViewCopyViewSet(kViewSetAlwaysOn); CFSetRef defaultViews = SOSViewCopyViewSet(kViewSetDefault); @@ -250,8 +281,14 @@ // setting fullPeerInfo takes an extra ref, so... self.fullPeerInfo = nil; - SOSFullPeerInfoRef fpi = SOSFullPeerInfoCreateWithViews(kCFAllocatorDefault, gestalt, backup, initialViews, full_key, octagonSigningFullKey, octagonEncryptionFullKey, error); + SOSFullPeerInfoRef fpi = SOSFullPeerInfoCreateWithViews(kCFAllocatorDefault, (__bridge CFDictionaryRef)(account.gestalt), (__bridge CFDataRef)(account.backup_key), initialViews, fullKey, octagonSigningFullKey, octagonEncryptionFullKey, error); self.fullPeerInfo = fpi; + SecKeyRef pubKey = SOSFullPeerInfoCopyPubKey(fpi, NULL); + account.peerPublicKey = pubKey; + CFReleaseNull(pubKey); + if(!account.peerPublicKey) { + secnotice("circleOp", "Failed to copy peer public key for account object"); + } CFReleaseNull(fpi); CFDictionaryRef v2dictionaryTestUpdates = [self getValueFromExpansion:kSOSTestV2Settings err:NULL]; @@ -272,7 +309,7 @@ } - CFReleaseNull(full_key); + CFReleaseNull(fullKey); CFReleaseNull(octagonSigningFullKey); CFReleaseNull(octagonEncryptionFullKey); CFReleaseNull(keyName); @@ -292,7 +329,7 @@ fail: // Purge private key but don't return error if we can't. CFErrorRef purgeError = NULL; if (!SOSFullPeerInfoPurgePersistentKey(self.fullPeerInfo, &purgeError)) { - secwarning("Couldn't purge persistent key for %@ [%@]", self.fullPeerInfo, purgeError); + secwarning("Couldn't purge persistent keys for %@ [%@]", self.fullPeerInfo, purgeError); } CFReleaseNull(purgeError); diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic.h b/keychain/SecureObjectSync/SOSAccountTrustClassic.h index a1a2e237..0188cf36 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic.h +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic.h @@ -32,7 +32,7 @@ //Views -(SOSViewResultCode) updateView:(SOSAccount*)account name:(CFStringRef) viewname code:(SOSViewActionCode) actionCode err:(CFErrorRef *)error; -(SOSViewResultCode) viewStatus:(SOSAccount*)account name:(CFStringRef) viewname err:(CFErrorRef *)error; --(bool) updateViewSetsWithAnalytics:(SOSAccount*)account enabled:(CFSetRef) origEnabledViews disabled:(CFSetRef) origDisabledViews parentEvent:(NSData*)parentEvent; +-(bool) updateViewSets:(SOSAccount*)account enabled:(CFSetRef) origEnabledViews disabled:(CFSetRef) origDisabledViews; -(CFSetRef) copyPeerSetForView:(CFStringRef) viewName; diff --git a/keychain/SecureObjectSync/SOSAccountTrustClassic.m b/keychain/SecureObjectSync/SOSAccountTrustClassic.m index 10459637..76831260 100644 --- a/keychain/SecureObjectSync/SOSAccountTrustClassic.m +++ b/keychain/SecureObjectSync/SOSAccountTrustClassic.m @@ -36,9 +36,7 @@ extern CFStringRef kSOSAccountDebugScope; -(id)init { - self = [super init]; - if(self) - { + if ((self = [super init])) { self.retirees = [NSMutableSet set]; self.fullPeerInfo = NULL; self.trustedCircle = NULL; @@ -52,9 +50,7 @@ extern CFStringRef kSOSAccountDebugScope; -(id)initWithRetirees:(NSMutableSet*)r fpi:(SOSFullPeerInfoRef)fpi circle:(SOSCircleRef) trusted_circle departureCode:(enum DepartureReason)code peerExpansion:(NSMutableDictionary*)e { - self = [super init]; - if(self) - { + if ((self = [super init])) { self.retirees = [[NSMutableSet alloc] initWithSet:r] ; self.fullPeerInfo = CFRetainSafe(fpi); self.trustedCircle = CFRetainSafe(trusted_circle); @@ -211,21 +207,11 @@ static bool SOSAccountScreenViewListForValidV0(SOSAccount* account, CFMutableSe return retval; } --(bool) updateViewSetsWithAnalytics:(SOSAccount*)account enabled:(CFSetRef) origEnabledViews disabled:(CFSetRef) origDisabledViews parentEvent:(NSData*)parentEvent +-(bool) updateViewSets:(SOSAccount*)account enabled:(CFSetRef) origEnabledViews disabled:(CFSetRef) origDisabledViews { bool retval = false; bool updateCircle = false; SOSPeerInfoRef pi = NULL; - NSError* localError = nil; - SFSignInAnalytics* parent = NULL; - bool doAnalytics = (parentEvent != NULL); - - if(doAnalytics) { - parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError]; - } - - SFSignInAnalytics *hasCompletedInitialSyncEvent = nil; - SFSignInAnalytics *updatePeerInCircleEvent = nil; CFMutableSetRef enabledViews = NULL; CFMutableSetRef disabledViews = NULL; @@ -263,9 +249,7 @@ static bool SOSAccountScreenViewListForValidV0(SOSAccount* account, CFMutableSe require_action_quiet(SOSAccountScreenViewListForValidV0(account, enabledViews, kSOSCCViewEnable), errOut, secnotice("viewChange", "Bad view change (enable) with kSOSViewKeychainV0")); require_action_quiet(SOSAccountScreenViewListForValidV0(account, disabledViews, kSOSCCViewDisable), errOut, secnotice("viewChange", "Bad view change (disable) with kSOSViewKeychainV0")); - if(doAnalytics) { - hasCompletedInitialSyncEvent = [parent newSubTaskForEvent:@"hasCompletedInitialSyncEvent"]; - } + if(SOSAccountHasCompletedInitialSync(account)) { if(enabledViews) updateCircle |= SOSViewSetEnable(pi, enabledViews); if(disabledViews) updateCircle |= SOSViewSetDisable(pi, disabledViews); @@ -276,31 +260,21 @@ static bool SOSAccountScreenViewListForValidV0(SOSAccount* account, CFMutableSe if(disabledViews) SOSAccountPendDisableViewSet(account, disabledViews); retval = true; } - if(doAnalytics) { - [hasCompletedInitialSyncEvent stopWithAttributes:nil]; - } + if(updateCircle) { /* UPDATE FULLPEERINFO VIEWS */ require_quiet(SOSFullPeerInfoUpdateToThisPeer(fpi, pi, NULL), errOut); - if(doAnalytics) { - updatePeerInCircleEvent = [parent newSubTaskForEvent:@"updatePeerInCircleEvent"]; - } + require_quiet([self modifyCircle:account.circle_transport err:NULL action:^(SOSCircleRef circle_to_change) { secnotice("circleChange", "Calling SOSCircleUpdatePeerInfo for views or peerInfo change"); bool updated= SOSCircleUpdatePeerInfo(circle_to_change, self.peerInfo); return updated; }], errOut); - if(doAnalytics) { - [updatePeerInCircleEvent stopWithAttributes:nil]; - } // Make sure we update the engine account.circle_rings_retirements_need_attention = true; } errOut: - if(doAnalytics) { - [updatePeerInCircleEvent stopWithAttributes:nil]; - } CFReleaseNull(enabledViews); CFReleaseNull(disabledViews); CFReleaseNull(pi); @@ -564,7 +538,7 @@ static size_t der_sizeof_data_optional(CFDataRef data) require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account.accountKeyIsTrusted, &failure)), fail); require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account.accountKey, &failure)), fail); require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account.previousAccountKey, &failure)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null((__bridge CFDataRef)account.accountKeyDerivationParamters, &failure)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null((__bridge CFDataRef)account.accountKeyDerivationParameters, &failure)), fail); require_quiet(accumulate_size(&sequence_size, SOSPeerInfoSetGetDEREncodedArraySize((__bridge CFSetRef)self.retirees, &failure)), fail); (void)accumulate_size(&sequence_size, der_sizeof_data_optional((__bridge CFDataRef)(account.backup_key))); require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary((__bridge CFDictionaryRef)(self.expansion), &failure)), fail); @@ -605,7 +579,7 @@ static uint8_t* der_encode_data_optional(CFDataRef data, CFErrorRef *error, ccder_encode_bool(account.accountKeyIsTrusted, der, der_encode_public_bytes(account.accountKey, &failure, der, der_encode_public_bytes(account.previousAccountKey, &failure, der, - der_encode_data_or_null((__bridge CFDataRef)(account.accountKeyDerivationParamters), &failure, der, + der_encode_data_or_null((__bridge CFDataRef)(account.accountKeyDerivationParameters), &failure, der, SOSPeerInfoSetEncodeToArrayDER((__bridge CFSetRef)(self.retirees), &failure, der, der_encode_data_optional((__bridge CFDataRef)account.backup_key, &failure, der, der_encode_dictionary((__bridge CFDictionaryRef)(self.expansion), &failure, der, @@ -717,6 +691,11 @@ static uint8_t* der_encode_data_optional(CFDataRef data, CFErrorRef *error, -(SOSEngineRef) getDataSourceEngine:(SOSDataSourceFactoryRef)factory { + // This is at least a piece of SecItemDataSourceFactoryCopyDataSource; looks like UaF + if(!self.trustedCircle) { + secnotice("engine", "Tried to set dataSourceEngine with no circle"); + return NULL; + } return SOSDataSourceFactoryGetEngineForDataSourceName(factory, SOSCircleGetName(self.trustedCircle), NULL); } diff --git a/keychain/SecureObjectSync/SOSAccountUpdate.m b/keychain/SecureObjectSync/SOSAccountUpdate.m index 9c0cad82..f4098276 100644 --- a/keychain/SecureObjectSync/SOSAccountUpdate.m +++ b/keychain/SecureObjectSync/SOSAccountUpdate.m @@ -162,6 +162,8 @@ bool SOSAccountSyncingV0(SOSAccount* account) { void SOSAccountNotifyEngines(SOSAccount* account) { + dispatch_assert_queue(account.queue); + SOSAccountTrustClassic *trust = account.trust; SOSFullPeerInfoRef identity = trust.fullPeerInfo; SOSCircleRef circle = trust.trustedCircle; @@ -179,7 +181,10 @@ void SOSAccountNotifyEngines(SOSAccount* account) // We add V0 views to everyone if we see a V0 peer, or a peer with the view explicity enabled // V2 peers shouldn't be explicity enabling the uber V0 view, though the seeds did. __block bool addV0Views = SOSAccountSyncingV0(account); - + + bool selfSupportCKKSForAll = SOSPeerInfoSupportsCKKSForAll(myPi); + secnotice("engine-notify", "Self peer(%@) %@ CKKS For All", myPi_id, selfSupportCKKSForAll ? @"supports" : @"doesn't support"); + syncing_peer_metas = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); zombie_peer_metas = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); SOSAccountForEachCirclePeerExceptMe(account, ^(SOSPeerInfoRef peer) { @@ -193,6 +198,12 @@ void SOSAccountNotifyEngines(SOSAccount* account) if(addV0Views) { CFSetAddValue(views, kSOSViewKeychainV0); } + + // If this peer supports CKKS4All, let's sync zero views to it. + if(selfSupportCKKSForAll && SOSPeerInfoSupportsCKKSForAll(peer)) { + secnotice("engine-notify", "Peer %@ supports CKKS For All; ignoring in SOS syncing", SOSPeerInfoGetPeerID(peer)); + CFSetRemoveAllValues(views); + } CFStringSetPerformWithDescription(views, ^(CFStringRef viewsDescription) { secnotice("engine-notify", "Meta: %@: %@", SOSPeerInfoGetPeerID(peer), viewsDescription); @@ -345,6 +356,12 @@ bool SOSAccountHandleCircleMessage(SOSAccount* account, CFStringRef circleName, CFDataRef encodedCircleMessage, CFErrorRef *error) { bool success = false; CFErrorRef localError = NULL; + + if(account && account.accountIsChanging) { + secnotice("circleOps", "SOSAccountHandleCircleMessage called before signing in to new account"); + return true; // we want to drop circle notifications when account is changing + } + SOSCircleRef circle = SOSAccountCreateCircleFrom(circleName, encodedCircleMessage, &localError); if (circle) { success = [account.trust updateCircleFromRemote:account.circle_transport newCircle:circle err:&localError]; @@ -372,14 +389,20 @@ bool SOSAccountHandleCircleMessage(SOSAccount* account, } bool SOSAccountHandleParametersChange(SOSAccount* account, CFDataRef parameters, CFErrorRef *error){ + if(account && account.accountIsChanging) { + secnotice("circleOps", "SOSAccountHandleParametersChange called before signing in to new account"); + return true; // we want to drop parm notifications when account is changing + } SecKeyRef newKey = NULL; - CFDataRef newParameters = NULL; + CFDataRef pbkdfParams = NULL; bool success = false; - if(SOSAccountRetrieveCloudParameters(account, &newKey, parameters, &newParameters, error)) { - debugDumpUserParameters(CFSTR("SOSAccountHandleParametersChange got new user key parameters:"), parameters); - secnotice("circleOps", "SOSAccountHandleParametersChange got new public key: %@", newKey); + if(SOSAccountRetrieveCloudParameters(account, &newKey, parameters, &pbkdfParams, error)) { + debugDumpUserParameters(CFSTR("SOSAccountHandleParametersChange got new user key parameters:"), pbkdfParams); + CFStringRef keyid = SOSCopyIDOfKeyWithLength(newKey, 8, NULL); + secnotice("circleOps", "SOSAccountHandleParametersChange got new public key: %@", keyid); + CFReleaseNull(keyid); if (CFEqualSafe(account.accountKey, newKey)) { secnotice("circleOps", "Got same public key sent our way. Ignoring."); @@ -390,7 +413,7 @@ bool SOSAccountHandleParametersChange(SOSAccount* account, CFDataRef parameters, } else { SOSAccountSetUnTrustedUserPublicKey(account, newKey); CFReleaseNull(newKey); - SOSAccountSetParameters(account, newParameters); + SOSAccountSetParameters(account, pbkdfParams); if(SOSAccountRetryUserCredentials(account)) { secnotice("circleOps", "Successfully used cached password with new parameters"); @@ -408,7 +431,7 @@ bool SOSAccountHandleParametersChange(SOSAccount* account, CFDataRef parameters, } CFReleaseNull(newKey); - CFReleaseNull(newParameters); + CFReleaseNull(pbkdfParams); return success; } diff --git a/keychain/SecureObjectSync/SOSAccountViewSync.m b/keychain/SecureObjectSync/SOSAccountViewSync.m index f619a750..c592b0bd 100644 --- a/keychain/SecureObjectSync/SOSAccountViewSync.m +++ b/keychain/SecureObjectSync/SOSAccountViewSync.m @@ -185,7 +185,7 @@ static bool SOSAccountResolvePendingViewSets(SOSAccount* account, CFErrorRef *er } CFReleaseNull(defaultOn); - bool status = [account.trust updateViewSetsWithAnalytics:account enabled:newPending disabled:pendingDisabled parentEvent: NULL]; + bool status = [account.trust updateViewSets:account enabled:newPending disabled:pendingDisabled]; CFReleaseNull(newPending); if(status){ diff --git a/keychain/SecureObjectSync/SOSAuthKitHelpers.m b/keychain/SecureObjectSync/SOSAuthKitHelpers.m index 03ea585d..36ca8e09 100644 --- a/keychain/SecureObjectSync/SOSAuthKitHelpers.m +++ b/keychain/SecureObjectSync/SOSAuthKitHelpers.m @@ -30,7 +30,6 @@ SOFT_LINK_CLASS(AuthKit, AKAccountManager); SOFT_LINK_CLASS(AuthKit, AKAnisetteProvisioningController); SOFT_LINK_CLASS(AuthKit, AKAppleIDAuthenticationController); SOFT_LINK_CLASS(AuthKit, AKDeviceListRequestContext); -SOFT_LINK_CLASS(Accounts, Accounts); SOFT_LINK_CLASS(Accounts, ACAccountStore); SOFT_LINK_CONSTANT(AuthKit, AKServiceNameiCloud, const NSString *); #pragma clang diagnostic pop @@ -189,29 +188,27 @@ static ACAccount *GetPrimaryAccount(void) { -(id) initWithActiveMIDS: (NSSet *) theMidList { - self = [super init]; - if(!self){ - return nil; - } - NSMutableSet *MmachineIDs = [[NSMutableSet alloc] init]; - NSMutableSet *MserialNumbers = [[NSMutableSet alloc] init]; - _machineIDs = [[NSSet alloc] init]; - _serialNumbers = [[NSSet alloc] init]; - - if(!theMidList) return nil; - _midList = theMidList; + if ((self = [super init])) { + NSMutableSet *MmachineIDs = [[NSMutableSet alloc] init]; + NSMutableSet *MserialNumbers = [[NSMutableSet alloc] init]; + _machineIDs = [[NSSet alloc] init]; + _serialNumbers = [[NSSet alloc] init]; + + if(!theMidList) return nil; + _midList = theMidList; + + for(SOSTrustedDeviceAttributes *dev in _midList) { + if(dev.machineID) { + [MmachineIDs addObject:dev.machineID]; + } + if(dev.serialNumber) { + [MserialNumbers addObject:dev.serialNumber]; + } - for(SOSTrustedDeviceAttributes *dev in _midList) { - if(dev.machineID) { - [MmachineIDs addObject:dev.machineID]; - } - if(dev.serialNumber) { - [MserialNumbers addObject:dev.serialNumber]; } - + _machineIDs = MmachineIDs; + _serialNumbers = MserialNumbers; } - _machineIDs = MmachineIDs; - _serialNumbers = MserialNumbers; return self; } diff --git a/keychain/SecureObjectSync/SOSBackupSliceKeyBag.m b/keychain/SecureObjectSync/SOSBackupSliceKeyBag.m index f41ad4b6..847f7463 100644 --- a/keychain/SecureObjectSync/SOSBackupSliceKeyBag.m +++ b/keychain/SecureObjectSync/SOSBackupSliceKeyBag.m @@ -49,7 +49,6 @@ #include #include "SOSKeyedPubKeyIdentifier.h" #include "keychain/SecureObjectSync/SOSInternal.h" -#include "SecADWrapper.h" #include "SecCFAllocator.h" CFStringRef bskbRkbgPrefix = CFSTR("RK"); @@ -131,10 +130,10 @@ const uint8_t* der_decode_BackupSliceKeyBag(CFAllocatorRef allocator, der = ccder_decode_sequence_tl(&sequence_end, der, der_end); require_quiet(sequence_end == der_end, fail); - der = der_decode_data(kCFAllocatorDefault, kCFPropertyListImmutable, &vb->aks_bag, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &vb->aks_bag, error, der, sequence_end); vb->peers = SOSPeerInfoSetCreateFromArrayDER(kCFAllocatorDefault, &kSOSPeerSetCallbacks, error, &der, der_end); - der = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &vb->wrapped_keys, error, der, sequence_end); + der = der_decode_dictionary(kCFAllocatorDefault, &vb->wrapped_keys, error, der, sequence_end); require_quiet(SecRequirementError(der == der_end, error, CFSTR("Extra space in sequence")), fail); @@ -489,17 +488,17 @@ bool SOSBKSBPeerBackupKeyIsInKeyBag(SOSBackupSliceKeyBagRef backupSliceKeyBag, S return result; } -// returns true if all peers in (peers) and only those peers have matching backupKeys in the BSKB bool SOSBSKBAllPeersBackupKeysAreInKeyBag(SOSBackupSliceKeyBagRef backupSliceKeyBag, CFSetRef peers) { - __block bool result = false; + // earlier we had to accept BSKBs listing peers without backup keys for compatibility. For that reason + // this routine will iterate over the peers given and only disqualify the BSKB if it doesn't include the backup key of a peer with one. + __block bool result = true; if(backupSliceKeyBag && peers) { - result = (SOSBSKBCountPeers(backupSliceKeyBag) == CFSetGetCount(peers)); - if(result) { - CFSetForEach(peers, ^(const void *value) { - SOSPeerInfoRef pi = asSOSPeerInfo(value); - result &= pi && SOSBKSBPeerBackupKeyIsInKeyBag(backupSliceKeyBag, pi); - }); - } + CFSetForEach(peers, ^(const void *value) { + SOSPeerInfoRef pi = asSOSPeerInfo(value); + if(pi && SOSPeerInfoHasBackupKey(pi)) { + result &= SOSBKSBPeerBackupKeyIsInKeyBag(backupSliceKeyBag, pi); + } + }); } return result; } diff --git a/keychain/SecureObjectSync/SOSChangeTracker.h b/keychain/SecureObjectSync/SOSChangeTracker.h index 0b68d4bc..4731c9a8 100644 --- a/keychain/SecureObjectSync/SOSChangeTracker.h +++ b/keychain/SecureObjectSync/SOSChangeTracker.h @@ -31,6 +31,8 @@ #include "keychain/SecureObjectSync/SOSDataSource.h" +#include "utilities/simulatecrash_assert.h" + __BEGIN_DECLS enum { diff --git a/keychain/SecureObjectSync/SOSCircle.c b/keychain/SecureObjectSync/SOSCircle.c index b80f1e0d..4dc4ff30 100644 --- a/keychain/SecureObjectSync/SOSCircle.c +++ b/keychain/SecureObjectSync/SOSCircle.c @@ -59,7 +59,7 @@ #include #include -#include +#include CFGiblisWithCompareFor(SOSCircle); diff --git a/keychain/SecureObjectSync/SOSCircleDer.c b/keychain/SecureObjectSync/SOSCircleDer.c index b44e9287..f60ee4ce 100644 --- a/keychain/SecureObjectSync/SOSCircleDer.c +++ b/keychain/SecureObjectSync/SOSCircleDer.c @@ -28,24 +28,9 @@ #include #include #include -#include #include "SOSCircleDer.h" -static const uint8_t* der_decode_mutable_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability, - CFMutableDictionaryRef* dictionary, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - CFDictionaryRef theDict; - const uint8_t* result = der_decode_dictionary(allocator, mutability, &theDict, error, der, der_end); - - if (result != NULL) - *dictionary = (CFMutableDictionaryRef)theDict; - - return result; -} - - SOSCircleRef SOSCircleCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, const uint8_t** der_p, const uint8_t *der_end) { SOSCircleRef cir = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator); @@ -70,15 +55,17 @@ SOSCircleRef SOSCircleCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, require_action_quiet(version == kOnlyCompatibleVersion, fail, SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Bad Circle Version"), NULL, error)); - *der_p = der_decode_string(allocator, 0, &cir->name, error, *der_p, sequence_end); + *der_p = der_decode_string(allocator, &cir->name, error, *der_p, sequence_end); cir->generation = SOSGenCountCreateFromDER(kCFAllocatorDefault, error, der_p, sequence_end); cir->peers = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); cir->applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); cir->rejected_applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); - *der_p = der_decode_mutable_dictionary(allocator, kCFPropertyListMutableContainersAndLeaves, - &cir->signatures, error, *der_p, sequence_end); + CFDictionaryRef tmp = NULL; + *der_p = der_decode_dictionary(allocator, &tmp, error, *der_p, sequence_end); + cir->signatures = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, tmp); + CFReleaseNull(tmp); require_action_quiet(*der_p == sequence_end, fail, SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error)); @@ -192,7 +179,7 @@ const uint8_t* der_decode_data_or_null(CFAllocatorRef allocator, CFDataRef* data const uint8_t* der, const uint8_t* der_end) { CFTypeRef value = NULL; - der = der_decode_plist(allocator, 0, &value, error, der, der_end); + der = der_decode_plist(allocator, &value, error, der, der_end); if (value && CFGetTypeID(value) != CFDataGetTypeID()) { CFReleaseNull(value); } diff --git a/keychain/SecureObjectSync/SOSCirclePriv.h b/keychain/SecureObjectSync/SOSCirclePriv.h index 79852a34..21aa0947 100644 --- a/keychain/SecureObjectSync/SOSCirclePriv.h +++ b/keychain/SecureObjectSync/SOSCirclePriv.h @@ -13,6 +13,8 @@ #include #include "keychain/SecureObjectSync/SOSGenCount.h" +#include + enum { kOnlyCompatibleVersion = 1, // Sometime in the future this name will be improved to reflect history. kAlwaysIncompatibleVersion = UINT64_MAX, diff --git a/keychain/SecureObjectSync/SOSCloudCircle.h b/keychain/SecureObjectSync/SOSCloudCircle.h index 0f3df9b6..4026c299 100644 --- a/keychain/SecureObjectSync/SOSCloudCircle.h +++ b/keychain/SecureObjectSync/SOSCloudCircle.h @@ -39,7 +39,6 @@ #include #include -#import __BEGIN_DECLS @@ -72,6 +71,7 @@ enum { typedef CF_OPTIONS(uint32_t, SOSInitialSyncFlags) { kSOSInitialSyncFlagTLKs = (1UL << 0), kSOSInitialSyncFlagiCloudIdentity = (1UL << 1), + kSOSInitialSyncFlagTLKsRequestOnly = (1UL << 2), // Note that this overrides the other two flags, as it's used for aborting the piggybacking session early and returning a very small number of TLKs }; @@ -126,7 +126,6 @@ bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CF */ bool SOSCCSetUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error); -bool SOSCCSetUserCredentialsAndDSIDWithAnalytics(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentevent, CFErrorRef *error); /*! @function SOSCCTryUserCredentials @@ -158,7 +157,6 @@ bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_passwor @return if we waited successfully */ bool SOSCCWaitForInitialSync(CFErrorRef* error); -bool SOSCCWaitForInitialSyncWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); /*! @function SOSCCCanAuthenticate @@ -247,7 +245,6 @@ bool SOSCCIsContinuityUnlockSyncing(void); @discussion Requests to join the user's circle or all the pending circles (other than his) if there are multiple pending circles. */ bool SOSCCRequestToJoinCircle(CFErrorRef* error); -bool SOSCCRequestToJoinCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); /*! @@ -258,7 +255,6 @@ bool SOSCCRequestToJoinCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* er @discussion Uses the cloud identity to get in the circle if it can. If it cannot it falls back on simple application. */ bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error); -bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); /*! @function SOSCCAccountSetToNew @@ -283,7 +279,6 @@ bool SOSCCResetToOffering(CFErrorRef* error); @result true if we posted the circle successfully. False if there was an error. */ bool SOSCCResetToEmpty(CFErrorRef* error); -bool SOSCCResetToEmptyWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); /*! @function SOSCCRemoveThisDeviceFromCircle @@ -294,7 +289,6 @@ bool SOSCCResetToEmptyWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); */ bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error); -bool SOSCCRemoveThisDeviceFromCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error); /*! @function SOSCCRemoveThisDeviceFromCircle @@ -306,14 +300,18 @@ bool SOSCCRemoveThisDeviceFromCircleWithAnalytics(CFDataRef parentEvent, CFError that we don't have the user credentail (need to prompt for password) */ bool SOSCCRemovePeersFromCircle(CFArrayRef peerList, CFErrorRef* error); -bool SOSCCRemovePeersFromCircleWithAnalytics(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error); /*! - @function SOSCCRemoveThisDeviceFromCircle - @abstract Removes the current device from the circle. - @param error What went wrong trying to remove ourselves. - @result true if we posted the removal. False if there was an error. - @discussion This removes us from the circle. + @function SOSCCLoggedIntoAccount + @param error value set if there are xpc errors. + @abstract Notifies the account object that the device logged into an icloud account + */ +bool SOSCCLoggedIntoAccount(CFErrorRef* error); + +/*! + @function SOSCCLoggedOutOfAccount + @param error value set if there are xpc errors. + @abstract Removes the current device from the circle. Clears the account object */ bool SOSCCLoggedOutOfAccount(CFErrorRef* error); @@ -578,7 +576,6 @@ SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode action, CFErrorR */ bool SOSCCViewSet(CFSetRef enabledviews, CFSetRef disabledviews); -bool SOSCCViewSetWithAnalytics(CFSetRef enabledviews, CFSetRef disabledviews, CFDataRef parentEvent); /* Security Attributes for PeerInfos diff --git a/keychain/SecureObjectSync/SOSCloudCircle.m b/keychain/SecureObjectSync/SOSCloudCircle.m index a186bb76..98c8dcd5 100644 --- a/keychain/SecureObjectSync/SOSCloudCircle.m +++ b/keychain/SecureObjectSync/SOSCloudCircle.m @@ -84,8 +84,18 @@ static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *ke return value && (xpc_get_type(value) == type); } +static void setSOSDisabledError(CFErrorRef *error) { + SecCFCreateErrorWithFormat(0, kSOSErrorDomain, NULL, error, NULL, CFSTR("SOS Disabled for this platform")); +} + SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return kSOSCCError; + } + SOSCCStatus retval = SOSGetCachedCircleStatus(error); if(retval != kSOSNoCachedValue) { secdebug("circleOps", "Retrieved cached circle value %d", retval); @@ -97,6 +107,12 @@ SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error) SOSCCStatus SOSCCThisDeviceIsInCircleNonCached(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return kSOSCCError; + } + sec_trace_enter_api(NULL); sec_trace_return_api(SOSCCStatus, ^{ SOSCCStatus result = kSOSCCError; @@ -128,20 +144,6 @@ SOSCCStatus SOSCCThisDeviceIsInCircleNonCached(CFErrorRef *error) }, CFSTR("SOSCCStatus=%d")) } -static bool sfsigninanalytics_bool_error_request(enum SecXPCOperation op, CFDataRef parentEvent, CFErrorRef* error) -{ - __block bool result = false; - - secdebug("sosops","enter - operation: %d", op); - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - return SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error); - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - return result; -} - static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error) { __block bool result = false; @@ -237,7 +239,7 @@ static CF_RETURNS_RETAINED CFArrayRef der_array_error_request(enum SecXPCOperati if (securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) { size_t length = 0; const uint8_t* bytes = xpc_dictionary_get_data(response, kSecXPCKeyResult, &length); - der_decode_plist(kCFAllocatorDefault, 0, (CFPropertyListRef*) &result, error, bytes, bytes + length); + der_decode_plist(kCFAllocatorDefault, (CFPropertyListRef*) &result, error, bytes, bytes + length); return result != NULL; })) { @@ -447,24 +449,6 @@ static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef return result; } -static bool info_array_data_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFDataRef parentEvent, CFErrorRef* error) -{ - __block bool result = false; - - secdebug("sosops", "enter - operation: %d", op); - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error); - xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error); - if (encoded_peers) - xpc_dictionary_set_value(message, kSecXPCKeyPeerInfoArray, encoded_peers); - return encoded_peers != NULL; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - return result; -} - static bool uint64_t_to_bool_error_request(enum SecXPCOperation op, uint64_t number, CFErrorRef* error) @@ -534,6 +518,12 @@ static CFDataRef cfdata_error_request_returns_cfdata(enum SecXPCOperation op, CF bool SOSCCRequestToJoinCircle(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_RequestToJoinCircle, error); @@ -542,18 +532,14 @@ bool SOSCCRequestToJoinCircle(CFErrorRef* error) }, NULL) } -bool SOSCCRequestToJoinCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RequestToJoinCircleWithAnalytics, parentEvent, error); - - return sfsigninanalytics_bool_error_request(kSecXPCOpRequestToJoinWithAnalytics, parentEvent, error); - }, NULL) -} - bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_RequestToJoinCircleAfterRestore, error); @@ -562,18 +548,14 @@ bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error) }, NULL) } -bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics(CFDataRef parentEvent, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RequestToJoinCircleAfterRestoreWithAnalytics, parentEvent, error); - - return sfsigninanalytics_bool_error_request(kSecXPCOpRequestToJoinAfterRestoreWithAnalytics, parentEvent, error); - }, NULL) -} - bool SOSCCAccountHasPublicKey(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_AccountHasPublicKey, error); @@ -583,18 +565,14 @@ bool SOSCCAccountHasPublicKey(CFErrorRef *error) } -bool SOSCCWaitForInitialSyncWithAnalytics(CFDataRef parentEvent, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_WaitForInitialSyncWithAnalytics, parentEvent, error); - - return sfsigninanalytics_bool_error_request(kSecXPCOpWaitForInitialSyncWithAnalytics, parentEvent, error); - }, NULL) -} - bool SOSCCWaitForInitialSync(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_WaitForInitialSync, error); @@ -605,6 +583,12 @@ bool SOSCCWaitForInitialSync(CFErrorRef* error) bool SOSCCAccountSetToNew(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secwarning("SOSCCAccountSetToNew called"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -615,6 +599,12 @@ bool SOSCCAccountSetToNew(CFErrorRef *error) bool SOSCCResetToOffering(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secwarning("SOSCCResetToOffering called"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -626,6 +616,12 @@ bool SOSCCResetToOffering(CFErrorRef* error) bool SOSCCResetToEmpty(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secwarning("SOSCCResetToEmpty called"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -635,18 +631,14 @@ bool SOSCCResetToEmpty(CFErrorRef* error) }, NULL) } -bool SOSCCResetToEmptyWithAnalytics(CFDataRef parentEvent, CFErrorRef* error) -{ - secwarning("SOSCCResetToEmptyWithAnalytics called"); - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_ResetToEmptyWithAnalytics, parentEvent, error); - - return sfsigninanalytics_bool_error_request(kSecXPCOpResetToEmptyWithAnalytics, parentEvent, error); - }, NULL) -} bool SOSCCRemovePeersFromCircle(CFArrayRef peers, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_RemovePeersFromCircle, peers, error); @@ -655,38 +647,39 @@ bool SOSCCRemovePeersFromCircle(CFArrayRef peers, CFErrorRef* error) }, NULL) } -bool SOSCCRemovePeersFromCircleWithAnalytics(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error) +bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error) { - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RemovePeersFromCircleWithAnalytics, peers, parentEvent, error); - - return info_array_data_to_bool_error_request(kSecXPCOpRemovePeersFromCircleWithAnalytics, peers, parentEvent, error); - }, NULL) -} + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } -bool SOSCCRemoveThisDeviceFromCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error) -{ sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ - do_if_registered(soscc_RemoveThisDeviceFromCircleWithAnalytics, parentEvent, error); - - return sfsigninanalytics_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics, parentEvent, error); + do_if_registered(soscc_RemoveThisDeviceFromCircle, error); + + return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error); }, NULL) } -bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error) -{ +bool SOSCCLoggedIntoAccount(CFErrorRef* error) { sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ - do_if_registered(soscc_RemoveThisDeviceFromCircle, error); - - return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error); + do_if_registered(soscc_LoggedIntoAccount, error); + + return simple_bool_error_request(kSecXPCOpLoggedIntoAccount, error); }, NULL) } bool SOSCCLoggedOutOfAccount(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_LoggedOutOfAccount, error); @@ -697,6 +690,12 @@ bool SOSCCLoggedOutOfAccount(CFErrorRef* error) bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_BailFromCircle, limit_in_seconds, error); @@ -707,6 +706,12 @@ bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyPeerInfo, error); @@ -717,6 +722,12 @@ CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyConcurringPeerInfo, error); @@ -727,6 +738,12 @@ CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyGenerationPeerInfo, error); @@ -737,6 +754,12 @@ CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyApplicantPeerInfo, error); @@ -746,6 +769,12 @@ CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error) } bool SOSCCValidateUserPublic(CFErrorRef* error){ + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_api(bool, ^{ do_if_registered(soscc_ValidateUserPublic, error); @@ -756,6 +785,12 @@ bool SOSCCValidateUserPublic(CFErrorRef* error){ CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyValidPeerPeerInfo, error); @@ -766,6 +801,12 @@ CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyNotValidPeerPeerInfo, error); @@ -776,7 +817,13 @@ CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error) { - sec_trace_enter_api(NULL); + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyRetirementPeerInfo, error); @@ -786,6 +833,12 @@ CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error) CFArrayRef SOSCCCopyViewUnawarePeerInfo(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyViewUnawarePeerInfo, error); @@ -796,6 +849,12 @@ CFArrayRef SOSCCCopyViewUnawarePeerInfo(CFErrorRef* error) SOSPeerInfoRef SOSCCCopyMyPeerInfo(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(SOSPeerInfoRef, ^{ do_if_registered(soscc_CopyMyPeerInfo, error); @@ -806,6 +865,12 @@ SOSPeerInfoRef SOSCCCopyMyPeerInfo(CFErrorRef *error) static CFArrayRef SOSCCCopyEngineState(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFArrayRef, ^{ do_if_registered(soscc_CopyEngineState, error); @@ -821,6 +886,11 @@ CFStringRef kSOSCCEngineStateCoderKey = CFSTR("CoderDump"); CFStringRef kSOSCCEngineStateManifestHashKey = CFSTR("ManifestHash"); void SOSCCForEachEngineStateAsStringFromArray(CFArrayRef states, void (^block)(CFStringRef oneStateString)) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return; + } + CFArrayForEach(states, ^(const void *value) { CFDictionaryRef dict = asDictionary(value, NULL); @@ -868,6 +938,12 @@ void SOSCCForEachEngineStateAsStringFromArray(CFArrayRef states, void (^block)(C } bool SOSCCForEachEngineStateAsString(CFErrorRef* error, void (^block)(CFStringRef oneStateString)) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + CFArrayRef states = SOSCCCopyEngineState(error); if (states == NULL) return false; @@ -882,6 +958,12 @@ bool SOSCCForEachEngineStateAsString(CFErrorRef* error, void (^block)(CFStringRe bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_AcceptApplicants, applicants, error); @@ -892,7 +974,13 @@ bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error) bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error) { - sec_trace_enter_api(CFSTR("applicants=%@"), applicants); + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + + sec_trace_enter_api(CFSTR("applicants=%@"), applicants); sec_trace_return_bool_api(^{ do_if_registered(soscc_RejectApplicants, applicants, error); @@ -911,6 +999,12 @@ static CF_RETURNS_RETAINED SOSPeerInfoRef SOSSetNewPublicBackupKey(CFDataRef pub } SOSPeerInfoRef SOSCCCopyMyPeerWithNewDeviceRecoverySecret(CFDataRef secret, CFErrorRef *error){ + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + secnotice("devRecovery", "Enter SOSCCCopyMyPeerWithNewDeviceRecoverySecret()"); CFDataRef publicKeyData = SOSCopyDeviceBackupPublicKey(secret, error); secnotice("devRecovery", "SOSCopyDeviceBackupPublicKey (%@)", publicKeyData); @@ -921,6 +1015,12 @@ SOSPeerInfoRef SOSCCCopyMyPeerWithNewDeviceRecoverySecret(CFDataRef secret, CFEr } bool SOSCCRegisterSingleRecoverySecret(CFDataRef aks_bag, bool forV0Only, CFErrorRef *error){ + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_RegisterSingleRecoverySecret, aks_bag, forV0Only, error); @@ -930,7 +1030,13 @@ bool SOSCCRegisterSingleRecoverySecret(CFDataRef aks_bag, bool forV0Only, CFErro bool SOSCCRegisterRecoveryPublicKey(CFDataRef recovery_key, CFErrorRef *error){ - sec_trace_enter_api(NULL); + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ bool retval = false; do_if_registered(soscc_RegisterRecoveryPublicKey, recovery_key, error); @@ -941,6 +1047,12 @@ bool SOSCCRegisterRecoveryPublicKey(CFDataRef recovery_key, CFErrorRef *error){ } CFDataRef SOSCCCopyRecoveryPublicKey(CFErrorRef *error){ + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFDataRef, ^{ do_if_registered(soscc_CopyRecoveryPublicKey, error); @@ -969,7 +1081,7 @@ static bool label_and_password_to_bool_error_request(enum SecXPCOperation op, static bool label_and_password_and_dsid_to_bool_error_request(enum SecXPCOperation op, CFStringRef user_label, CFDataRef user_password, - CFStringRef dsid, CFDataRef parentEvent, CFErrorRef* error) + CFStringRef dsid, CFErrorRef* error) { __block bool result = false; @@ -981,9 +1093,6 @@ static bool label_and_password_and_dsid_to_bool_error_request(enum SecXPCOperati xpc_dictionary_set_string(message, kSecXPCKeyDSID, utr8StrDSID); }); xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password)); - if(parentEvent){ - SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error); - } return true; }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); @@ -995,12 +1104,24 @@ static bool label_and_password_and_dsid_to_bool_error_request(enum SecXPCOperati bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) { - secnotice("circleOps", "SOSCCRegisterUserCredentials - calling SOSCCSetUserCredentials for %@\n", user_label); + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + + secnotice("circleOps", "SOSCCRegisterUserCredentials - calling SOSCCSetUserCredentials for %@\n", user_label); return SOSCCSetUserCredentials(user_label, user_password, error); } bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("circleOps", "SOSCCSetUserCredentials for %@\n", user_label); sec_trace_enter_api(CFSTR("user_label=%@"), user_label); sec_trace_return_bool_api(^{ @@ -1012,6 +1133,12 @@ bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CF bool SOSCCSetUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("circleOps", "SOSCCSetUserCredentialsAndDSID for %@\n", user_label); sec_trace_enter_api(CFSTR("user_label=%@"), user_label); sec_trace_return_bool_api(^{ @@ -1026,30 +1153,7 @@ bool SOSCCSetUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_passw if(account_dsid == NULL){ account_dsid = CFSTR(""); } - return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSID, user_label, user_password, account_dsid, nil, error); - out: - return result; - - }, NULL) -} - -bool SOSCCSetUserCredentialsAndDSIDWithAnalytics(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error) -{ - secnotice("circleOps", "SOSCCSetUserCredentialsAndDSIDWithAnalytics for %@\n", user_label); - sec_trace_enter_api(CFSTR("user_label=%@"), user_label); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_SetUserCredentialsAndDSIDWithAnalytics, user_label, user_password, dsid, parentEvent, error); - - bool result = false; - __block CFStringRef account_dsid = dsid; - - require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil"))); - require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil"))); - - if(account_dsid == NULL){ - account_dsid = CFSTR(""); - } - return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics, user_label, user_password, account_dsid, parentEvent, error); + return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpSetUserCredentialsAndDSID, user_label, user_password, account_dsid, error); out: return result; @@ -1070,7 +1174,7 @@ static bool SOSCCTryUserCredentialsAndDSID_internal(CFStringRef user_label, CFDa account_dsid = CFSTR(""); } - return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, account_dsid, nil, error); + return label_and_password_and_dsid_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, account_dsid, error); out: return result; @@ -1080,6 +1184,12 @@ static bool SOSCCTryUserCredentialsAndDSID_internal(CFStringRef user_label, CFDa bool SOSCCTryUserCredentialsAndDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("sosops", "SOSCCTryUserCredentialsAndDSID!! %@\n", user_label); require_action_quiet(user_label, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_label is nil"))); require_action_quiet(user_password, out, SOSErrorCreate(kSOSErrorParam, error, NULL, CFSTR("user_password is nil"))); @@ -1090,11 +1200,23 @@ out: } bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + return SOSCCTryUserCredentialsAndDSID_internal(user_label, user_password, NULL, error); } bool SOSCCCanAuthenticate(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_CanAuthenticate, error); @@ -1104,6 +1226,12 @@ bool SOSCCCanAuthenticate(CFErrorRef* error) { } bool SOSCCPurgeUserCredentials(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ do_if_registered(soscc_PurgeUserCredentials, error); @@ -1113,6 +1241,12 @@ bool SOSCCPurgeUserCredentials(CFErrorRef* error) { } enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return kSOSDepartureReasonError; + } + sec_trace_enter_api(NULL); sec_trace_return_api(enum DepartureReason, ^{ do_if_registered(soscc_GetLastDepartureReason, error); @@ -1122,6 +1256,12 @@ enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) { } bool SOSCCSetLastDepartureReason(enum DepartureReason reason, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_enter_api(NULL); sec_trace_return_api(bool, ^{ do_if_registered(soscc_SetLastDepartureReason, reason, error); @@ -1138,6 +1278,12 @@ bool SOSCCSetLastDepartureReason(enum DepartureReason reason, CFErrorRef *error) } bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error){ + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("updates", "enter SOSCCProcessEnsurePeerRegistration"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -1150,6 +1296,12 @@ bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error){ CFSetRef /* CFString */ SOSCCProcessSyncWithPeers(CFSetRef peers, CFSetRef backupPeers, CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + sec_trace_enter_api(NULL); sec_trace_return_api(CFSetRef, ^{ do_if_registered(soscc_ProcessSyncWithPeers, peers, backupPeers, error); @@ -1161,6 +1313,12 @@ CFSetRef /* CFString */ SOSCCProcessSyncWithPeers(CFSetRef peers, CFSetRef backu SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return kSyncWithAllPeersOtherFail; + } + sec_trace_enter_api(NULL); sec_trace_return_api(SyncWithAllPeersReason, ^{ do_if_registered(soscc_ProcessSyncWithAllPeers, error); @@ -1228,6 +1386,12 @@ static int64_t name_action_to_code_request(enum SecXPCOperation op, uint16_t err } SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode actionCode, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return kSOSCCGeneralViewError; + } + if(actionCode == kSOSCCViewQuery) { uint64_t circleStat = SOSGetCachedCircleBitmask(); if(circleStat & CC_STATISVALID) { @@ -1254,6 +1418,11 @@ SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode actionCode, CFEr bool SOSCCViewSet(CFSetRef enabledViews, CFSetRef disabledViews) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFErrorRef *error = NULL; __block bool result = false; @@ -1273,27 +1442,6 @@ bool SOSCCViewSet(CFSetRef enabledViews, CFSetRef disabledViews) { }, NULL) } -bool SOSCCViewSetWithAnalytics(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent) { - CFErrorRef *error = NULL; - __block bool result = false; - - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_ViewSetWithAnalytics, enabledViews, disabledViews, parentEvent); - return securityd_send_sync_and_do(kSecXPCOpViewSetWithAnalytics, error, ^bool(xpc_object_t message, CFErrorRef *error) { - xpc_object_t enabledSetXpc = CreateXPCObjectWithCFSetRef(enabledViews, error); - xpc_object_t disabledSetXpc = CreateXPCObjectWithCFSetRef(disabledViews, error); - if (enabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyEnabledViewsKey, enabledSetXpc); - if (disabledSetXpc) xpc_dictionary_set_value(message, kSecXPCKeyDisabledViewsKey, disabledSetXpc); - if(parentEvent) SecXPCDictionarySetData(message, kSecXPCKeySignInAnalytics, parentEvent, error); - return (enabledSetXpc != NULL) || (disabledSetXpc != NULL) ; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - }, NULL) -} - static CFStringRef copyViewNames(size_t n, CFStringRef *views) { CFMutableStringRef retval = CFStringCreateMutable(kCFAllocatorDefault, 0); CFStringAppend(retval, CFSTR("|")); @@ -1354,36 +1502,72 @@ static bool sosIsViewSetSyncing(size_t n, CFStringRef *views) { } bool SOSCCIsIcloudKeychainSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; // should we lie since CKKS is syncing - or forward? + } + CFStringRef views[] = { kSOSViewWiFi, kSOSViewAutofillPasswords, kSOSViewSafariCreditCards, kSOSViewOtherSyncable }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } bool SOSCCIsSafariSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFStringRef views[] = { kSOSViewAutofillPasswords, kSOSViewSafariCreditCards }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } bool SOSCCIsAppleTVSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFStringRef views[] = { kSOSViewAppleTV }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } bool SOSCCIsHomeKitSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFStringRef views[] = { kSOSViewHomeKit }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } bool SOSCCIsWiFiSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFStringRef views[] = { kSOSViewWiFi }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } bool SOSCCIsContinuityUnlockSyncing(void) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + return false; + } + CFStringRef views[] = { kSOSViewContinuityUnlock }; return sosIsViewSetSyncing(sizeof(views)/sizeof(views[0]), views); } SOSPeerInfoRef SOSCCCopyApplication(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + secnotice("hsa2PB", "enter SOSCCCopyApplication applicant"); sec_trace_enter_api(NULL); @@ -1394,6 +1578,12 @@ SOSPeerInfoRef SOSCCCopyApplication(CFErrorRef *error) { } bool SOSCCCleanupKVSKeys(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("cleanup-keys", "enter SOSCCCleanupKVSKeys"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -1406,6 +1596,12 @@ bool SOSCCCleanupKVSKeys(CFErrorRef *error) { } CFDataRef SOSCCCopyCircleJoiningBlob(SOSPeerInfoRef applicant, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + secnotice("hsa2PB", "enter SOSCCCopyCircleJoiningBlob approver"); sec_trace_enter_api(NULL); @@ -1420,6 +1616,12 @@ CFDataRef SOSCCCopyCircleJoiningBlob(SOSPeerInfoRef applicant, CFErrorRef *error } CFDataRef SOSCCCopyInitialSyncData(SOSInitialSyncFlags flags, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return NULL; + } + secnotice("circleJoin", "enter SOSCCCopyInitialSyncData approver"); sec_trace_enter_api(NULL); @@ -1430,6 +1632,12 @@ CFDataRef SOSCCCopyInitialSyncData(SOSInitialSyncFlags flags, CFErrorRef *error) } bool SOSCCJoinWithCircleJoiningBlob(CFDataRef joiningBlob, PiggyBackProtocolVersion version, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("hsa2PB", "enter SOSCCJoinWithCircleJoiningBlob applicant"); sec_trace_enter_api(NULL); sec_trace_return_bool_api(^{ @@ -1440,6 +1648,12 @@ bool SOSCCJoinWithCircleJoiningBlob(CFDataRef joiningBlob, PiggyBackProtocolVers } CFBooleanRef SOSCCPeersHaveViewsEnabled(CFArrayRef viewNames, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return FALSE; + } + secnotice("view-enabled", "enter SOSCCPeersHaveViewsEnabled"); sec_trace_enter_api(NULL); sec_trace_return_api(CFBooleanRef, ^{ @@ -1450,6 +1664,12 @@ CFBooleanRef SOSCCPeersHaveViewsEnabled(CFArrayRef viewNames, CFErrorRef *error) } bool SOSCCMessageFromPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + secnotice("pending-check", "enter SOSCCMessageFromPeerIsPending"); sec_trace_return_bool_api(^{ @@ -1461,6 +1681,12 @@ bool SOSCCMessageFromPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) { } bool SOSCCSendToPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return false; + } + sec_trace_return_bool_api(^{ do_if_registered(soscc_SOSCCSendToPeerIsPending, peer, error); @@ -1505,6 +1731,12 @@ bool SOSCCSendToPeerIsPending(SOSPeerInfoRef peer, CFErrorRef *error) { static id SOSCCGetStatusObject(CFErrorRef *error) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(error); + return nil; + } + if (gSecurityd && gSecurityd->soscc_status) return (__bridge id)gSecurityd->soscc_status(); @@ -1519,6 +1751,11 @@ SOSCCGetStatusObject(CFErrorRef *error) static id SOSCCGetSynchronousStatusObject(CFErrorRef *cferror) { + IF_SOS_DISABLED { + secdebug("circleOps", "SOS disabled for this platform"); + setSOSDisabledError(cferror); + return nil; + } if (gSecurityd && gSecurityd->soscc_status) return (__bridge id)gSecurityd->soscc_status(); diff --git a/keychain/SecureObjectSync/SOSCloudCircleInternal.h b/keychain/SecureObjectSync/SOSCloudCircleInternal.h index b174896f..9fd07e97 100644 --- a/keychain/SecureObjectSync/SOSCloudCircleInternal.h +++ b/keychain/SecureObjectSync/SOSCloudCircleInternal.h @@ -31,6 +31,24 @@ #include #include +#if TARGET_OS_TV +#define SOS_AVAILABLE false +#elif TARGET_OS_WATCH +#define SOS_AVAILABLE false +#elif TARGET_OS_BRIDGE +#define SOS_AVAILABLE false +#elif TARGET_OS_IOS +#define SOS_AVAILABLE true +#elif TARGET_OS_OSX +#define SOS_AVAILABLE true +#elif TARGET_OS_SIMULATOR +#define SOS_AVAILABLE true +#else +#define SOS_AVAILABLE false +#endif + +#define IF_SOS_DISABLED if(!SOS_AVAILABLE) + __BEGIN_DECLS // Use the kSecAttrViewHint* constants in SecItemPriv.h instead diff --git a/keychain/SecureObjectSync/SOSCoder.c b/keychain/SecureObjectSync/SOSCoder.c index 109cffae..4172edb3 100644 --- a/keychain/SecureObjectSync/SOSCoder.c +++ b/keychain/SecureObjectSync/SOSCoder.c @@ -48,7 +48,6 @@ #include #include -#include #include "AssertMacros.h" @@ -274,7 +273,7 @@ SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) { switch (SOSCoderGetExportedVersion(der, der_end)) { case kCoderAsOTRDataOnly: - der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, der_end); + der = der_decode_data(kCFAllocatorDefault, &otr_data, error, der, der_end); p->waitingForDataPacket = false; break; @@ -285,10 +284,10 @@ SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) { require_action_quiet(sequence_end == der_end, fail, SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Extra data in SOS coder"), NULL, error)); - der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &otr_data, error, der, sequence_end); der = ccder_decode_bool(&p->waitingForDataPacket, der, sequence_end); if (der != sequence_end) { // optionally a pending response - der = der_decode_data(kCFAllocatorDefault, 0, &p->pendingResponse, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &p->pendingResponse, error, der, sequence_end); } } break; @@ -307,12 +306,12 @@ SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) { goto fail; } - der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &otr_data, error, der, sequence_end); der = ccder_decode_bool(&p->waitingForDataPacket, der, sequence_end); der = ccder_decode_bool(&p->lastReceivedWasOld, der, sequence_end); - der = der_decode_data(kCFAllocatorDefault, 0, &p->hashOfLastReceived, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &p->hashOfLastReceived, error, der, sequence_end); if (der != sequence_end) { // optionally a pending response - der = der_decode_data(kCFAllocatorDefault, 0, &p->pendingResponse, error, der, sequence_end); + der = der_decode_data(kCFAllocatorDefault, &p->pendingResponse, error, der, sequence_end); } } break; @@ -356,7 +355,7 @@ SOSCoderRef SOSCoderCreate(SOSPeerInfoRef peerInfo, SOSFullPeerInfoRef myPeerInf privateKey = SOSFullPeerInfoCopyDeviceKey(myPeerInfo, &localError); require_quiet(privateKey, errOut); - myRef = SecOTRFullIdentityCreateFromSecKeyRef(allocator, privateKey, &localError); + myRef = SecOTRFullIdentityCreateFromSecKeyRefSOS(allocator, privateKey, &localError); require_quiet(myRef, errOut); CFReleaseNull(privateKey); @@ -566,7 +565,6 @@ SOSCoderStatus SOSCoderUnwrap(SOSCoderRef coder, CFDataRef codedMessage, CFMutab case errSecDecode: CFStringAppend(action, CFSTR("resending dh")); result = SOSCoderResendDH(coder, error); - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.restartotrnegotiation"), 1); break; default: SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot negotiate session (%ld)"), clientId, (long)ppstatus); @@ -592,7 +590,6 @@ SOSCoderStatus SOSCoderUnwrap(SOSCoderRef coder, CFDataRef codedMessage, CFMutab if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) { CFStringAppend(action, CFSTR("not ready for data; resending DH packet")); - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.restartotrnegotiation"), 1); result = SOSCoderResendDH(coder, error); } else { if (coder->waitingForDataPacket) { diff --git a/keychain/SecureObjectSync/SOSControlHelper.m b/keychain/SecureObjectSync/SOSControlHelper.m index d700b69e..a8296b90 100644 --- a/keychain/SecureObjectSync/SOSControlHelper.m +++ b/keychain/SecureObjectSync/SOSControlHelper.m @@ -24,6 +24,8 @@ #import #import #import +#import +#include #import "keychain/SecureObjectSync/SOSTypes.h" #import "keychain/SecureObjectSync/SOSControlHelper.h" @@ -31,40 +33,37 @@ void _SOSControlSetupInterface(NSXPCInterface *interface) { - static NSMutableSet *errClasses; + NSSet *errClasses = [SecXPCHelper safeErrorClasses]; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - errClasses = [NSMutableSet set]; + @try { + [interface setClasses:errClasses forSelector:@selector(userPublicKey:) argumentIndex:2 ofReply:YES]; - char *classes[] = { - "NSURL", - "NSURLError", - "NSError" - }; + [interface setClasses:errClasses forSelector:@selector(stashedCredentialPublicKey:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(assertStashedAccountCredential:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(validatedStashedAccountCredential:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(stashAccountCredential:complete:) argumentIndex:1 ofReply:YES]; - for (unsigned n = 0; n < sizeof(classes)/sizeof(classes[0]); n++) { - Class cls = objc_getClass(classes[n]); - if (cls) - [errClasses addObject:cls]; - } - }); + [interface setClasses:errClasses forSelector:@selector(ghostBust:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(ghostBustPeriodic:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(ghostBustTriggerTimed:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(ghostBustInfo:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(userPublicKey:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(iCloudIdentityStatus:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(stashedCredentialPublicKey:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(assertStashedAccountCredential:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(stashAccountCredential:complete:) argumentIndex:1 ofReply:YES]; - - [interface setClasses:errClasses forSelector:@selector(myPeerInfo:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(circleHash:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(circleJoiningBlob:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(joinCircleWithBlob:version:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(initialSyncCredentials:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(importInitialSyncCredentials:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(triggerSync:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(getWatchdogParameters:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(setWatchdogParmeters:complete:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(ghostBust:complete:) argumentIndex:1 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(triggerBackup:complete:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(myPeerInfo:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(circleHash:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(circleJoiningBlob:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(joinCircleWithBlob:version:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(initialSyncCredentials:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(importInitialSyncCredentials:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcTriggerSync:complete:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(getWatchdogParameters:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(setWatchdogParmeters:complete:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcTriggerBackup:complete:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcTriggerRingUpdate:) argumentIndex:0 ofReply:YES]; + } + @catch(NSException* e) { + secerror("Could not configure SOSControlHelper: %@", e); + @throw e; + } } diff --git a/keychain/SecureObjectSync/SOSControlServer.m b/keychain/SecureObjectSync/SOSControlServer.m index 46332efa..38bfa056 100644 --- a/keychain/SecureObjectSync/SOSControlServer.m +++ b/keychain/SecureObjectSync/SOSControlServer.m @@ -149,14 +149,9 @@ [self.account importInitialSyncCredentials:items complete:complete]; } -- (void)triggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete +- (void)rpcTriggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete { - if (![self checkEntitlement:(__bridge NSString *)kSecEntitlementKeychainCloudCircle]) { - complete(false, [NSError errorWithDomain:(__bridge NSString *)kSOSErrorDomain code:kSOSEntitlementMissing userInfo:NULL]); - return; - } - - [self.account triggerSync:peers complete:complete]; + [self.account rpcTriggerSync:peers complete:complete]; } - (void)getWatchdogParameters:(void (^)(NSDictionary* parameters, NSError* error))complete @@ -185,9 +180,21 @@ [self.account ghostBustInfo:complete]; } -- (void)triggerBackup:(NSArray* _Nullable)backupPeers complete:(void (^)(NSError *error))complete +- (void)iCloudIdentityStatus: (void (^)(NSData *json, NSError *error))complete { + [self.account iCloudIdentityStatus: complete]; +} + +- (void)rpcTriggerBackup:(NSArray* _Nullable)backupPeers complete:(void (^)(NSError *error))complete { - [self.account triggerBackup:backupPeers complete:complete]; + [self.account rpcTriggerBackup:backupPeers complete:complete]; +} + +- (void)rpcTriggerRingUpdate:(void (^)(NSError *))complete { + [self.account rpcTriggerRingUpdate:complete]; +} + +- (void)iCloudIdentityStatus_internal:(void (^)(NSDictionary *, NSError *))complete { + [self.account iCloudIdentityStatus_internal:complete]; } @@ -197,8 +204,7 @@ - (instancetype)initSOSConnectionWithConnection:(NSXPCConnection *)connection account:(SOSAccount *)account { - self = [super initSOSClientWithAccount:account]; - if (self) { + if ((self = [super initSOSClientWithAccount:account])) { self.connection = connection; } return self; diff --git a/keychain/SecureObjectSync/SOSECWrapUnwrap.c b/keychain/SecureObjectSync/SOSECWrapUnwrap.c index 7aea444d..f013cb8e 100644 --- a/keychain/SecureObjectSync/SOSECWrapUnwrap.c +++ b/keychain/SecureObjectSync/SOSECWrapUnwrap.c @@ -9,11 +9,11 @@ #include -#include #include #include #include -#include +#import +#import #if 0 && defined(CCEC_RFC6637_DEBUG_KEYS) @@ -46,7 +46,7 @@ SOSCopyECWrappedData(ccec_pub_ctx_t ec_ctx, CFDataRef data, CFErrorRef *error) res = ccec_rfc6637_wrap_key(ec_ctx, CFDataGetMutableBytePtr(output), CCEC_RFC6637_COMPACT_KEYS | DEBUGKEYS, kAlgorithmID, CFDataGetLength(data), CFDataGetBytePtr(data), &ccec_rfc6637_dh_curve_p256, &ccec_rfc6637_wrap_sha256_kek_aes128, (const uint8_t *)fingerprint, - ccDevRandomGetRngState()); + ccrng(NULL)); require_noerr_action(res, exit, SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("Wrap failed with %d"), res)); CFTransferRetained(result, output); diff --git a/keychain/SecureObjectSync/SOSEngine.c b/keychain/SecureObjectSync/SOSEngine.c index f2a4a9db..d644bee0 100644 --- a/keychain/SecureObjectSync/SOSEngine.c +++ b/keychain/SecureObjectSync/SOSEngine.c @@ -50,9 +50,8 @@ #include #include #include -#include #include - +#include "utilities/SecCoreAnalytics.h" #include #include @@ -332,6 +331,19 @@ static void SOSEngineForEachBackupPeer_locked(SOSEngineRef engine, void (^with)( CFRelease(peerMapCopy); } +static void SOSEngineForBackupPeer_locked(SOSEngineRef engine, CFStringRef backupPeerID, void (^with)(SOSPeerRef peer)) { + struct SOSEngineWithPeerContext ewp = { .engine = engine, .with = with }; + CFMutableDictionaryRef singleEntryMap = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryRef peerMapCopy = CFDictionaryCreateCopy(NULL, engine->peerMap); + SOSPeerRef peer = (SOSPeerRef)CFDictionaryGetValue(peerMapCopy, backupPeerID); + if(peer != NULL) { + CFDictionaryAddValue(singleEntryMap, backupPeerID, peer); + CFDictionaryApplyFunction(singleEntryMap, SOSEngineWithBackupPeerMapEntry_locked, &ewp); + } + CFRelease(peerMapCopy); + CFRelease(singleEntryMap); +} + // // Manifest cache // @@ -706,7 +718,7 @@ CFMutableDictionaryRef derStateToDictionaryCopy(CFDataRef state, CFErrorRef *err if (state) { const uint8_t *der = CFDataGetBytePtr(state); const uint8_t *der_end = der + CFDataGetLength(state); - ok = der = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *)&stateDict, error, der, der_end); + ok = der = der_decode_dictionary(kCFAllocatorDefault, (CFDictionaryRef *)&stateDict, error, der, der_end); if (der && der != der_end) { ok = SOSErrorCreate(kSOSErrorDecodeFailure, error, NULL, CFSTR("trailing %td bytes at end of state"), der_end - der); } @@ -773,7 +785,7 @@ static bool SOSEngineLoadCoders(SOSEngineRef engine, SOSTransactionRef txn, CFEr secnotice("coder", "Will force peer registration: %s",needPeerRegistration ? "yes" : "no"); if (needPeerRegistration) { - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_queue_t queue = dispatch_get_global_queue(SOS_ENGINE_PRIORITY, 0); dispatch_async(queue, ^{ CFErrorRef eprError = NULL; @@ -1202,22 +1214,12 @@ static bool SOSEngineUpdateChanges_locked(SOSEngineRef engine, SOSTransactionRef if (deleted) { bool someoneCares = SOSChangeMapperIngestChange(&cm, false, deleted); if (someoneCares) { -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.delete"), 1); -#endif mappedItemChanged = true; } } if (inserted) { bool someoneCares = SOSChangeMapperIngestChange(&cm, true, inserted); if (someoneCares) { -#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - if (deleted == NULL) { - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.add"), 1); - } else { - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.update"), 1); - } -#endif mappedItemChanged = true; } if (!someoneCares && !isData(inserted) && SecDbItemIsTombstone((SecDbItemRef)inserted) && !CFEqualSafe(SecDbItemGetValue((SecDbItemRef)inserted, &v7utomb, NULL), kCFBooleanTrue)) { @@ -1748,6 +1750,12 @@ static void SOSEngineForEachBackupPeer(SOSEngineRef engine, void (^with)(SOSPeer }); } +static void SOSEngineForBackupPeer(SOSEngineRef engine, CFStringRef backupPeerID, void (^with)(SOSPeerRef peer)) { + SOSEngineDoOnQueue(engine, ^{ + SOSEngineForBackupPeer_locked(engine, backupPeerID, with); + }); +} + static const CFStringRef kSecADSecurityNewItemSyncTimeKey = CFSTR("com.apple.security.secureobjectsync.itemtime.new"); static const CFStringRef kSecADSecurityKnownItemSyncTimeKey = CFSTR("com.apple.security.secureobjectsync.itemtime.known"); @@ -1764,8 +1772,8 @@ static void ReportItemSyncTime(SOSDataSourceRef ds, bool known, SOSObjectRef obj syncTime = now - peerModificationAbsoluteTime; } - SecADClientPushValueForDistributionKey(known ? kSecADSecurityKnownItemSyncTimeKey : kSecADSecurityNewItemSyncTimeKey, - SecBucket2Significant(syncTime)); + SecCoreAnalyticsSendValue(known ? kSecADSecurityKnownItemSyncTimeKey : kSecADSecurityNewItemSyncTimeKey, + SecBucket2Significant(syncTime)); } CFReleaseNull(itemModDate); } @@ -2772,6 +2780,14 @@ CFArrayRef SOSEngineCopyBackupPeerNames(SOSEngineRef engine, CFErrorRef *error) return backupNames; } +CFStringRef SOSEngineEnsureCopyBackupPeerForView(SOSEngineRef engine, CFStringRef backupPeerID, CFErrorRef *error) { + __block CFStringRef backupName = CFSTR(""); + SOSEngineForBackupPeer(engine, backupPeerID, ^(SOSPeerRef peer) { + backupName = CFRetainSafe(SOSPeerGetID(peer)); + }); + return backupName; +} + static CFMutableDictionaryRef SOSEngineCreateStateDictionary(CFStringRef peerID, SOSManifestRef manifest, CFSetRef vns, CFStringRef coderString) { CFNumberRef manifestCount = CFNumberCreateWithCFIndex(kCFAllocatorDefault, SOSManifestGetCount(manifest)); CFDataRef manifestHash = SOSManifestGetDigest(manifest, NULL); diff --git a/keychain/SecureObjectSync/SOSEngine.h b/keychain/SecureObjectSync/SOSEngine.h index ea598b8b..0e508d17 100644 --- a/keychain/SecureObjectSync/SOSEngine.h +++ b/keychain/SecureObjectSync/SOSEngine.h @@ -135,6 +135,7 @@ bool SOSEnginePeerDidConnect(SOSEngineRef engine, CFStringRef peerID, CFErrorRef bool SOSEngineSetPeerConfirmedManifest(SOSEngineRef engine, CFStringRef backupName, CFDataRef keybagDigest, CFDataRef manifestData, CFErrorRef *error); CFArrayRef SOSEngineCopyBackupPeerNames(SOSEngineRef engine, CFErrorRef *error); +CFStringRef SOSEngineEnsureCopyBackupPeerForView(SOSEngineRef engine, CFStringRef backupPeerID, CFErrorRef *error); void logRawMessage(CFDataRef message, bool sending, uint64_t seqno); diff --git a/keychain/SecureObjectSync/SOSExports.exp-in b/keychain/SecureObjectSync/SOSExports.exp-in index 4417dd34..fe277148 100644 --- a/keychain/SecureObjectSync/SOSExports.exp-in +++ b/keychain/SecureObjectSync/SOSExports.exp-in @@ -39,6 +39,7 @@ _SOSCCIsIcloudKeychainSyncing _SOSCCIsSafariSyncing _SOSCCIsWiFiSyncing _SOSCCJoinWithCircleJoiningBlob +_SOSCCLoggedIntoAccount _SOSCCLoggedOutOfAccount _SOSCCMessageFromPeerIsPending _SOSCCPeersHaveViewsEnabled @@ -51,21 +52,15 @@ _SOSCCRegisterSingleRecoverySecret _SOSCCRegisterUserCredentials _SOSCCRejectApplicants _SOSCCRemovePeersFromCircle -_SOSCCRemovePeersFromCircleWithAnalytics _SOSCCRemoveThisDeviceFromCircle -_SOSCCRemoveThisDeviceFromCircleWithAnalytics _SOSCCRequestToJoinCircle -_SOSCCRequestToJoinCircleWithAnalytics _SOSCCRequestToJoinCircleAfterRestore -_SOSCCRequestToJoinCircleAfterRestoreWithAnalytics _SOSCCResetToEmpty -_SOSCCResetToEmptyWithAnalytics _SOSCCResetToOffering _SOSCCSendToPeerIsPending _SOSCCSetLastDepartureReason _SOSCCSetUserCredentials _SOSCCSetUserCredentialsAndDSID -_SOSCCSetUserCredentialsAndDSIDWithAnalytics _SOSCCThisDeviceIsInCircle _SOSCCThisDeviceIsInCircleNonCached _SOSCCTryUserCredentials @@ -73,9 +68,7 @@ _SOSCCTryUserCredentialsAndDSID _SOSCCValidateUserPublic _SOSCCView _SOSCCViewSet -_SOSCCViewSetWithAnalytics _SOSCCWaitForInitialSync -_SOSCCWaitForInitialSyncWithAnalytics _SOSCCCopyInitialSyncData _kSOSCCEngineStateCoderKey @@ -141,6 +134,7 @@ _SOSPeerInfoGetClass _SOSPeerInfoGetDEREncodedSize _SOSPeerInfoGetPeerDeviceType _SOSPeerInfoGetPeerID +_SOSPeerInfoGetSPID _SOSPeerInfoGetPeerName _SOSPeerInfoGetPeerProtocolVersion _SOSPeerInfoGetPermittedViews @@ -407,6 +401,7 @@ _SOSFullPeerInfoCreateWithViews _SOSFullPeerInfoEncodeToDER _SOSFullPeerInfoGetDEREncodedSize _SOSFullPeerInfoPing +_SOSFullPeerInfoSetCKKS4AllSupport _SOSFullPeerInfoPrivKeyExists _SOSFullPeerInfoPromoteToRetiredAndCopy _SOSFullPeerInfoPurgePersistentKey @@ -468,6 +463,7 @@ _SOSRingKeyCreateWithName _SOSRingKeyCreateWithRingName _kSOSKVSKeyParametersKey _sCirclePrefix +_sRingPrefix _sDebugInfoPrefix _sRetirementPrefix @@ -489,6 +485,7 @@ _SOSCreateErrorWithFormat _SOSCreateErrorWithFormatAndArguments _SOSDateCreate _SOSErrorCreate +_SOSCCCredentialQueue _SOSGenerateDeviceBackupFullKey _SOSGetBackupKeyCurveParameters _SOSItemsChangedCopyDescription @@ -498,7 +495,7 @@ _SOSTransportMessageTypeIDSV2 _SOSTransportMessageTypeKVS _kSOSDSIDKey _kSOSNoCachedValue - +_kSOSCountKey _SOSPeerGestaltGetAnswer _SOSPeerGestaltGetName @@ -536,6 +533,7 @@ _sBackupKeyKey _sEscrowRecord _sTransportType _SOSGenerationCountCopyDescription +_sCKKSForAll _kSOSHsaCrKeyDictionary _SOSPeerInfoCopySerialNumber @@ -544,6 +542,8 @@ _SOSPeerInfoPackV2Data _SOSPeerInfoSerialNumberIsSet _SOSPeerInfoSetSerialNumber _SOSPeerInfoSetTestSerialNumber +_SOSPeerInfoSetSupportsCKKSForAll +_SOSPeerInfoSupportsCKKSForAll _SOSPeerInfoSign _SOSPeerInfoUpdateToV2 _SOSPeerInfoV2DictionaryCopyDictionary diff --git a/keychain/SecureObjectSync/SOSFullPeerInfo.h b/keychain/SecureObjectSync/SOSFullPeerInfo.h index dce3a3f8..05e1b1af 100644 --- a/keychain/SecureObjectSync/SOSFullPeerInfo.h +++ b/keychain/SecureObjectSync/SOSFullPeerInfo.h @@ -63,6 +63,7 @@ SecKeyRef SOSFullPeerInfoCopyOctagonPublicSigningKey(SOSFullPeerInfoRef fullPeer SecKeyRef SOSFullPeerInfoCopyOctagonPublicEncryptionKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error); SecKeyRef SOSFullPeerInfoCopyOctagonSigningKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error); SecKeyRef SOSFullPeerInfoCopyOctagonEncryptionKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error); +bool SOSFullPeerInfoSetCKKS4AllSupport(SOSFullPeerInfoRef fullPeerInfo, bool support, CFErrorRef* error); bool SOSFullPeerInfoPurgePersistentKey(SOSFullPeerInfoRef peer, CFErrorRef* error); diff --git a/keychain/SecureObjectSync/SOSFullPeerInfo.m b/keychain/SecureObjectSync/SOSFullPeerInfo.m index adea2788..02cbbe20 100644 --- a/keychain/SecureObjectSync/SOSFullPeerInfo.m +++ b/keychain/SecureObjectSync/SOSFullPeerInfo.m @@ -41,7 +41,6 @@ #include #include -#include #include #include @@ -146,15 +145,17 @@ SOSFullPeerInfoRef SOSFullPeerInfoCreateWithViews(CFAllocatorRef allocator, fpi->peer_info = SOSPeerInfoCreateWithTransportAndViews(allocator, gestalt, backupKey, IDSID, transportType, preferIDS, preferIDSFragmentation, preferACKModel, initialViews, - signingKey, octagonPeerSigningKey, octagonPeerEncryptionKey, error); + signingKey, octagonPeerSigningKey, octagonPeerEncryptionKey, + // All newly-created FullPeerInfos are on software that supports CKKS4All + true, + error); require_quiet(fpi->peer_info, exit); OSStatus status = SecKeyCopyPersistentRef(signingKey, &fpi->key_ref); require_quiet(SecError(status, error, CFSTR("Inflating persistent ref")), exit); - status = SecKeyCopyPersistentRef(octagonPeerSigningKey, &fpi->octagon_peer_signing_key_ref); require_quiet(SecError(status, error, CFSTR("Inflating octagon peer signing persistent ref")), exit); - status = SecKeyCopyPersistentRef(octagonPeerSigningKey, &fpi->octagon_peer_encryption_key_ref); + status = SecKeyCopyPersistentRef(octagonPeerEncryptionKey, &fpi->octagon_peer_encryption_key_ref); require_quiet(SecError(status, error, CFSTR("Inflating octagon peer encryption persistent ref")), exit); CFTransferRetained(result, fpi); @@ -199,6 +200,27 @@ bool SOSFullPeerInfoUpdateOctagonEncryptionKey(SOSFullPeerInfoRef peer, SecKeyRe }); } +bool SOSFullPeerInfoSetCKKS4AllSupport(SOSFullPeerInfoRef fullPeerInfo, bool support, CFErrorRef* error) { + + SOSPeerInfoRef peerInfo = SOSFullPeerInfoGetPeerInfo(fullPeerInfo); + bool supportsCKKS4All = SOSPeerInfoSupportsCKKSForAll(peerInfo); + + if(supportsCKKS4All == support) { + // Early-exit: no change needed + return true; + } + + secnotice("circleChange", "Setting CKKS4All status to '%@'", support ? @"supported" : @"not supported"); + + return SOSFullPeerInfoUpdate(fullPeerInfo, error, ^SOSPeerInfoRef(SOSPeerInfoRef currentPeerInfo, SecKeyRef key, CFErrorRef *blockerror) { + SOSPeerInfoRef newPeerInfo = SOSPeerInfoCopyWithModification(kCFAllocatorDefault, currentPeerInfo, key, blockerror, + ^bool(SOSPeerInfoRef peerToModify, CFErrorRef *innerblockerror) { + SOSPeerInfoSetSupportsCKKSForAll(peerToModify, support); + return true; + }); + return newPeerInfo; + }); +} CFDataRef SOSPeerInfoCopyData(SOSPeerInfoRef pi, CFErrorRef *error) @@ -271,7 +293,7 @@ SOSFullPeerInfoRef SOSFullPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErro fpi->peer_info = SOSPeerInfoCreateFromDER(allocator, error, der_p, der_end); require_quiet(fpi->peer_info != NULL, fail); - *der_p = der_decode_data(allocator, kCFPropertyListImmutable, &fpi->key_ref, error, *der_p, sequence_end); + *der_p = der_decode_data(allocator, &fpi->key_ref, error, *der_p, sequence_end); require_quiet(*der_p != NULL, fail); return fpi; @@ -492,12 +514,14 @@ errOut: static SecKeyRef SOSFullPeerInfoCopyMatchingPrivateKey(SOSFullPeerInfoRef fpi, CFErrorRef *error) { SecKeyRef retval = NULL; - SecKeyRef pub = SOSFullPeerInfoCopyPubKey(fpi, error); - require_quiet(pub, exit); - retval = SecKeyCopyMatchingPrivateKey(pub, error); -exit: - CFReleaseNull(pub); + if(pub) { + retval = SecKeyCopyMatchingPrivateKey(pub, error); + if(!retval) { + secnotice("circleOp", "Failed to find my private key for spid %@", SOSPeerInfoGetSPID(SOSFullPeerInfoGetPeerInfo(fpi))); + } + CFReleaseNull(pub); + } return retval; } diff --git a/keychain/SecureObjectSync/SOSGenCount.c b/keychain/SecureObjectSync/SOSGenCount.c index 5163e901..ef04e2dc 100644 --- a/keychain/SecureObjectSync/SOSGenCount.c +++ b/keychain/SecureObjectSync/SOSGenCount.c @@ -124,7 +124,7 @@ SOSGenCountRef SOSGenerationCreateWithBaseline(SOSGenCountRef reference) { SOSGenCountRef SOSGenCountCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, const uint8_t** der_p, const uint8_t *der_end) { SOSGenCountRef retval = NULL; - *der_p = der_decode_number(allocator, 0, &retval, error, *der_p, der_end); + *der_p = der_decode_number(allocator, &retval, error, *der_p, der_end); if(retval == NULL) retval = SOSGenerationCreate(); return retval; diff --git a/keychain/SecureObjectSync/SOSInternal.h b/keychain/SecureObjectSync/SOSInternal.h index 0460de82..8c02d3c0 100644 --- a/keychain/SecureObjectSync/SOSInternal.h +++ b/keychain/SecureObjectSync/SOSInternal.h @@ -39,6 +39,10 @@ __BEGIN_DECLS +#define SOS_ACCOUNT_PRIORITY DISPATCH_QUEUE_PRIORITY_LOW +#define SOS_ENGINE_PRIORITY DISPATCH_QUEUE_PRIORITY_BACKGROUND +#define SOS_TRANSPORT_PRIORITY DISPATCH_QUEUE_PRIORITY_LOW + #define ENABLE_IDS 0 #define kSOSPeerIDLengthMax (26) @@ -82,12 +86,16 @@ enum { kSOSErrorParam = 1045, kSOSErrorNotInCircle = 1046, kSOSErrorKeysNeedAttention = 1047, + kSOSErrorNoAccount = 1048, }; extern const CFStringRef SOSTransportMessageTypeIDSV2; extern const CFStringRef SOSTransportMessageTypeKVS; extern const CFStringRef kSOSDSIDKey; extern const SOSCCStatus kSOSNoCachedValue; +extern const CFStringRef kSOSCountKey; + +dispatch_queue_t SOSCCCredentialQueue(void); // Returns false unless errorCode is 0. bool SOSErrorCreate(CFIndex errorCode, CFErrorRef *error, CFDictionaryRef formatOptions, CFStringRef descriptionString, ...); diff --git a/keychain/SecureObjectSync/SOSInternal.m b/keychain/SecureObjectSync/SOSInternal.m index 35e8c151..696387e3 100644 --- a/keychain/SecureObjectSync/SOSInternal.m +++ b/keychain/SecureObjectSync/SOSInternal.m @@ -47,9 +47,9 @@ #include #include -#include - -#include +#include +#include +#include #include @@ -59,6 +59,7 @@ const CFStringRef kSOSErrorDomain = CFSTR("com.apple.security.sos.error"); const CFStringRef kSOSDSIDKey = CFSTR("AccountDSID"); const CFStringRef SOSTransportMessageTypeIDSV2 = CFSTR("IDS2.0"); const CFStringRef SOSTransportMessageTypeKVS = CFSTR("KVS"); +const CFStringRef kSOSCountKey = CFSTR("numberOfErrorsDeep"); bool SOSErrorCreate(CFIndex errorCode, CFErrorRef *error, CFDictionaryRef formatOptions, CFStringRef format, ...) CF_FORMAT_FUNCTION(4, 5); @@ -256,23 +257,29 @@ bool SOSGenerateDeviceBackupFullKey(ccec_full_ctx_t generatedKey, ccec_const_cp_ { bool result = false; int cc_result = 0; - struct ccrng_pbkdf2_prng_state pbkdf2_prng; - const int kBackupKeyMaxBytes = 1024; // This may be a function of the cp but will be updated when we use a formally deterministic key generation. - - cc_result = ccrng_pbkdf2_prng_init(&pbkdf2_prng, kBackupKeyMaxBytes, - CFDataGetLength(entropy), CFDataGetBytePtr(entropy), - sizeof(sBackupKeySalt), sBackupKeySalt, - kBackupKeyIterations); - require_action_quiet(cc_result == 0, exit, SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("pbkdf rng init failed: %d"), cc_result)); - cc_result = ccec_compact_generate_key(cp, (struct ccrng_state *) &pbkdf2_prng, generatedKey); - require_action_quiet(cc_result == 0, exit, SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("Generate key failed: %d"), cc_result)); +#define drbg_output_size 1024 + + uint8_t drbg_output[drbg_output_size]; + cc_result = ccpbkdf2_hmac(ccsha256_di(), CFDataGetLength(entropy), CFDataGetBytePtr(entropy), + sizeof(sBackupKeySalt), sBackupKeySalt, + kBackupKeyIterations, + drbg_output_size, drbg_output); + require_action_quiet(cc_result == 0, exit, + SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("ccpbkdf2_hmac failed: %d"), cc_result)); + + cc_result = ccec_generate_key_deterministic(cp, + drbg_output_size, + drbg_output, + ccrng(NULL), + CCEC_GENKEY_DETERMINISTIC_SECBKP, + generatedKey); + require_action_quiet(cc_result == 0, exit, + SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("ccec_generate_key_deterministic failed: %d"), cc_result)); result = true; exit: - bzero(&pbkdf2_prng, sizeof(pbkdf2_prng)); return result; - } CFDataRef SOSCopyDeviceBackupPublicKey(CFDataRef entropy, CFErrorRef *error) @@ -440,3 +447,12 @@ NSDate *SOSCreateRandomDateBetweenNowPlus(NSTimeInterval starting, NSTimeInterva return [[NSDate alloc] initWithTimeIntervalSinceNow:resultInterval]; } + +dispatch_queue_t SOSCCCredentialQueue(void) { + static dispatch_queue_t credQueue = NULL; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + credQueue = dispatch_queue_create("com.apple.SOSCredentialsQueue", DISPATCH_QUEUE_SERIAL); + }); + return credQueue; +} diff --git a/keychain/SecureObjectSync/SOSIntervalEvent.m b/keychain/SecureObjectSync/SOSIntervalEvent.m index 30fda736..f230261b 100644 --- a/keychain/SecureObjectSync/SOSIntervalEvent.m +++ b/keychain/SecureObjectSync/SOSIntervalEvent.m @@ -54,15 +54,16 @@ SOSIntervalEvent fooEvent = [[SOSIntervalEvent alloc] initWithDefaults:account.s } -(id)initWithDefaults:(NSUserDefaults*) defaults dateDescription:(NSString *)dateDescription earliest:(NSTimeInterval) earliest latest: (NSTimeInterval) latest { - if(!self) return nil; - _defaults = defaults; - if(! _defaults) { - _defaults = [[NSUserDefaults alloc] init]; + if ((self = [super init])) { + _defaults = defaults; + if(! _defaults) { + _defaults = [[NSUserDefaults alloc] init]; + } + _dateDescription = dateDescription; + _earliestDate = earliest; + _latestDate = latest; + [self schedule]; } - _dateDescription = dateDescription; - _earliestDate = earliest; - _latestDate = latest; - [self schedule]; return self; } diff --git a/keychain/SecureObjectSync/SOSKVSKeys.h b/keychain/SecureObjectSync/SOSKVSKeys.h index 84afb8c9..dabc69c5 100644 --- a/keychain/SecureObjectSync/SOSKVSKeys.h +++ b/keychain/SecureObjectSync/SOSKVSKeys.h @@ -36,6 +36,7 @@ extern const CFStringRef kSOSKVSWroteLastKeyParams; extern const CFStringRef sCirclePrefix; extern const CFStringRef sRetirementPrefix; extern const CFStringRef sDebugInfoPrefix; +extern const CFStringRef sRingPrefix; SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key); bool SOSKVSKeyParse(SOSKVSKeyType keyType, CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to); diff --git a/keychain/SecureObjectSync/SOSMessage.c b/keychain/SecureObjectSync/SOSMessage.c index 97ab42db..f01b48da 100644 --- a/keychain/SecureObjectSync/SOSMessage.c +++ b/keychain/SecureObjectSync/SOSMessage.c @@ -443,13 +443,13 @@ bool SOSMessageAppendObject(SOSMessageRef message, CFDataRef object, CFErrorRef return true; } -static CC_NONNULL_ALL -size_t ccder_sizeof_bit_string(cc_size n, const cc_unit *s) { +static +size_t ccder_sizeof_bit_string(cc_size n, const cc_unit *_Nonnull s) { return ccder_sizeof(CCDER_BIT_STRING, ccn_sizeof(ccn_bitlen(n, s)) + 1); } -static CC_NONNULL_ALL -uint8_t *ccder_encode_bit_string(cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end) { +static +uint8_t *ccder_encode_bit_string(cc_size n, const cc_unit *_Nonnull s, const uint8_t *_Nonnull der, uint8_t *_Nonnull der_end) { size_t bits = ccn_bitlen(n, s); size_t out_size = ccn_sizeof(bits) + 1; der_end = ccder_encode_body_nocopy(out_size, der, der_end); @@ -467,8 +467,8 @@ size_t der_sizeof_implicit_data(ccder_tag tag, CFDataRef data) { } -static CC_NONNULL((3, 4)) -uint8_t *der_encode_implicit_data(ccder_tag tag, CFDataRef data, const uint8_t *der, uint8_t *der_end) { +static +uint8_t *der_encode_implicit_data(ccder_tag tag, CFDataRef data, const uint8_t *_Nonnull der, uint8_t *_Nonnull der_end) { if (!data) return der_end; return ccder_encode_implicit_raw_octet_string(tag, CFDataGetLength(data), CFDataGetBytePtr(data), der, der_end); @@ -765,8 +765,8 @@ CFDataRef SOSMessageCreateData(SOSMessageRef message, uint64_t sequenceNumber, C // Decode BER length field. Sets *lenp to ccber_indefinite_len if this is an indefinite length encoded object. // Behaves like ccder_decode_len in every other way. -static CC_NONNULL((1, 3)) -const uint8_t *ccber_decode_len(size_t *lenp, const uint8_t *der, const uint8_t *der_end) { +static +const uint8_t *ccber_decode_len(size_t *_Nonnull lenp, const uint8_t *_Nullable der, const uint8_t *_Nonnull der_end) { if (der && der < der_end) { if (*der == 0x80) { der++; @@ -793,8 +793,8 @@ static const uint8_t *der_decode_optional_generalizedtime(CFAbsoluteTime *at, CF return times_end ? times_end : der; } -static CC_NONNULL((2, 4)) -const uint8_t *ccder_decode_implicit_uint64(ccder_tag expected_tag, uint64_t* r, const uint8_t *der, const uint8_t *der_end) { +static +const uint8_t *ccder_decode_implicit_uint64(ccder_tag expected_tag, uint64_t *_Nonnull r, const uint8_t *_Nullable der, const uint8_t *_Nonnull der_end) { size_t len; der = ccder_decode_tl(expected_tag, &len, der, der_end); if (der && len && (*der & 0x80) != 0x80) { @@ -1155,7 +1155,7 @@ bool SOSMessageWithSOSObjects(SOSMessageRef message, SOSDataSourceRef dataSource const uint8_t *der = CFDataGetBytePtr(object); const uint8_t *der_end = der + CFDataGetLength(object); // TODO Remove intermediate plist format - der = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &plist, error, der, der_end); + der = der_decode_dictionary(kCFAllocatorDefault, &plist, error, der, der_end); if (der) { SOSObjectRef peersObject = SOSObjectCreateWithPropertyList(dataSource, plist, error); withObject(peersObject, stop); diff --git a/keychain/SecureObjectSync/SOSPeerInfo.h b/keychain/SecureObjectSync/SOSPeerInfo.h index 0e6579b4..e7c78516 100644 --- a/keychain/SecureObjectSync/SOSPeerInfo.h +++ b/keychain/SecureObjectSync/SOSPeerInfo.h @@ -61,11 +61,15 @@ static inline SOSPeerInfoRef asSOSPeerInfo(CFTypeRef obj) { return isSOSPeerInfo(obj) ? (SOSPeerInfoRef) obj : NULL; } -SOSPeerInfoRef SOSPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, SecKeyRef signingKey, SecKeyRef octagonSigningKey, SecKeyRef octagonPeerEncryptionKey, CFErrorRef* error); +SOSPeerInfoRef SOSPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, SecKeyRef signingKey, + SecKeyRef octagonSigningKey, SecKeyRef octagonPeerEncryptionKey, bool supportsCKKS4All, + CFErrorRef* error); SOSPeerInfoRef SOSPeerInfoCreateWithTransportAndViews(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, CFStringRef IDSID, CFStringRef transportType, CFBooleanRef preferIDS, - CFBooleanRef preferFragmentation, CFBooleanRef preferAckModel, CFSetRef enabledViews, SecKeyRef signingKey, SecKeyRef octagonSigningKey, SecKeyRef octagonPeerEncryptionKey, CFErrorRef* error); + CFBooleanRef preferFragmentation, CFBooleanRef preferAckModel, CFSetRef enabledViews, SecKeyRef signingKey, + SecKeyRef octagonSigningKey, SecKeyRef octagonPeerEncryptionKey, bool supportsCKKS4All, + CFErrorRef* error); SOSPeerInfoRef SOSPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error); @@ -138,6 +142,8 @@ CFIndex SOSPeerInfoGetPeerProtocolVersion(SOSPeerInfoRef peer); // Stringified ID for this peer, not human readable. CFStringRef SOSPeerInfoGetPeerID(SOSPeerInfoRef peer); +CFStringRef SOSPeerInfoGetSPID(SOSPeerInfoRef pi); + bool SOSPeerInfoPeerIDEqual(SOSPeerInfoRef pi, CFStringRef myPeerID); CFIndex SOSPeerInfoGetVersion(SOSPeerInfoRef peer); @@ -153,7 +159,7 @@ CFTypeRef SOSPeerGestaltGetAnswer(CFDictionaryRef gestalt, CFStringRef question) SecKeyRef SOSPeerInfoCopyPubKey(SOSPeerInfoRef peer, CFErrorRef *error); SecKeyRef SOSPeerInfoCopyOctagonSigningPublicKey(SOSPeerInfoRef peer, CFErrorRef* error); SecKeyRef SOSPeerInfoCopyOctagonEncryptionPublicKey(SOSPeerInfoRef peer, CFErrorRef* error); -void SOSPeerInfoSetOctagonKeysInDescription(SOSPeerInfoRef peer, SecKeyRef octagonSigningKey, +bool SOSPeerInfoSetOctagonKeysInDescription(SOSPeerInfoRef peer, SecKeyRef octagonSigningKey, SecKeyRef octagonEncryptionKey, CFErrorRef *error); CFDataRef SOSPeerInfoGetAutoAcceptInfo(SOSPeerInfoRef peer); @@ -183,6 +189,9 @@ void SOSPeerInfoWithEnabledViewSet(SOSPeerInfoRef pi, void (^operation)(CFSetRef uint64_t SOSViewBitmaskFromSet(CFSetRef views); uint64_t SOSPeerInfoViewBitMask(SOSPeerInfoRef pi); +bool SOSPeerInfoSupportsCKKSForAll(SOSPeerInfoRef peerInfo); +void SOSPeerInfoSetSupportsCKKSForAll(SOSPeerInfoRef peerInfo, bool supports); + bool SOSPeerInfoKVSOnly(SOSPeerInfoRef pi); CFStringRef SOSPeerInfoCopyTransportType(SOSPeerInfoRef peer); CFStringRef SOSPeerInfoCopyDeviceID(SOSPeerInfoRef peer); diff --git a/keychain/SecureObjectSync/SOSPeerInfo.m b/keychain/SecureObjectSync/SOSPeerInfo.m index 915cc403..f7c304eb 100644 --- a/keychain/SecureObjectSync/SOSPeerInfo.m +++ b/keychain/SecureObjectSync/SOSPeerInfo.m @@ -37,7 +37,6 @@ #include #include -#include #include #include @@ -98,6 +97,8 @@ CFStringRef sPreferIDSACKModel = CFSTR("PreferIDSAckModel"); CFStringRef sTransportType = CFSTR("TransportType"); CFStringRef sDeviceID = CFSTR("DeviceID"); +CFStringRef sCKKSForAll = CFSTR("CKKS4A"); + const CFStringRef peerIDLengthKey = CFSTR("idLength"); SOSPeerInfoRef SOSPeerInfoAllocate(CFAllocatorRef allocator) { @@ -158,10 +159,9 @@ static bool SOSDescriptionHash(SOSPeerInfoRef peer, const struct ccdigest_info * #define SIGLEN 128 static CFDataRef sosCopySignedHash(SecKeyRef privkey, const struct ccdigest_info *di, uint8_t *hbuf) { - OSStatus stat; size_t siglen = SIGLEN; uint8_t sig[siglen]; - if((stat = SecKeyRawSign(privkey, kSecPaddingNone, hbuf, di->output_size, sig, &siglen)) != 0) { + if(SecKeyRawSign(privkey, kSecPaddingNone, hbuf, di->output_size, sig, &siglen) != 0) { return NULL; } return CFDataCreate(NULL, sig, (CFIndex)siglen); @@ -230,6 +230,7 @@ static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, SecKeyRef signingKey, SecKeyRef octagonPeerSigningKey, SecKeyRef octagonPeerEncryptionKey, + bool supportsCKKS4All, CFErrorRef* error, void (^ description_modifier)(CFMutableDictionaryRef description)) { SOSPeerInfoRef pi = CFTypeAllocate(SOSPeerInfo, struct __OpaqueSOSPeerInfo, allocator); @@ -257,6 +258,7 @@ static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, goto exit; } + if (octagonPeerSigningKey) { SecKeyRef octagonPeerSigningPublicKey = SecKeyCreatePublicFromPrivate(octagonPeerSigningKey); if (octagonPeerSigningPublicKey == NULL) { @@ -311,6 +313,7 @@ static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, description_modifier(pi->description); pi->peerID = SOSCopyIDOfKey(publicKey, error); + pi->spid = CFStringCreateTruncatedCopy(pi->peerID, 8); pi->verifiedAppKeyID = NULL; pi->verifiedResult = false; @@ -328,6 +331,8 @@ static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, if (backup_key != NULL) SOSPeerInfoV2DictionarySetValue(pi, sBackupKeyKey, backup_key); SOSPeerInfoV2DictionarySetValue(pi, sViewsKey, enabledViews); + SOSPeerInfoSetSupportsCKKSForAll(pi, supportsCKKS4All); + // ================ V2 Additions End if (!SOSPeerInfoSign(signingKey, pi, error)) { @@ -344,8 +349,14 @@ exit: return pi; } -SOSPeerInfoRef SOSPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, SecKeyRef signingKey, SecKeyRef octagonPeerSigningKey, SecKeyRef octagonPeerEncryptionKey, CFErrorRef* error) { - return SOSPeerInfoCreate_Internal(allocator, gestalt, backup_key, NULL, NULL, NULL, NULL, NULL, NULL, signingKey, octagonPeerSigningKey, octagonPeerEncryptionKey, error, ^(CFMutableDictionaryRef description) {}); +SOSPeerInfoRef SOSPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, SecKeyRef signingKey, + SecKeyRef octagonPeerSigningKey, + SecKeyRef octagonPeerEncryptionKey, + bool supportsCKKS4All, + CFErrorRef* error) { + return SOSPeerInfoCreate_Internal(allocator, gestalt, backup_key, NULL, NULL, NULL, NULL, NULL, NULL, signingKey, octagonPeerSigningKey, octagonPeerEncryptionKey, + supportsCKKS4All, + error, ^(CFMutableDictionaryRef description) {}); } SOSPeerInfoRef SOSPeerInfoCreateWithTransportAndViews(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backup_key, @@ -354,14 +365,19 @@ SOSPeerInfoRef SOSPeerInfoCreateWithTransportAndViews(CFAllocatorRef allocator, SecKeyRef signingKey, SecKeyRef octagonPeerSigningKey, SecKeyRef octagonPeerEncryptionKey, + bool supportsCKKS4All, CFErrorRef* error) { - return SOSPeerInfoCreate_Internal(allocator, gestalt, backup_key, IDSID, transportType, preferIDS, preferFragmentation, preferAckModel, enabledViews, signingKey, octagonPeerSigningKey, octagonPeerEncryptionKey, error, ^(CFMutableDictionaryRef description) {}); + return SOSPeerInfoCreate_Internal(allocator, gestalt, backup_key, IDSID, transportType, preferIDS, preferFragmentation, preferAckModel, enabledViews, signingKey, + octagonPeerSigningKey, + octagonPeerEncryptionKey, + supportsCKKS4All, + error, ^(CFMutableDictionaryRef description) {}); } SOSPeerInfoRef SOSPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error) { - return SOSPeerInfoCreate_Internal(allocator, gestalt, NULL, NULL, NULL, NULL, NULL, NULL, NULL, signingKey, NULL, NULL, error, ^(CFMutableDictionaryRef description) { + return SOSPeerInfoCreate_Internal(allocator, gestalt, NULL, NULL, NULL, NULL, NULL, NULL, NULL, signingKey, NULL, NULL, false, error, ^(CFMutableDictionaryRef description) { CFDictionarySetValue(description, sCloudIdentityKey, kCFBooleanTrue); }); @@ -377,6 +393,7 @@ SOSPeerInfoRef SOSPeerInfoCreateCopy(CFAllocatorRef allocator, SOSPeerInfoRef to pi->gestalt = CFDictionaryCreateCopy(allocator, toCopy->gestalt); pi->peerID = CFStringCreateCopy(allocator, toCopy->peerID); + pi->spid = CFStringCreateCopy(allocator, toCopy->spid); pi->verifiedAppKeyID = NULL; // The peer resulting from this will need to be re-evaluated for an application signature. pi->verifiedResult = false; @@ -414,10 +431,10 @@ SOSPeerInfoRef SOSPeerInfoCreateCurrentCopy(CFAllocatorRef allocator, SOSPeerInf } -static SOSPeerInfoRef SOSPeerInfoCopyWithModification(CFAllocatorRef allocator, SOSPeerInfoRef original, - SecKeyRef signingKey, CFErrorRef *error, - bool (^modification)(SOSPeerInfoRef peerToModify, CFErrorRef *error)) { - +SOSPeerInfoRef SOSPeerInfoCopyWithModification(CFAllocatorRef allocator, SOSPeerInfoRef original, + SecKeyRef signingKey, CFErrorRef *error, + bool (^modification)(SOSPeerInfoRef peerToModify, CFErrorRef *error)) +{ SOSPeerInfoRef result = NULL; SOSPeerInfoRef copy = SOSPeerInfoCreateCopy(allocator, original, error); @@ -507,6 +524,7 @@ SOSPeerInfoRef SOSPeerInfoCopyWithPing(CFAllocatorRef allocator, SOSPeerInfoRef SecKeyRef pub_key = SOSPeerInfoCopyPubKey(pi, error); require_quiet(pub_key, exit); pi->peerID = SOSCopyIDOfKey(pub_key, error); + pi->spid = CFStringCreateTruncatedCopy(pi->peerID, 8); require_quiet(pi->peerID, exit); require_action_quiet(SOSPeerInfoSign(signingKey, pi, error), exit, CFReleaseNull(pi)); exit: @@ -528,8 +546,9 @@ static void SOSPeerInfoDestroy(CFTypeRef aObj) { CFReleaseNull(pi->signature); CFReleaseNull(pi->gestalt); CFReleaseNull(pi->peerID); - CFReleaseNull(pi->v2Dictionary); + CFReleaseNull(pi->spid); CFReleaseNull(pi->verifiedAppKeyID); + CFReleaseNull(pi->v2Dictionary); pi->verifiedResult = false; } @@ -609,19 +628,19 @@ static CFStringRef copyDescriptionWithFormatOptions(CFTypeRef aObj, CFDictionary bool selfValid = SOSPeerInfoVerify(pi, NULL); bool backingUp = SOSPeerInfoHasBackupKey(pi); bool isKVS = SOSPeerInfoKVSOnly(pi); + bool isCKKSForAll = SOSPeerInfoSupportsCKKSForAll(pi); CFStringRef osVersion = CFDictionaryGetValue(pi->gestalt, kPIOSVersionKey); CFStringRef tmp = SOSPeerInfoV2DictionaryCopyString(pi, sDeviceID); CFStringRef deviceID = CFStringCreateTruncatedCopy(tmp, 8); CFReleaseNull(tmp); CFStringRef serialNum = SOSPeerInfoCopySerialNumber(pi); - CFStringRef peerID = CFStringCreateTruncatedCopy(SOSPeerInfoGetPeerID(pi), 8); // Calculate the truncated length CFStringRef objectPrefix = CFStringCreateWithFormat(kCFAllocatorDefault, formatOptions, CFSTR("PI@%p"), pi); description = CFStringCreateWithFormat(kCFAllocatorDefault, formatOptions, - CFSTR("<%@: [name: %20@] [%c%c%c%c%c%c%c] [type: %-20@] [spid: %8@] [os: %10@] [devid: %10@] [serial: %12@]"), + CFSTR("<%@: [name: %20@] [%c%c%c%c%c%c%c%c] [type: %-20@] [spid: %8@] [os: %10@] [devid: %10@] [serial: %12@]"), objectPrefix, isKnown(SOSPeerInfoGetPeerName(pi)), '-', @@ -631,10 +650,10 @@ static CFStringRef copyDescriptionWithFormatOptions(CFTypeRef aObj, CFDictionary boolToChars(backingUp, 'B', 'b'), boolToChars(isKVS, 'K', 'I'), '-', - isKnown(SOSPeerInfoGetPeerDeviceType(pi)), isKnown(peerID), + boolToChars(isCKKSForAll, 'C', '_'), + isKnown(SOSPeerInfoGetPeerDeviceType(pi)), isKnown(SOSPeerInfoGetSPID(pi)), isKnown(osVersion), isKnown(deviceID), isKnown(serialNum)); - CFReleaseNull(peerID); CFReleaseNull(deviceID); CFReleaseNull(serialNum); CFReleaseNull(objectPrefix); @@ -660,25 +679,25 @@ void SOSPeerInfoLogState(char *category, SOSPeerInfoRef pi, SecKeyRef pubKey, CF bool backingUp = SOSPeerInfoHasBackupKey(pi); bool isMe = CFEqualSafe(SOSPeerInfoGetPeerID(pi), myPID) == true; bool isKVS = SOSPeerInfoKVSOnly(pi); + bool isCKKSForAll = SOSPeerInfoSupportsCKKSForAll(pi); CFStringRef osVersion = CFDictionaryGetValue(pi->gestalt, kPIOSVersionKey); CFStringRef tmp = SOSPeerInfoV2DictionaryCopyString(pi, sDeviceID); CFStringRef deviceID = CFStringCreateTruncatedCopy(tmp, 8); CFReleaseNull(tmp); CFStringRef serialNum = SOSPeerInfoCopySerialNumber(pi); - CFStringRef peerID = CFStringCreateTruncatedCopy(SOSPeerInfoGetPeerID(pi), 8); - secnotice(category, "PI: [name: %-20@] [%c%c%c%c%c%c%c] [type: %-20@] [spid: %8@] [os: %10@] [devid: %10@] [serial: %12@]", isKnown(SOSPeerInfoGetPeerName(pi)), + secnotice(category, "PI: [name: %-20@] [%c%c%c%c%c%c%c%c] [type: %-20@] [spid: %8@] [os: %10@] [devid: %10@] [serial: %12@]", isKnown(SOSPeerInfoGetPeerName(pi)), boolToChars(isMe, 'M', 'm'), boolToChars(appValid, 'A', 'a'), boolToChars(selfValid, 'S', 's'), boolToChars(retired, 'R', 'r'), boolToChars(backingUp, 'B', 'b'), boolToChars(isKVS, 'K', 'I'), + boolToChars(isCKKSForAll, 'C', '_'), sigchr, - isKnown(SOSPeerInfoGetPeerDeviceType(pi)), isKnown(peerID), + isKnown(SOSPeerInfoGetPeerDeviceType(pi)), isKnown(SOSPeerInfoGetSPID(pi)), isKnown(osVersion), isKnown(deviceID), isKnown(serialNum)); - CFReleaseNull(peerID); CFReleaseNull(deviceID); CFReleaseNull(serialNum); } @@ -716,6 +735,10 @@ CFStringRef SOSPeerInfoGetPeerID(SOSPeerInfoRef pi) { return pi ? pi->peerID : NULL; } +CFStringRef SOSPeerInfoGetSPID(SOSPeerInfoRef pi) { + return pi ? pi->spid : NULL; +} + bool SOSPeerInfoPeerIDEqual(SOSPeerInfoRef pi, CFStringRef myPeerID) { return CFEqualSafe(myPeerID, SOSPeerInfoGetPeerID(pi)); } @@ -780,7 +803,7 @@ static CFDataRef sosCreateDate() { static CFDateRef sosCreateCFDate(CFDataRef sosdate) { CFDateRef date; - der_decode_date(NULL, 0, &date, NULL, CFDataGetBytePtr(sosdate), + der_decode_date(NULL, &date, NULL, CFDataGetBytePtr(sosdate), CFDataGetBytePtr(sosdate) + CFDataGetLength(sosdate)); return date; } @@ -983,9 +1006,10 @@ SOSPeerInfoRef SOSPeerInfoUpgradeSignatures(CFAllocatorRef allocator, SecKeyRef return retval; } -void SOSPeerInfoSetOctagonKeysInDescription(SOSPeerInfoRef peer, SecKeyRef octagonSigningKey, +bool SOSPeerInfoSetOctagonKeysInDescription(SOSPeerInfoRef peer, SecKeyRef octagonSigningKey, SecKeyRef octagonEncryptionKey, CFErrorRef *error) { + bool ret = false; CFDataRef signingPublicKeyBytes = NULL; CFDataRef encryptionPublicKeyBytes = NULL; @@ -999,9 +1023,13 @@ void SOSPeerInfoSetOctagonKeysInDescription(SOSPeerInfoRef peer, SecKeyRef octa CFDictionarySetValue(peer->description, sOctagonPeerSigningPublicKeyKey, signingPublicKeyBytes); CFDictionarySetValue(peer->description, sOctagonPeerEncryptionPublicKeyKey, encryptionPublicKeyBytes); + ret = true; + fail: CFReleaseNull(signingPublicKeyBytes); CFReleaseNull(encryptionPublicKeyBytes); + + return ret; } diff --git a/keychain/SecureObjectSync/SOSPeerInfoDER.m b/keychain/SecureObjectSync/SOSPeerInfoDER.m index b71e7f93..a1bc10ff 100644 --- a/keychain/SecureObjectSync/SOSPeerInfoDER.m +++ b/keychain/SecureObjectSync/SOSPeerInfoDER.m @@ -77,8 +77,8 @@ SOSPeerInfoRef SOSPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* er pi->gestalt = NULL; pi->version = 0; // TODO: Encode this in the DER *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - *der_p = der_decode_plist(allocator, kCFPropertyListImmutable, &pl, error, *der_p, sequence_end); - *der_p = der_decode_data(allocator, kCFPropertyListImmutable, &pi->signature, error, *der_p, sequence_end); + *der_p = der_decode_plist(allocator, &pl, error, *der_p, sequence_end); + *der_p = der_decode_data(allocator, &pi->signature, error, *der_p, sequence_end); if (*der_p == NULL || *der_p != sequence_end) { SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Format of Peer Info DER"), NULL, error); @@ -134,7 +134,8 @@ SOSPeerInfoRef SOSPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* er pi->peerID = SOSCopyIDOfKey(pubKey, error); require_quiet(pi->peerID, fail); - + pi->spid = CFStringCreateTruncatedCopy(pi->peerID, 8); + if(pi->version >= 2) SOSPeerInfoExpandV2Data(pi, error); if(!SOSPeerInfoVerify(pi, error)) { diff --git a/keychain/SecureObjectSync/SOSPeerInfoPriv.h b/keychain/SecureObjectSync/SOSPeerInfoPriv.h index c216d2c0..c669ab0a 100644 --- a/keychain/SecureObjectSync/SOSPeerInfoPriv.h +++ b/keychain/SecureObjectSync/SOSPeerInfoPriv.h @@ -22,6 +22,7 @@ struct __OpaqueSOSPeerInfo { // Cached data CFDictionaryRef gestalt; CFStringRef peerID; + CFStringRef spid; CFIndex version; CFStringRef verifiedAppKeyID; bool verifiedResult; @@ -35,6 +36,10 @@ bool SOSPeerInfoSign(SecKeyRef privKey, SOSPeerInfoRef peer, CFErrorRef *error); bool SOSPeerInfoVerify(SOSPeerInfoRef peer, CFErrorRef *error); void SOSPeerInfoSetVersionNumber(SOSPeerInfoRef pi, int version); +SOSPeerInfoRef SOSPeerInfoCopyWithModification(CFAllocatorRef allocator, SOSPeerInfoRef original, + SecKeyRef signingKey, CFErrorRef *error, + bool (^modification)(SOSPeerInfoRef peerToModify, CFErrorRef *error)); + extern const CFStringRef peerIDLengthKey; #endif diff --git a/keychain/SecureObjectSync/SOSPeerInfoV2.h b/keychain/SecureObjectSync/SOSPeerInfoV2.h index d482b248..661699f8 100644 --- a/keychain/SecureObjectSync/SOSPeerInfoV2.h +++ b/keychain/SecureObjectSync/SOSPeerInfoV2.h @@ -30,6 +30,8 @@ extern CFStringRef sRingState; // Dictionary of Ring Membership extern CFStringRef sBackupKeyKey; extern CFStringRef sEscrowRecord; +extern CFStringRef sCKKSForAll; + bool SOSPeerInfoUpdateToV2(SOSPeerInfoRef pi, CFErrorRef *error); void SOSPeerInfoPackV2Data(SOSPeerInfoRef peer); bool SOSPeerInfoExpandV2Data(SOSPeerInfoRef pi, CFErrorRef *error); diff --git a/keychain/SecureObjectSync/SOSPeerInfoV2.m b/keychain/SecureObjectSync/SOSPeerInfoV2.m index 84eec8a6..d3a812fb 100644 --- a/keychain/SecureObjectSync/SOSPeerInfoV2.m +++ b/keychain/SecureObjectSync/SOSPeerInfoV2.m @@ -127,7 +127,7 @@ static CFMutableDictionaryRef SOSCreateDictionaryFromDER(CFDataRef v2Data, CFErr const uint8_t *der_p = CFDataGetBytePtr(v2Data); const uint8_t *der_end = CFDataGetLength(v2Data) + der_p; - der_p = der_decode_plist(NULL, kCFPropertyListImmutable, &pl, error, der_p, der_end); + der_p = der_decode_plist(NULL, &pl, error, der_p, der_end); if (der_p == NULL || der_p != der_end) { SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Format of Dictionary DER"), NULL, error); diff --git a/keychain/SecureObjectSync/SOSPeerOTRTimer.m b/keychain/SecureObjectSync/SOSPeerOTRTimer.m index 87c682fe..f2f93a8b 100644 --- a/keychain/SecureObjectSync/SOSPeerOTRTimer.m +++ b/keychain/SecureObjectSync/SOSPeerOTRTimer.m @@ -15,16 +15,12 @@ #include "keychain/SecureObjectSync/SOSPeerOTRTimer.h" #include "keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.h" -#include #include #include #include #include "keychain/SecureObjectSync/SOSInternal.h" -//AGGD -NSString* const SecSOSAggdMaxRenegotiation = @"com.apple.security.sos.otrrenegotiationmaxretries"; - static int maxRetryCount = 7; //max number of times to attempt restarting OTR negotiation bool SOSPeerOTRTimerHaveReachedMaxRetryAllowance(SOSAccount* account, NSString* peerid){ @@ -37,7 +33,6 @@ bool SOSPeerOTRTimerHaveReachedMaxRetryAllowance(SOSAccount* account, NSString* if(attempt && [attempt intValue] >= maxRetryCount) { reachedMax = true; - SecADAddValueForScalarKey((__bridge CFStringRef) SecSOSAggdMaxRenegotiation,1); } return reachedMax; } diff --git a/keychain/SecureObjectSync/SOSPeerRateLimiter.m b/keychain/SecureObjectSync/SOSPeerRateLimiter.m index 15d756f9..104efeba 100644 --- a/keychain/SecureObjectSync/SOSPeerRateLimiter.m +++ b/keychain/SecureObjectSync/SOSPeerRateLimiter.m @@ -71,8 +71,7 @@ -(instancetype)initWithPeer:(SOSPeerRef)peer { - self = [super initWithConfig:[self setUpConfigForPeer]]; - if(self){ + if ((self = [super initWithConfig:[self setUpConfigForPeer]])) { self.peerID = (__bridge NSString *)(SOSPeerGetID(peer)); self.accessGroupRateLimitState = [[NSMutableDictionary alloc] init]; self.accessGroupToTimer = [[NSMutableDictionary alloc]init]; @@ -102,8 +101,7 @@ -(instancetype)initWithAccessGroup:(NSString *)accessGroup { - self = [super init]; - if(self){ + if ((self = [super init])) { _accessGroup = accessGroup; } return self; diff --git a/keychain/SecureObjectSync/SOSPiggyback.m b/keychain/SecureObjectSync/SOSPiggyback.m index 0234388f..5780234c 100644 --- a/keychain/SecureObjectSync/SOSPiggyback.m +++ b/keychain/SecureObjectSync/SOSPiggyback.m @@ -262,7 +262,7 @@ SOSPiggyCreateDecodedTLKs(const uint8_t *der, const uint8_t *der_end) CFErrorRef localError = NULL; CFStringRef string = NULL; - choice_der = der_decode_string(NULL, 0, &string, &localError, item_der, end_item_der); + choice_der = der_decode_string(NULL, &string, &localError, item_der, end_item_der); if (choice_der == NULL || string == NULL) { CFReleaseNull(string); secnotice("piggy", "Failed to parse view name"); @@ -365,7 +365,7 @@ SOSPiggyBackBlobCreateFromDER(SOSGenCountRef *retGencount, *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); require_action_quiet(sequence_end != NULL, errOut, SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Blob DER"), (error != NULL) ? *error : NULL, error)); - *der_p = der_decode_number(kCFAllocatorDefault, 0, &gencount, error, *der_p, sequence_end); + *der_p = der_decode_number(kCFAllocatorDefault, &gencount, error, *der_p, sequence_end); *der_p = der_decode_data_or_null(kCFAllocatorDefault, &publicBytes, error, *der_p, sequence_end); *der_p = der_decode_data_or_null(kCFAllocatorDefault, &signature, error, *der_p, sequence_end); diff --git a/keychain/SecureObjectSync/SOSRecoveryKeyBag.m b/keychain/SecureObjectSync/SOSRecoveryKeyBag.m index 5555949b..91abdc17 100644 --- a/keychain/SecureObjectSync/SOSRecoveryKeyBag.m +++ b/keychain/SecureObjectSync/SOSRecoveryKeyBag.m @@ -101,10 +101,10 @@ const uint8_t* der_decode_RecoveryKeyBag(CFAllocatorRef allocator, der = ccder_decode_sequence_tl(&sequence_end, der, der_end); require_quiet(sequence_end == der_end, fail); - der = der_decode_string(kCFAllocatorDefault, kCFPropertyListImmutable, &rb->accountDSID, error, der, sequence_end); + der = der_decode_string(kCFAllocatorDefault, &rb->accountDSID, error, der, sequence_end); rb->generation = SOSGenCountCreateFromDER(kCFAllocatorDefault, error, &der, sequence_end); der = ccder_decode_uint64(&rb->rkbVersion, der, sequence_end); - der = der_decode_data(allocator, kCFPropertyListImmutable, &rb->recoveryKeyBag, error, der, sequence_end); + der = der_decode_data(allocator, &rb->recoveryKeyBag, error, der, sequence_end); require_quiet(SecRequirementError(der == der_end, error, CFSTR("Extra space in sequence")), fail); if (RecoveryKeyBag) CFTransferRetained(*RecoveryKeyBag, rb); diff --git a/keychain/SecureObjectSync/SOSRingBackup.m b/keychain/SecureObjectSync/SOSRingBackup.m index 26582d44..1c9cba4c 100644 --- a/keychain/SecureObjectSync/SOSRingBackup.m +++ b/keychain/SecureObjectSync/SOSRingBackup.m @@ -24,7 +24,6 @@ #include #include -#include #include "SOSRingUtils.h" #include "SOSRingTypes.h" diff --git a/keychain/SecureObjectSync/SOSRingBasic.m b/keychain/SecureObjectSync/SOSRingBasic.m index 6c0cfa21..e2fea8b8 100644 --- a/keychain/SecureObjectSync/SOSRingBasic.m +++ b/keychain/SecureObjectSync/SOSRingBasic.m @@ -23,7 +23,6 @@ #include #include -#include #include "SOSRingUtils.h" #include "SOSRingTypes.h" diff --git a/keychain/SecureObjectSync/SOSRingConcordanceTrust.c b/keychain/SecureObjectSync/SOSRingConcordanceTrust.c index 2218db14..110aee53 100644 --- a/keychain/SecureObjectSync/SOSRingConcordanceTrust.c +++ b/keychain/SecureObjectSync/SOSRingConcordanceTrust.c @@ -34,7 +34,6 @@ #include #include -#include #include "SOSRing.h" #include "SOSRingUtils.h" diff --git a/keychain/SecureObjectSync/SOSRingDER.c b/keychain/SecureObjectSync/SOSRingDER.c index 66d6f70a..b53f54ad 100644 --- a/keychain/SecureObjectSync/SOSRingDER.c +++ b/keychain/SecureObjectSync/SOSRingDER.c @@ -35,7 +35,6 @@ #include #include -#include #include "SOSRingUtils.h" @@ -79,10 +78,10 @@ SOSRingRef SOSRingCreateFromDER(CFErrorRef* error, const uint8_t** der_p, const require_action_quiet(ring, errOut, secnotice("ring", "Unable to allocate ring")); *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - *der_p = der_decode_dictionary(ALLOCATOR, kCFPropertyListImmutable, &unSignedInformation, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(ALLOCATOR, kCFPropertyListImmutable, &signedInformation, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(ALLOCATOR, kCFPropertyListImmutable, &signatures, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(ALLOCATOR, kCFPropertyListImmutable, &data, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(ALLOCATOR, &unSignedInformation, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(ALLOCATOR, &signedInformation, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(ALLOCATOR, &signatures, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(ALLOCATOR, &data, error, *der_p, sequence_end); require_action_quiet(*der_p, errOut, secnotice("ring", "Unable to decode DER")); require_action_quiet(*der_p == der_end, errOut, secnotice("ring", "Unable to decode DER")); diff --git a/keychain/SecureObjectSync/SOSRingPeerInfoUtils.c b/keychain/SecureObjectSync/SOSRingPeerInfoUtils.c index a141de62..e18ddb0a 100644 --- a/keychain/SecureObjectSync/SOSRingPeerInfoUtils.c +++ b/keychain/SecureObjectSync/SOSRingPeerInfoUtils.c @@ -35,7 +35,6 @@ #include #include -#include #include "SOSRing.h" #include "SOSRingUtils.h" diff --git a/keychain/SecureObjectSync/SOSRingRecovery.m b/keychain/SecureObjectSync/SOSRingRecovery.m index 3a204d68..e513853c 100644 --- a/keychain/SecureObjectSync/SOSRingRecovery.m +++ b/keychain/SecureObjectSync/SOSRingRecovery.m @@ -47,7 +47,6 @@ #include #include -#include #include "SOSRingUtils.h" #include "SOSRingTypes.h" diff --git a/keychain/SecureObjectSync/SOSRingUtils.c b/keychain/SecureObjectSync/SOSRingUtils.c index ddff4c19..ac2ad45d 100644 --- a/keychain/SecureObjectSync/SOSRingUtils.c +++ b/keychain/SecureObjectSync/SOSRingUtils.c @@ -54,7 +54,7 @@ #include #include -#include +#include #include "SOSRing.h" #include "SOSRingUtils.h" @@ -730,16 +730,18 @@ static CFStringRef CreateCommaSeparatedPeerIDs(CFSetRef peers) { __block bool addSeparator = false; - CFSetForEachPeerID(peers, ^(CFStringRef peerID) { - if (addSeparator) { - CFStringAppendCString(result, ", ", kCFStringEncodingUTF8); - } - CFStringRef spid = CFStringCreateTruncatedCopy(peerID, 8); - CFStringAppend(result, spid); - CFReleaseNull(spid); - - addSeparator = true; - }); + if(peers) { + CFSetForEachPeerID(peers, ^(CFStringRef peerID) { + if (addSeparator) { + CFStringAppendCString(result, ", ", kCFStringEncodingUTF8); + } + CFStringRef spid = CFStringCreateTruncatedCopy(peerID, 8); + CFStringAppend(result, spid); + CFReleaseNull(spid); + + addSeparator = true; + }); + } return result; } diff --git a/keychain/SecureObjectSync/SOSRingV0.m b/keychain/SecureObjectSync/SOSRingV0.m index 32e28056..e070bd93 100644 --- a/keychain/SecureObjectSync/SOSRingV0.m +++ b/keychain/SecureObjectSync/SOSRingV0.m @@ -23,7 +23,6 @@ #include #include -#include #include "SOSRingUtils.h" #include "SOSRingTypes.h" diff --git a/keychain/SecureObjectSync/SOSTransport.m b/keychain/SecureObjectSync/SOSTransport.m index ce9a8d82..4bdfe17c 100644 --- a/keychain/SecureObjectSync/SOSTransport.m +++ b/keychain/SecureObjectSync/SOSTransport.m @@ -206,7 +206,7 @@ void SOSUpdateKeyInterest(SOSAccount* account) secnotice("key-interests", "Updating interests done: %lu", (unsigned long)itemCount); CFStringRef uuid = SOSAccountCopyUUID(account); - SOSCloudKeychainUpdateKeys(keyDict, uuid, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef error) { + SOSCloudKeychainUpdateKeys(keyDict, uuid, dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(CFDictionaryRef returnedValues, CFErrorRef error) { if (error) { secerror("Error updating keys: %@", error); account.key_interests_need_updating = true; diff --git a/keychain/SecureObjectSync/SOSTransportCircle.m b/keychain/SecureObjectSync/SOSTransportCircle.m index 49145ab1..d58a85e1 100644 --- a/keychain/SecureObjectSync/SOSTransportCircle.m +++ b/keychain/SecureObjectSync/SOSTransportCircle.m @@ -12,8 +12,7 @@ } -(SOSCircleStorageTransport*) initWithAccount:(SOSAccount*)acct { - self = [super init]; - if(self){ + if ((self = [super init])) { self.account = acct; } return self; diff --git a/keychain/SecureObjectSync/SOSTransportCircleCK.m b/keychain/SecureObjectSync/SOSTransportCircleCK.m index 2e3a4cc5..4e82d116 100644 --- a/keychain/SecureObjectSync/SOSTransportCircleCK.m +++ b/keychain/SecureObjectSync/SOSTransportCircleCK.m @@ -15,8 +15,7 @@ -(id) init { - self = [super init]; - if(self){ + if ((self = [super init])) { SOSRegisterTransportCircle(self); } return self; @@ -24,9 +23,7 @@ -(id) initWithAccount:(SOSAccount*)acct { - self = [super init]; - if(self) - { + if ((self = [super init])) { self.account = acct; } return self; diff --git a/keychain/SecureObjectSync/SOSTransportCircleKVS.m b/keychain/SecureObjectSync/SOSTransportCircleKVS.m index d3237e81..1077f639 100644 --- a/keychain/SecureObjectSync/SOSTransportCircleKVS.m +++ b/keychain/SecureObjectSync/SOSTransportCircleKVS.m @@ -25,8 +25,7 @@ extern CFStringRef kSOSAccountDebugScope; -(id)initWithAccount:(SOSAccount*)acct andCircleName:(NSString*)name { - self = [super init]; - if(self){ + if ((self = [super init])) { self.pending_changes = [NSMutableDictionary dictionary]; self.circleName = [[NSString alloc] initWithString:name]; self.account = acct; @@ -52,7 +51,7 @@ static bool SOSTransportCircleKVSUpdateKVS(NSDictionary *changes, CFErrorRef *er } }; - SOSCloudKeychainPutObjectsInCloud((__bridge CFDictionaryRef)(changes), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error); + SOSCloudKeychainPutObjectsInCloud((__bridge CFDictionaryRef)(changes), dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), log_error); return true; } diff --git a/keychain/SecureObjectSync/SOSTransportKeyParameter.m b/keychain/SecureObjectSync/SOSTransportKeyParameter.m index 84b1bf27..25ccd6bb 100644 --- a/keychain/SecureObjectSync/SOSTransportKeyParameter.m +++ b/keychain/SecureObjectSync/SOSTransportKeyParameter.m @@ -35,8 +35,7 @@ -(id) initWithAccount:(SOSAccount*) acct { - self = [super init]; - if(self){ + if ((self = [super init])) { self.account = acct; SOSRegisterTransportKeyParameter(self); } @@ -57,7 +56,7 @@ static bool SOSTransportKeyParameterKVSUpdateKVS(CFDictionaryRef changes, CFErro } }; - SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error); + SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), log_error); return true; } diff --git a/keychain/SecureObjectSync/SOSTransportMessage.m b/keychain/SecureObjectSync/SOSTransportMessage.m index 407c5543..1e6b247f 100644 --- a/keychain/SecureObjectSync/SOSTransportMessage.m +++ b/keychain/SecureObjectSync/SOSTransportMessage.m @@ -5,8 +5,8 @@ #include "keychain/SecureObjectSync/SOSEngine.h" #import "keychain/SecureObjectSync/SOSPeerRateLimiter.h" #import "keychain/SecureObjectSync/SOSPeerOTRTimer.h" -#include +#import "utilities/SecCoreAnalytics.h" #include #include #include "keychain/SecureObjectSync/SOSInternal.h" @@ -29,8 +29,7 @@ static const CFStringRef kSecAccessGroupCKKS = CFSTR("com.apple. -(id) initWithAccount:(SOSAccount*)acct andName:(NSString*)name { - self = [super init]; - if(self){ + if ((self = [super init])) { SOSEngineRef e = SOSDataSourceFactoryGetEngineForDataSourceName(acct.factory, (__bridge CFStringRef)name, NULL); engine = e; account = acct; @@ -89,6 +88,12 @@ static const CFStringRef kSecAccessGroupCKKS = CFSTR("com.apple. bool SOSEngineHandleCodedMessage(SOSAccount* account, SOSEngineRef engine, CFStringRef peerID, CFDataRef codedMessage, CFErrorRef*error) { __block bool result = true; __block bool somethingChanged = false; + + if(account && account.accountIsChanging) { + secnotice("engine", "SOSEngineHandleCodedMessage called before signing in to new account"); + return true; // we want to drop sync message notifications when account is changing + } + result &= SOSEngineWithPeerID(engine, peerID, error, ^(SOSPeerRef peer, SOSCoderRef coder, SOSDataSourceRef dataSource, SOSTransactionRef txn, bool *shouldSave) { CFDataRef decodedMessage = NULL; enum SOSCoderUnwrapStatus uwstatus = SOSPeerHandleCoderMessage(peer, coder, peerID, codedMessage, &decodedMessage, shouldSave, error); @@ -188,8 +193,8 @@ bool SOSEngineHandleCodedMessage(SOSAccount* account, SOSEngineRef engine, CFStr secnotice("otrtimer","peerID: %@ current date: %@, stored date: %@", peerid, currentDate, storedDate); secnotice("otrtimer", "rtt: %d", rtt); [self SOSTransportMessageCalculateNextTimer:account rtt:rtt peerid:peerid]; - - SecADClientPushValueForDistributionKey(kSecSOSMessageRTT, rtt); + + [SecCoreAnalytics sendEvent:(__bridge id)kSecSOSMessageRTT event:@{SecCoreAnalyticsValue: [NSNumber numberWithUnsignedInt:rtt]}]; [peerToTimeLastSentDict removeObjectForKey:peerid]; //remove last sent message date SOSAccountSetValue(account, kSOSAccountPeerLastSentTimestamp, (__bridge CFMutableDictionaryRef)peerToTimeLastSentDict, NULL); } diff --git a/keychain/SecureObjectSync/SOSTransportMessageKVS.m b/keychain/SecureObjectSync/SOSTransportMessageKVS.m index 68af1835..5d785ed9 100644 --- a/keychain/SecureObjectSync/SOSTransportMessageKVS.m +++ b/keychain/SecureObjectSync/SOSTransportMessageKVS.m @@ -3,7 +3,6 @@ #import "keychain/SecureObjectSync/SOSTransportMessageKVS.h" #include "keychain/SecureObjectSync/SOSKVSKeys.h" #include -#include #include "keychain/SecureObjectSync/SOSInternal.h" #include #include "keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.h" @@ -14,9 +13,7 @@ -(id) initWithAccount:(SOSAccount*)acct andName:(NSString*)name { - self = [super init]; - - if (self) { + if ((self = [super init])) { account = acct; circleName = [[NSString alloc]initWithString:name]; SOSEngineRef e = SOSDataSourceFactoryGetEngineForDataSourceName(acct.factory, (__bridge CFStringRef)(circleName), NULL); @@ -83,16 +80,13 @@ fail: } static bool SOSTransportMessageKVSUpdateKVS(SOSMessageKVS* transport, CFDictionaryRef changes, CFErrorRef *error){ - - SecADAddValueForScalarKey(CFSTR("com.apple.security.sos.sendkvs"), 1); - CloudKeychainReplyBlock log_error = ^(CFDictionaryRef returnedValues __unused, CFErrorRef block_error) { if (block_error) { secerror("Error putting: %@", block_error); } }; - SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error); + SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), log_error); return true; } diff --git a/keychain/SecureObjectSync/SOSTypes.h b/keychain/SecureObjectSync/SOSTypes.h index 65f2d9e6..7c328783 100644 --- a/keychain/SecureObjectSync/SOSTypes.h +++ b/keychain/SecureObjectSync/SOSTypes.h @@ -116,6 +116,8 @@ typedef NS_OPTIONS(uint32_t, SOSAccountGhostBustingOptions) { - (void)ghostBustPeriodic:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool busted, NSError *error))complete; - (void)ghostBustTriggerTimed:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool ghostBusted, NSError *error))complete; - (void)ghostBustInfo: (void(^)(NSData *json, NSError *error))complete; +- (void)iCloudIdentityStatus_internal: (void(^)(NSDictionary *tableSpid, NSError *error))complete; +- (void)iCloudIdentityStatus: (void (^)(NSData *json, NSError *error))complete; - (void)myPeerInfo:(void (^)(NSData *, NSError *))complete; - (void)circleHash:(void (^)(NSString *, NSError *))complete; @@ -124,12 +126,14 @@ typedef NS_OPTIONS(uint32_t, SOSAccountGhostBustingOptions) { - (void)initialSyncCredentials:(uint32_t)flags complete:(void (^)(NSArray *, NSError *))complete; - (void)importInitialSyncCredentials:(NSArray *)items complete:(void (^)(bool success, NSError *))complete; -- (void)triggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete; +- (void)rpcTriggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete; - (void)getWatchdogParameters:(void (^)(NSDictionary* parameters, NSError* error))complete; - (void)setWatchdogParmeters:(NSDictionary*)parameters complete:(void (^)(NSError* error))complete; -- (void)triggerBackup:(NSArray*)backupPeers complete:(void (^)(NSError *error))complete; +- (void)rpcTriggerBackup:(NSArray*)backupPeers complete:(void (^)(NSError *error))complete; +- (void)rpcTriggerRingUpdate:(void (^)(NSError *error))complete; + @end #endif diff --git a/keychain/SecureObjectSync/SOSUserKeygen.m b/keychain/SecureObjectSync/SOSUserKeygen.m index 5e466ae7..a8ab22b3 100644 --- a/keychain/SecureObjectSync/SOSUserKeygen.m +++ b/keychain/SecureObjectSync/SOSUserKeygen.m @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -197,8 +196,8 @@ CFDataRef SOSUserKeyCreateGenerateParameters(CFErrorRef *error) { size_t iterations = ITERATIONMIN; size_t keysize = 256; - if(CCRandomCopyBytes(kCCRandomDefault, salt, sizeof(salt)) != kCCSuccess) { - SOSCreateError(kSOSErrorProcessingFailure, CFSTR("CCRandomCopyBytes failed"), NULL, error); + if (SecRandomCopyBytes(NULL, sizeof(salt), salt) != 0) { + SOSCreateError(kSOSErrorProcessingFailure, CFSTR("SecRandomCopyBytes failed"), NULL, error); return NULL; } @@ -213,7 +212,7 @@ CFDataRef SOSUserKeyCreateGenerateParameters(CFErrorRef *error) { CFReleaseNull(result); if (result) { - secnotice("circleOps", "Created new parameters: iterations %zd, keysize %zd: %@", iterations, keysize, result); + debugDumpUserParameters(CFSTR("SOSUserKeyCreateGenerateParameters created new parameters:"), result); } return result; @@ -259,7 +258,7 @@ SecKeyRef SOSUserKeygen(CFDataRef password, CFDataRef parameters, CFErrorRef *er ccec_const_cp_t cp = ccec_get_cp(keysize); ccec_full_ctx_decl_cp(cp, tmpkey); - secnotice("circleOps", "Generating key for: iterations %zd, keysize %zd: %@", iterations, keysize, parameters); + debugDumpUserParameters(CFSTR("SOSUserKeygen generating key for:"), parameters); size_t drbg_output_size=128; uint8_t drbg_output[drbg_output_size]; @@ -297,51 +296,28 @@ void debugDumpUserParameters(CFStringRef message, CFDataRef parameters) CF_RETURNS_RETAINED CFStringRef UserParametersDescription(CFDataRef parameters){ - __block CFStringRef description = NULL; - CFDataRef newParameters = NULL; - SecKeyRef newKey = NULL; - - CFErrorRef error = NULL; - const uint8_t *parse_end = der_decode_cloud_parameters(kCFAllocatorDefault, kSecECDSAAlgorithmID, - &newKey, &newParameters, &error, - CFDataGetBytePtr(parameters), CFDataGetPastEndPtr(parameters)); - - if (parse_end != CFDataGetPastEndPtr(parameters)){ - secdebug("circleOps", "failed to decode cloud parameters"); - CFReleaseNull(newParameters); - CFReleaseNull(newKey); + if(parameters == NULL) { return NULL; } - + __block CFStringRef description = NULL; size_t saltlen = 0; const uint8_t *salt = NULL; - size_t iterations = 0; size_t keysize = 0; - const uint8_t *der = CFDataGetBytePtr(newParameters); - const uint8_t *der_end = der + CFDataGetLength(newParameters); + const uint8_t *der = CFDataGetBytePtr(parameters); + const uint8_t *der_end = der + CFDataGetLength(parameters); der = der_decode_pbkdf2_params(&saltlen, &salt, &iterations, &keysize, der, der_end); - if (der != NULL) { + if (der != der_end) { secdebug("circleOps", "failed to decode pbkdf2 params"); - CFReleaseNull(newParameters); - CFReleaseNull(newKey); return NULL; } - - CFStringRef userPubKeyID = SOSCopyIDOfKeyWithLength(newKey, 8, NULL); - + BufferPerformWithHexString(salt, 4, ^(CFStringRef saltHex) { // Only dump 4 bytes worth of salthex - CFDataPerformWithHexString(newParameters, ^(CFStringRef parametersHex) { - description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(" "), iterations, keysize, saltHex, userPubKeyID); - }); + description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), iterations, keysize, saltHex); }); - - CFReleaseNull(newParameters); - CFReleaseNull(newKey); - CFReleaseNull(userPubKeyID); - + return description; } diff --git a/keychain/SecureObjectSync/SOSViews.m b/keychain/SecureObjectSync/SOSViews.m index 4098335d..0b785687 100644 --- a/keychain/SecureObjectSync/SOSViews.m +++ b/keychain/SecureObjectSync/SOSViews.m @@ -306,6 +306,26 @@ CFSetRef SOSViewCreateSetFromBitmask(uint64_t bitmask) { return retval; } +bool SOSPeerInfoSupportsCKKSForAll(SOSPeerInfoRef peerInfo) { + if(!peerInfo) { + return false; + } + + bool ret = false; + CFBooleanRef value = SOSPeerInfoV2DictionaryCopyBoolean(peerInfo, sCKKSForAll); + + if(value) { + ret = CFBooleanGetValue(value) ? true : false; + } + + CFReleaseNull(value); + return ret; +} + +void SOSPeerInfoSetSupportsCKKSForAll(SOSPeerInfoRef peerInfo, bool supports) { + return SOSPeerInfoV2DictionarySetValue(peerInfo, sCKKSForAll, supports ? kCFBooleanTrue : kCFBooleanFalse); +} + const char *SOSViewsXlateAction(SOSViewActionCode action) { switch(action) { case kSOSCCViewEnable: return "kSOSCCViewEnable"; diff --git a/keychain/SecureObjectSync/Tool/accountCirclesViewsPrint.m b/keychain/SecureObjectSync/Tool/accountCirclesViewsPrint.m index 9cdf7d3a..b9d0db31 100644 --- a/keychain/SecureObjectSync/Tool/accountCirclesViewsPrint.m +++ b/keychain/SecureObjectSync/Tool/accountCirclesViewsPrint.m @@ -149,7 +149,8 @@ static void printPeerInfos(char *label, CFStringRef mypeerID, CFArrayRef (^copyP CFStringRef bufstr = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); CFStringRef pid = SOSPeerInfoGetPeerID(peer); CFIndex vers = SOSPeerInfoGetVersion(peer); - printmsg(CFSTR("%@ pid:%@ V%d OS:%@\n"), bufstr, pid, vers, osVersion ?: CFSTR("")); + bool isCKKSForAll = SOSPeerInfoSupportsCKKSForAll(peer); + printmsg(CFSTR("%@ pid:%@ V%d %@ OS:%@\n"), bufstr, pid, vers, isCKKSForAll ? CFSTR("c4a") : CFSTR("SOS"), osVersion ?: CFSTR("")); CFRelease(bufstr); CFReleaseNull(gestalt); diff --git a/keychain/SecureObjectSync/Tool/keychain_sync.m b/keychain/SecureObjectSync/Tool/keychain_sync.m index 5cb4adc9..e545b84e 100644 --- a/keychain/SecureObjectSync/Tool/keychain_sync.m +++ b/keychain/SecureObjectSync/Tool/keychain_sync.m @@ -489,7 +489,7 @@ keychain_sync(int argc, char * const *argv) CFMutableArrayRef peers2remove = NULL; SOSLogSetOutputTo(NULL, NULL); - while ((ch = getopt_long(argc, argv, "ab:deikmorv:NCDLOP:RT:UWV05", longopts, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "ab:deikmorv:NCDLOP:RT:UWV05", longopts, NULL)) != -1) { switch (ch) { case 'a': { @@ -635,10 +635,25 @@ keychain_sync(int argc, char * const *argv) } break; } + case 0: + { + if (action == SYNC_REMOVE_PEER) { + CFStringRef optstr = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); + if (peers2remove == NULL) { + peers2remove = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + CFArrayAppendValue(peers2remove, optstr); + CFReleaseNull(optstr); + } else { + return SHOW_USAGE_MESSAGE; + } + break; + } case '?': default: return SHOW_USAGE_MESSAGE; } + } if (peers2remove != NULL) { hadError = !doRemovePeers(peers2remove, &error); diff --git a/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.h b/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.h index 1930811b..c381e08a 100644 --- a/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.h +++ b/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.h @@ -15,9 +15,9 @@ __attribute__((visibility("hidden"))) @interface SOSAccountConfiguration : PBCodable { NSMutableArray *_pendingBackupPeers; - BOOL _sbdBackup; + BOOL _ringUpdateFlag; struct { - int sbdBackup:1; + int ringUpdateFlag:1; } _has; } @@ -29,8 +29,8 @@ __attribute__((visibility("hidden"))) - (NSString *)pendingBackupPeersAtIndex:(NSUInteger)idx; + (Class)pendingBackupPeersType; -@property (nonatomic) BOOL hasSbdBackup; -@property (nonatomic) BOOL sbdBackup; +@property (nonatomic) BOOL hasRingUpdateFlag; +@property (nonatomic) BOOL ringUpdateFlag; // Performs a shallow copy into other - (void)copyTo:(SOSAccountConfiguration *)other; diff --git a/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.m b/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.m index f394355f..be89bc72 100644 --- a/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.m +++ b/keychain/SecureObjectSync/generated_source/SOSAccountConfiguration.m @@ -38,6 +38,20 @@ { return [NSString class]; } +@synthesize ringUpdateFlag = _ringUpdateFlag; +- (void)setRingUpdateFlag:(BOOL)v +{ + _has.ringUpdateFlag = YES; + _ringUpdateFlag = v; +} +- (void)setHasRingUpdateFlag:(BOOL)f +{ + _has.ringUpdateFlag = f; +} +- (BOOL)hasRingUpdateFlag +{ + return _has.ringUpdateFlag != 0; +} - (NSString *)description { @@ -51,6 +65,10 @@ { [dict setObject:self->_pendingBackupPeers forKey:@"pendingBackupPeers"]; } + if (self->_has.ringUpdateFlag) + { + [dict setObject:[NSNumber numberWithBool:self->_ringUpdateFlag] forKey:@"ringUpdateFlag"]; + } return dict; } @@ -79,6 +97,12 @@ BOOL SOSAccountConfigurationReadFrom(__unsafe_unretained SOSAccountConfiguration } } break; + case 2 /* ringUpdateFlag */: + { + self->_has.ringUpdateFlag = YES; + self->_ringUpdateFlag = PBReaderReadBOOL(reader); + } + break; default: if (!PBReaderSkipValueWithTag(reader, tag, aType)) return NO; @@ -101,6 +125,13 @@ BOOL SOSAccountConfigurationReadFrom(__unsafe_unretained SOSAccountConfiguration PBDataWriterWriteStringField(writer, s_pendingBackupPeers, 1); } } + /* ringUpdateFlag */ + { + if (self->_has.ringUpdateFlag) + { + PBDataWriterWriteBOOLField(writer, self->_ringUpdateFlag, 2); + } + } } - (void)copyTo:(SOSAccountConfiguration *)other @@ -114,6 +145,11 @@ BOOL SOSAccountConfigurationReadFrom(__unsafe_unretained SOSAccountConfiguration [other addPendingBackupPeers:[self pendingBackupPeersAtIndex:i]]; } } + if (self->_has.ringUpdateFlag) + { + other->_ringUpdateFlag = _ringUpdateFlag; + other->_has.ringUpdateFlag = YES; + } } - (id)copyWithZone:(NSZone *)zone @@ -124,6 +160,11 @@ BOOL SOSAccountConfigurationReadFrom(__unsafe_unretained SOSAccountConfiguration NSString *vCopy = [v copyWithZone:zone]; [copy addPendingBackupPeers:vCopy]; } + if (self->_has.ringUpdateFlag) + { + copy->_ringUpdateFlag = _ringUpdateFlag; + copy->_has.ringUpdateFlag = YES; + } return copy; } @@ -133,6 +174,8 @@ BOOL SOSAccountConfigurationReadFrom(__unsafe_unretained SOSAccountConfiguration return [other isMemberOfClass:[self class]] && ((!self->_pendingBackupPeers && !other->_pendingBackupPeers) || [self->_pendingBackupPeers isEqual:other->_pendingBackupPeers]) + && + ((self->_has.ringUpdateFlag && other->_has.ringUpdateFlag && ((self->_ringUpdateFlag && other->_ringUpdateFlag) || (!self->_ringUpdateFlag && !other->_ringUpdateFlag))) || (!self->_has.ringUpdateFlag && !other->_has.ringUpdateFlag)) ; } @@ -141,6 +184,8 @@ BOOL SOSAccountConfigurationReadFrom(__unsafe_unretained SOSAccountConfiguration return 0 ^ [self->_pendingBackupPeers hash] + ^ + (self->_has.ringUpdateFlag ? PBHashInt((NSUInteger)self->_ringUpdateFlag) : 0) ; } @@ -150,6 +195,11 @@ BOOL SOSAccountConfigurationReadFrom(__unsafe_unretained SOSAccountConfiguration { [self addPendingBackupPeers:iter_pendingBackupPeers]; } + if (other->_has.ringUpdateFlag) + { + self->_ringUpdateFlag = other->_ringUpdateFlag; + self->_has.ringUpdateFlag = YES; + } } @end diff --git a/keychain/SecurityUnitTests/SecItemTests.m b/keychain/SecurityUnitTests/SecItemTests.m index 998dc16b..efcb1e2c 100644 --- a/keychain/SecurityUnitTests/SecItemTests.m +++ b/keychain/SecurityUnitTests/SecItemTests.m @@ -68,7 +68,7 @@ attrs = [self addGenericPassword:@"delete-me" service:@"delete-me"]; XCTAssertNotNil(attrs, "should create genp"); - XCTAssertEqual(attrs[@"OSStatus"], @(errSecDuplicateItem), "should have duplicate item"); + XCTAssertEqual([attrs[@"OSStatus"] integerValue], errSecDuplicateItem, "should have duplicate item"); } @@ -80,7 +80,7 @@ attrs = [self addGenericPassword:@"delete-me" service:@"delete-me"]; XCTAssertNotNil(attrs, "should create genp"); - XCTAssertEqual(attrs[@"OSStatus"], @(errSecDuplicateItem), "should have duplicate item"); + XCTAssertEqual([attrs[@"OSStatus"] integerValue], errSecDuplicateItem, "should have duplicate item"); XCTAssertEqual([self moveGenericPassword:@"delete-me" service:@"delete-me" newAccount:@"delete-me2" newService:@"delete-me2"], diff --git a/keychain/SecurityUnitTests/SecKeyTests.m b/keychain/SecurityUnitTests/SecKeyTests.m index 97348ac5..98966270 100644 --- a/keychain/SecurityUnitTests/SecKeyTests.m +++ b/keychain/SecurityUnitTests/SecKeyTests.m @@ -28,16 +28,34 @@ @implementation SecKeyTests -- (void)testSecKeyAttributesCanBeReadWithMatchingStringsAsKeys -{ +- (void)testSecKeyAttributesCanBeReadWithMatchingStringsAsKeys { CFMutableDictionaryRef keyParameters = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(keyParameters, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom); CFDictionarySetValue(keyParameters, kSecAttrKeySizeInBits, (__bridge CFNumberRef)@(384)); CFDictionarySetValue(keyParameters, CFSTR("nleg"), kCFBooleanTrue); SecKeyRef secKey = SecKeyCreateRandomKey(keyParameters, nil); NSDictionary* attributes = (__bridge_transfer NSDictionary*)SecKeyCopyAttributes(secKey); - XCTAssertEqual(attributes[(__bridge NSString*)kSecAttrKeySizeInBits], attributes[@"bsiz"], @"the SecKey attributes dictionary value of 'kSecAttrKeySizeInBits' and 'bsiz' are not the same"); + XCTAssertEqualObjects(attributes[(__bridge NSString*)kSecAttrKeySizeInBits], attributes[@"bsiz"], @"the SecKey attributes dictionary value of 'kSecAttrKeySizeInBits' and 'bsiz' are not the same"); XCTAssertNotNil(attributes[@"bsiz"], @"the SecKey attributes dictionary value for 'bsiz' is nil"); } +- (void)testECIESDecryptBadInputData { + NSData *message = [@"message" dataUsingEncoding:NSUTF8StringEncoding]; + NSError *error; + id privKey = CFBridgingRelease(SecKeyCreateRandomKey((CFDictionaryRef)@{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom, (id)kSecAttrKeySizeInBits: @256}, (void *)&error)); + XCTAssertNotNil(privKey, @"key generation failed: %@", error); + id pubKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privKey)); + XCTAssertNotNil(pubKey); + NSData *ciphertext = CFBridgingRelease(SecKeyCreateEncryptedData((SecKeyRef)pubKey, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)message, (void *)&error)); + XCTAssertNotNil(ciphertext, @"Encryption failed: %@", error); + NSData *plaintext = CFBridgingRelease(SecKeyCreateDecryptedData((SecKeyRef)privKey, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)ciphertext, (void *)&error)); + XCTAssertEqualObjects(message, plaintext, @"Decryption did not provide original message"); + + // Strip tag from ciphertext + NSData *strippedCiphertext = [ciphertext subdataWithRange:NSMakeRange(0, ciphertext.length - 16)]; + NSData *failedDecrypted = CFBridgingRelease(SecKeyCreateDecryptedData((SecKeyRef)privKey, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)strippedCiphertext, (void *)&error)); + XCTAssertNil(failedDecrypted, @"Decryption of malformed data did not fail"); + XCTAssertEqual(error.code, errSecParam, @"Unexpected error code provided"); +} + @end diff --git a/keychain/SigninMetrics/OctagonSignPosts.h b/keychain/SigninMetrics/OctagonSignPosts.h index 34c07c65..b6a06b8d 100644 --- a/keychain/SigninMetrics/OctagonSignPosts.h +++ b/keychain/SigninMetrics/OctagonSignPosts.h @@ -38,8 +38,16 @@ typedef struct octagon_signpost_s { } OctagonSignpost; #define OctagonSignpostNamePerformEscrowRecovery "OctagonSignpostNamePerformEscrowRecovery" +#define OctagonSignpostNamePerformSilentEscrowRecovery "OctagonSignpostNamePerformSilentEscrowRecovery" #define OctagonSignpostNamePerformRecoveryFromSBD "OctagonSignpostNamePerformRecoveryFromSBD" -#define OctagonSignpostNamePerformBottleRecovery "OctagonSignpostNamePerformBottleRecovery" + +#define OctagonSignpostNameRecoverWithCDPContext "OctagonSignpostNameRecoverWithCDPContext" +#define OctagonSignpostNameRecoverSilentWithCDPContext "OctagonSignpostNameRecoverSilentWithCDPContext" +#define OctagonSignpostNamePerformOctagonJoinForSilent "OctagonSignpostNamePerformOctagonJoinForSilent" +#define OctagonSignpostNamePerformOctagonJoinForNonSilent "OctagonSignpostNamePerformOctagonJoinForNonSilent" + + +#define OctagonSignpostNamePerformOctagonJoin "OctagonSignpostNamePerformOctagonJoin" #define OctagonSignpostNamePerformResetAndEstablishAfterFailedBottle "OctagonSignpostNamePerformResetAndEstablishAfterFailedBottle" #define OctagonSignpostNameFetchEgoPeer "OctagonSignpostNameFetchEgoPeer" #define OctagonSignpostNameEstablish "OctagonSignpostNameEstablish" @@ -61,11 +69,13 @@ typedef struct octagon_signpost_s { #define OctagonSignpostNameRequestToJoinCircle "OctagonSignpostNameRequestToJoinCircle" #define OctagonSignpostNameAccountUserKeyAvailable "OctagonSignpostNameAccountUserKeyAvailable" #define OctagonSignpostNameFindOptimalBottleIDsWithContextData "OctagonSignpostNameFindOptimalBottleIDsWithContextData" +#define OctagonSignpostNameFetchEscrowRecords "OctagonSignpostNameFetchEscrowRecords" #define OctagonSignpostNameFetchEscrowContents "OctagonSignpostNameFetchEscrowContents" #define OctagonSignpostNameSetNewRecoveryKeyWithData "OctagonSignpostNameSetNewRecoveryKeyWithData" #define OctagonSignpostNameRecoverOctagonUsingData "OctagonSignpostNameRecoverOctagonUsingData" #define OctagonSignpostNamePerformedCDPStateMachineRun "OctagonSignpostNamePerformedCDPStateMachineRun" #define OctagonSignpostNameWaitForOctagonUpgrade "OctagonSignpostNameWaitForOctagonUpgrade" +#define OctagonSignpostNameGetAccountInfo "OctagonSignpostNameGetAccountInfo" #define SOSSignpostNameAssertUserCredentialsAndOptionalDSID "SOSSignpostNameAssertUserCredentialsAndOptionalDSID" #define SOSSignpostNameSOSCCTryUserCredentials "SOSSignpostNameSOSCCTryUserCredentials" diff --git a/keychain/SigninMetrics/SFSignInAnalytics.h b/keychain/SigninMetrics/SFSignInAnalytics.h deleted file mode 100644 index 2863a4d3..00000000 --- a/keychain/SigninMetrics/SFSignInAnalytics.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2017 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@ - */ - -#if __OBJC2__ -#ifndef SignInAnalytics_h -#define SignInAnalytics_h - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface SFSignInAnalytics : NSObject - -@property (readonly) NSString* eventName; -@property (readonly) NSString* category; -@property (readonly) BOOL stopped; - -/* - abstract: creates a new SignInAnalytics object, automatically starts a timer for this task. - uuid: iCloud sign in transaction UUID - category: name of client subsystem. This will be used as the category name when logging - eventName: name of the event we are measuring - */ -- (instancetype _Nullable)initWithSignInUUID:(NSString *)uuid category:(NSString *)category eventName:(NSString*)eventName; -- (instancetype)init NS_UNAVAILABLE; - -/* - abstract: creates a new SignInAnalytics that starts a timer for the subtask. - ideal for fine grained timing of sub events and automatically creates a dependency chain. - eventNmae: name of the event being timed - */ -- (SFSignInAnalytics* _Nullable)newSubTaskForEvent:(NSString*)eventName; - -/* - abstract: call to log when a recoverable error occurs during sign in - error: error that occured during iCloud Sign in - */ -- (void)logRecoverableError:(NSError*)error; - -/* - abstract: call to log when a unrecoverable error occurs during sign in - error: error that occured during iCloud Sign in - */ -- (void)logUnrecoverableError:(NSError*)error; - -/* - abstract: call to cancel the timer object. - */ -- (void)cancel; - -/* - abstract: call to stop a timer and log the time spent. - eventName: subsystem name - attributes: a dictionary containing event attributes - */ -- (void)stopWithAttributes:(NSDictionary* _Nullable)attributes; - -/* - abstract: call to signal iCloud sign in has finished. - */ -- (void)signInCompleted; - -@end -NS_ASSUME_NONNULL_END -#endif /* SignInAnalytics_h */ -#endif diff --git a/keychain/SigninMetrics/SFSignInAnalytics.m b/keychain/SigninMetrics/SFSignInAnalytics.m deleted file mode 100644 index 3b079c97..00000000 --- a/keychain/SigninMetrics/SFSignInAnalytics.m +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (c) 2017 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@ - */ - -#if __OBJC2__ - -#import "SFSignInAnalytics.h" -#import "SFSignInAnalytics+Internal.h" - -#import -#import "Analytics/SFAnalyticsDefines.h" -#import "Analytics/SFAnalyticsSQLiteStore.h" -#import "Analytics/SFAnalytics.h" - -#import -#import -#import -#import "utilities/debugging.h" -#import - -//metrics database location -NSString* signinMetricsDatabase = @"signin_metrics"; - -//defaults write results location -static NSString* const SFSignInAnalyticsDumpLoggedResultsToLocation = @"/tmp/signin_results.txt"; -static NSString* const SFSignInAnalyticsPersistedEventList = @"/tmp/signin_eventlist"; - -//analytics constants -static NSString* const SFSignInAnalyticsAttributeRecoverableError = @"recoverableError"; -static NSString* const SFSignInAnalyticsAttributeErrorDomain = @"errorDomain"; -static NSString* const SFSignInAnalyticsAttributeErrorCode = @"errorCode"; -static NSString* const SFSignInAnalyticsAttributeErrorChain = @"errorChain"; -static NSString* const SFSignInAnalyticsAttributeParentUUID = @"parentUUID"; -static NSString* const SFSignInAnalyticsAttributeMyUUID = @"myUUID"; -static NSString* const SFSignInAnalyticsAttributeSignInUUID = @"signinUUID"; -static NSString* const SFSignInAnalyticsAttributeEventName = @"eventName"; -static NSString* const SFSignInAnalyticsAttributeSubsystemName = @"subsystemName"; -static NSString* const SFSignInAnalyticsAttributeBuiltDependencyChains = @"dependencyChains"; -static NSString* const SFSignInAnalyticsAttributeTrackerTime = @"trackerTime"; - -@implementation SFSIALoggerObject -+ (NSString*)databasePath { - return [SFSIALoggerObject defaultAnalyticsDatabasePath:signinMetricsDatabase]; -} - -+ (instancetype)logger -{ - return [super logger]; -} -@end - - -@interface SFSignInAnalytics () -@property (nonatomic, copy) NSString *signin_uuid; -@property (nonatomic, copy) NSString *my_uuid; -@property (nonatomic, copy) NSString *parent_uuid; -@property (nonatomic, copy) NSString *category; -@property (nonatomic, copy) NSString *eventName; -@property (nonatomic, copy) NSString *persistencePath; - -@property (nonatomic, strong) NSURL *persistedEventPlist; -@property (nonatomic, strong) NSMutableDictionary *eventDependencyList; -@property (nonatomic, strong) NSMutableArray *builtDependencyChains; - -@property (nonatomic) BOOL canceled; -@property (nonatomic) BOOL stopped; - -@property (nonatomic, strong) os_log_t logObject; - -@property (nonatomic, strong) NSNumber *measurement; - -@property (nonatomic, strong) dispatch_queue_t queue; - -@property (nonatomic, strong) SFSignInAnalytics *root; -@property (nonatomic, strong) SFAnalyticsActivityTracker *tracker; - --(os_log_t) newLogForCategoryName:(NSString*) category; --(os_log_t) logForCategoryName:(NSString*) category; - -@end - -static NSMutableDictionary *logObjects; -static const NSString* signInLogSpace = @"com.apple.security.wiiss"; - -@implementation SFSignInAnalytics - -+ (BOOL)supportsSecureCoding { - return YES; -} - --(os_log_t) logForCategoryName:(NSString*) category -{ - return logObjects[category]; -} - --(os_log_t) newLogForCategoryName:(NSString*) category -{ - return os_log_create([signInLogSpace UTF8String], [category UTF8String]); -} - -- (BOOL)writeDependencyList:(NSError**)error -{ - NSError *localError = nil; - if (![NSPropertyListSerialization propertyList: self.root.eventDependencyList isValidForFormat: NSPropertyListXMLFormat_v1_0]){ - os_log_error(self.logObject, "can't save PersistentState as XML"); - return false; - } - - NSData *data = [NSPropertyListSerialization dataWithPropertyList: self.root.eventDependencyList - format: NSPropertyListXMLFormat_v1_0 options: 0 error: &localError]; - if (data == nil){ - os_log_error(self.logObject, "error serializing PersistentState to xml: %@", localError); - return false; - } - - BOOL writeStatus = [data writeToURL:self.root.persistedEventPlist options: NSDataWritingAtomic error: &localError]; - if (!writeStatus){ - os_log_error(self.logObject, "error writing PersistentState to file: %@", localError); - } - if(localError && error){ - *error = localError; - } - - return writeStatus; -} - -- (instancetype)initWithSignInUUID:(NSString *)uuid category:(NSString *)category eventName:(NSString*)eventName -{ - self = [super init]; - if (self) { - _signin_uuid = uuid; - - _my_uuid = uuid; - _parent_uuid = uuid; - _eventName = eventName; - _category = category; - _root = self; - _canceled = NO; - _stopped = NO; - _builtDependencyChains = [NSMutableArray array]; - - if ([self writeResultsToTmp]) { - //make plist file containing uuid parent/child - _persistencePath = [NSString stringWithFormat:@"%@-%@.plist", SFSignInAnalyticsPersistedEventList, eventName]; - _persistedEventPlist = [NSURL fileURLWithPath:_persistencePath isDirectory:NO]; - } - - _eventDependencyList = [NSMutableDictionary dictionary]; - [_eventDependencyList setObject:[NSMutableArray array] forKey:_signin_uuid]; - - _tracker = [[SFSIALoggerObject logger] logSystemMetricsForActivityNamed:eventName withAction:nil]; - [_tracker start]; - - NSError* error = nil; - - if(self.root.persistedEventPlist && ![self writeDependencyList:&error] ){ - os_log(self.logObject, "attempting to write dependency list: %@", error); - } - - _queue = dispatch_queue_create("com.apple.security.SignInAnalytics", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - logObjects = [NSMutableDictionary dictionary]; - }); - @synchronized(logObjects){ - if(category){ - _logObject = [self logForCategoryName:category]; - - if(!_logObject){ - _logObject = [self newLogForCategoryName:category]; - [logObjects setObject:_logObject forKey:category]; - } - } - } - } - return self; -} - --(instancetype) initChildWithSignInUUID:(NSString*)uuid andCategory:(NSString*)category andEventName:(NSString*)eventName -{ - self = [super init]; - if (self) { - _signin_uuid = uuid; - - _my_uuid = uuid; - _parent_uuid = uuid; - _eventName = eventName; - _category = category; - _canceled = NO; - } - return self; -} - -- (void)encodeWithCoder:(NSCoder *)coder { - [coder encodeObject:_signin_uuid forKey:@"UUID"]; - [coder encodeObject:_category forKey:@"category"]; - [coder encodeObject:_parent_uuid forKey:@"parentUUID"]; - [coder encodeObject:_my_uuid forKey:@"myUUID"]; - [coder encodeObject:_measurement forKey:@"measurement"]; - [coder encodeObject:_eventName forKey:@"eventName"]; -} - -- (nullable instancetype)initWithCoder:(NSCoder *)decoder -{ - self = [super init]; - if (self) { - _signin_uuid = [decoder decodeObjectOfClass:[NSString class] forKey:@"UUID"]; - _category = [decoder decodeObjectOfClass:[NSString class] forKey:@"category"]; - _parent_uuid = [decoder decodeObjectOfClass:[NSString class] forKey:@"parentUUID"]; - _my_uuid = [decoder decodeObjectOfClass:[NSString class] forKey:@"myUUID"]; - _measurement = [decoder decodeObjectOfClass:[NSString class] forKey:@"measurement"]; - _eventName = [decoder decodeObjectOfClass:[NSString class] forKey:@"eventName"]; - _queue = dispatch_queue_create("com.apple.security.SignInAnalytics", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - - if(_signin_uuid == nil || - _category == nil || - _parent_uuid == nil){ - [decoder failWithError:[NSError errorWithDomain:@"securityd" code:errSecDecode userInfo:@{NSLocalizedDescriptionKey: @"Failed to decode SignInAnalytics object"}]]; - return nil; - } - } - return self; -} - -- (SFSignInAnalytics*)newSubTaskForEvent:(NSString*)eventName -{ - SFSignInAnalytics *newSubTask = [[SFSignInAnalytics alloc] initChildWithSignInUUID:self.signin_uuid andCategory:self.category andEventName:self.eventName]; - if(newSubTask){ - newSubTask.my_uuid = [NSUUID UUID].UUIDString; - newSubTask.parent_uuid = self.my_uuid; - newSubTask.signin_uuid = self.signin_uuid; - - newSubTask.category = self.category; - newSubTask.eventName = [eventName copy]; - newSubTask.root = self.root; - newSubTask.canceled = NO; - newSubTask.stopped = NO; - - newSubTask.queue = dispatch_queue_create("com.apple.security.SignInAnalytics", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - newSubTask.tracker = [[SFSIALoggerObject logger] logSystemMetricsForActivityNamed:eventName withAction:nil]; - [newSubTask.tracker start]; - - @synchronized(_eventDependencyList){ - NSMutableArray *parentEntry = [newSubTask.root.eventDependencyList objectForKey:newSubTask.parent_uuid]; - - //add new subtask entry to parent event's list - [parentEntry addObject:newSubTask.my_uuid]; - [newSubTask.root.eventDependencyList setObject:parentEntry forKey:newSubTask.parent_uuid]; - - //create new array list for this new subtask incase it has subtasks - [newSubTask.root.eventDependencyList setObject:[NSMutableArray array] forKey:newSubTask.my_uuid]; - NSError* error = nil; - if(self.root.persistedEventPlist && ![newSubTask writeDependencyList:&error] ){ - os_log(self.logObject, "attempting to write dependency list: %@", error); - } - } - } - - return newSubTask; -} - -- (void)logRecoverableError:(NSError*)error -{ - - if (error == nil){ - os_log_error(self.logObject, "attempting to log a nil error for event:%@", self.eventName); - return; - } - - os_log_error(self.logObject, "%@", error); - - NSMutableDictionary* eventAttributes = [NSMutableDictionary dictionary]; - - [eventAttributes setValuesForKeysWithDictionary:@{ - SFSignInAnalyticsAttributeRecoverableError : @(YES), - SFSignInAnalyticsAttributeErrorDomain : error.domain, - SFSignInAnalyticsAttributeErrorCode : @(error.code), - SFSignInAnalyticsAttributeMyUUID : self.my_uuid, - SFSignInAnalyticsAttributeParentUUID : self.parent_uuid, - SFSignInAnalyticsAttributeSignInUUID : self.signin_uuid, - SFSignInAnalyticsAttributeEventName : self.eventName, - SFSignInAnalyticsAttributeSubsystemName : self.category - }]; - - [[SFSIALoggerObject logger] logSoftFailureForEventNamed:self.eventName withAttributes:eventAttributes]; - -} - -- (void)logUnrecoverableError:(NSError*)error -{ - if (error == nil){ - os_log_error(self.logObject, "attempting to log a nil error for event:%@", self.eventName); - return; - } - - os_log_error(self.logObject, "%@", error); - - NSMutableDictionary* eventAttributes = [NSMutableDictionary dictionary]; - - [eventAttributes setValuesForKeysWithDictionary:@{ - SFSignInAnalyticsAttributeRecoverableError : @(NO), - SFSignInAnalyticsAttributeErrorDomain : error.domain, - SFSignInAnalyticsAttributeErrorCode : @(error.code), - SFSignInAnalyticsAttributeMyUUID : self.my_uuid, - SFSignInAnalyticsAttributeParentUUID : self.parent_uuid, - SFSignInAnalyticsAttributeSignInUUID : self.signin_uuid, - SFSignInAnalyticsAttributeEventName : self.eventName, - SFSignInAnalyticsAttributeSubsystemName : self.category - }]; - - [[SFSIALoggerObject logger] logHardFailureForEventNamed:self.eventName withAttributes:eventAttributes]; -} - --(void)cancel -{ - dispatch_sync(self.queue, ^{ - [self.tracker cancel]; - self.canceled = YES; - os_log(self.logObject, "canceled timer for %@", self.eventName); - }); -} - -- (void)stopWithAttributes:(NSDictionary*)attributes -{ - dispatch_sync(self.queue, ^{ - - if(self.canceled || self.stopped){ - return; - } - - self.stopped = YES; - - [self.tracker stop]; - - NSMutableDictionary *mutableAttributes = nil; - - if(attributes){ - mutableAttributes = [NSMutableDictionary dictionaryWithDictionary:attributes]; - } - else{ - mutableAttributes = [NSMutableDictionary dictionary]; - } - mutableAttributes[SFSignInAnalyticsAttributeMyUUID] = self.my_uuid; - mutableAttributes[SFSignInAnalyticsAttributeParentUUID] = self.parent_uuid; - mutableAttributes[SFSignInAnalyticsAttributeSignInUUID] = self.signin_uuid; - mutableAttributes[SFSignInAnalyticsAttributeEventName] = self.eventName; - mutableAttributes[SFSignInAnalyticsAttributeSubsystemName] = self.category; - mutableAttributes[SFSignInAnalyticsAttributeTrackerTime] = self.tracker.measurement; - - [mutableAttributes enumerateKeysAndObjectsUsingBlock:^(NSString* key, id obj, BOOL * stop) { - os_log(self.logObject, "event: %@, %@ : %@", self.eventName, key, obj); - }]; - - [[SFSIALoggerObject logger] logSuccessForEventNamed:self.eventName]; - [[SFSIALoggerObject logger] logSoftFailureForEventNamed:self.eventName withAttributes:mutableAttributes]; - }); -} - --(BOOL) writeResultsToTmp { - - bool shouldWriteResultsToTemp = NO; - CFBooleanRef toTmp = (CFBooleanRef)CFPreferencesCopyValue(CFSTR("DumpResultsToTemp"), - CFSTR("com.apple.security"), - kCFPreferencesAnyUser, kCFPreferencesAnyHost); - if(toTmp && CFGetTypeID(toTmp) == CFBooleanGetTypeID()){ - if(toTmp == kCFBooleanFalse){ - os_log(self.logObject, "writing results to splunk"); - shouldWriteResultsToTemp = NO; - } - if(toTmp == kCFBooleanTrue){ - os_log(self.logObject, "writing results to /tmp"); - shouldWriteResultsToTemp = YES; - } - } - - CFReleaseNull(toTmp); - return shouldWriteResultsToTemp; -} - -- (void)processEventChainForUUID:(NSString*)uuid dependencyChain:(NSString*)dependencyChain -{ - NSString* newChain = dependencyChain; - - NSArray* children = [self.root.eventDependencyList objectForKey:uuid]; - for (NSString* child in children) { - newChain = [NSString stringWithFormat:@"%@, %@", dependencyChain, child]; - [self processEventChainForUUID:child dependencyChain:newChain]; - } - if([children count] == 0){ - [self.root.builtDependencyChains addObject:newChain]; - os_log(self.logObject, "current dependency chain list: %@", newChain); - } -} - -- (void)signInCompleted -{ - //print final - os_log(self.logObject, "sign in complete"); - NSError* error = nil; - - //create dependency chains and log them - [self processEventChainForUUID:self.root.my_uuid dependencyChain:self.root.signin_uuid]; - //write to database - if([self.root.builtDependencyChains count] > 0){ - NSDictionary* eventAttributes = @{SFSignInAnalyticsAttributeBuiltDependencyChains : self.root.builtDependencyChains}; - [[SFSIALoggerObject logger] logSoftFailureForEventNamed:SFSignInAnalyticsAttributeBuiltDependencyChains withAttributes:eventAttributes]; - } - - if([self writeResultsToTmp]){ //writing sign in analytics to /tmp - os_log(self.logObject, "logging to /tmp"); - - NSData* eventData = [NSKeyedArchiver archivedDataWithRootObject:[[SFSIALoggerObject logger].database allEvents] requiringSecureCoding:YES error:&error]; - if(eventData){ - [eventData writeToFile:SFSignInAnalyticsDumpLoggedResultsToLocation options:0 error:&error]; - - if(error){ - os_log_error(self.logObject, "error writing to file [%@], error:%@", SFSignInAnalyticsDumpLoggedResultsToLocation, error); - }else{ - os_log(self.logObject, "successfully wrote sign in analytics to:%@", SFSignInAnalyticsDumpLoggedResultsToLocation); - } - }else{ - os_log_error(self.logObject, "collected no data"); - } - - }else{ //writing to splunk - os_log(self.logObject, "logging to splunk"); - } - - if (self.persistencePath) { - //remove dependency list - BOOL removedPersistedDependencyList = [[NSFileManager defaultManager] removeItemAtPath:self.persistencePath error:&error]; - if(!removedPersistedDependencyList || error){ - os_log(self.logObject, "encountered error when attempting to remove persisted event list: %@", error); - } - } -} - -@end -#endif - diff --git a/keychain/SigninMetrics/tests/SFSignInAnalyticsTests.m b/keychain/SigninMetrics/tests/SFSignInAnalyticsTests.m deleted file mode 100644 index b52d9b4e..00000000 --- a/keychain/SigninMetrics/tests/SFSignInAnalyticsTests.m +++ /dev/null @@ -1,514 +0,0 @@ -/* - * Copyright (c) 2017 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@ - */ - -#import -#import "keychain/SigninMetrics/SFSignInAnalytics.h" -#import "keychain/SigninMetrics/SFSignInAnalytics+Internal.h" -#import "keychain/ot/OTDefines.h" -#import "SFAnalytics+Signin.h" -#import - -static NSInteger _testnum; -static NSString* _path; - -@interface SFSignInAnalyticsTester : SFSignInAnalytics --(instancetype)init; -@end - -@implementation SFSignInAnalyticsTester - -+ (NSString*)databasePath { - return _path; -} - --(instancetype)init -{ - self = [super initWithSignInUUID:[NSUUID UUID].UUIDString category:@"CoreCDP" eventName:@"signin"]; - - return self; -} - -@end - - -@interface SignInAnalyticsTests : XCTestCase -@property (nonatomic) SFSignInAnalyticsTester *metric; -@end - -@implementation SignInAnalyticsTests - - -- (void)setUp { - [super setUp]; - _testnum = 0; - self.continueAfterFailure = NO; - _path = [@"/tmp" stringByAppendingFormat:@"/test_%ld.db", (long)++_testnum]; - _metric = [[SFSignInAnalyticsTester alloc] init]; - XCTAssertNotNil(_metric, "SignInAnalyticsTester object should not be nil"); -} - -- (void)tearDown -{ - dispatch_async([SFSIALoggerObject logger].queue, ^{ - [[SFSIALoggerObject logger].database executeSQL:@"delete from all_events"]; - [[SFSIALoggerObject logger].database executeSQL:@"delete from soft_failures"]; - [[SFSIALoggerObject logger].database executeSQL:@"delete from hard_failures"]; - }); - - [[SFSIALoggerObject logger] removeState]; - _metric = nil; - [super tearDown]; -} - -- (void)testStop -{ - sleep(2); - NSDictionary *attributes = @{@"success": @YES, - @"takenFlow" : @"restore", - }; - XCTAssertNotNil(attributes, "attributes dictionary should exist"); - - [_metric stopWithAttributes:attributes]; - - NSArray* results = [[SFSIALoggerObject logger].database allEvents]; - - XCTAssertEqual([results count], 2, @"should have 2 results"); - -} - -- (void)testCancel -{ - [_metric cancel]; -} - -- (void)testLogError -{ - NSError* error = [NSError errorWithDomain:OctagonErrorDomain code:OTErrorBottleID userInfo:@{NSLocalizedDescriptionKey: @"Failed to deserialize bottle peer"}]; - [_metric logRecoverableError:error]; - NSArray* results = [[SFSIALoggerObject logger].database softFailures]; - XCTAssertEqual([results count], 1, @"should have 1 results"); -} - -- (void)testCreateNewSubtask -{ - SFSignInAnalytics* child = [_metric newSubTaskForEvent:@"restore"]; - XCTAssertNotNil(child, "child should be created"); - [[SFSIALoggerObject logger] removeState]; - child = nil; -} - - -- (void)testCreateNewSubtaskAndStop -{ - SFSignInAnalytics* child = [_metric newSubTaskForEvent:@"restore"]; - - sleep(2); - NSDictionary *attributes = @{@"success": @YES, - @"takenFlow" : @"piggyback", - }; - - [child stopWithAttributes:attributes]; - - XCTAssertNotNil(child, "child should be created"); - - NSArray* results = [[SFSIALoggerObject logger].database allEvents]; - - XCTAssertEqual([results count], 2, @"should have 2 results"); - - [[SFSIALoggerObject logger] removeState]; - child = nil; -} - -- (void)testStopAfterCancel -{ - sleep(2); - NSDictionary *attributes = @{@"success": @YES, - @"takenFlow" : @"piggyback", - }; - XCTAssertNotNil(attributes, "attributes dictionary should exist"); - - [_metric cancel]; - - [_metric stopWithAttributes:attributes]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - - XCTAssertEqual([allEvents count], 0, @"should have 0 things logged"); -} - -- (void)testStopAfterStop -{ - sleep(2); - NSDictionary *attributes = @{@"success": @YES, - @"takenFlow" : @"piggyback", - }; - XCTAssertNotNil(attributes, "attributes dictionary should exist"); - - [_metric stopWithAttributes:attributes]; - - [_metric stopWithAttributes:attributes]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - - XCTAssertEqual([allEvents count], 2, @"should have 2 things logged"); -} - --(void)testSignInComplete -{ - NSDictionary* attributes = [NSDictionary dictionary]; - [_metric stopWithAttributes:attributes]; - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array should not be nil"); - XCTAssertTrue(allEvents && [allEvents count] > 0, "array should not be nil and contain an entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - XCTAssertTrue(dependencyEntry && [dependencyEntry count] > 0, "dictionary should not be nil and contain an entry"); - - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - - XCTAssertEqual([chains count], 1, "should be one list"); - - XCTAssertTrue([chains containsObject:_metric.signin_uuid], "should contain 1 uuid"); -} - --(void)testSingleChainDependencyList -{ - SFSignInAnalytics* child1 = [_metric newSubTaskForEvent:@"piggyback"]; - XCTAssertNotNil(child1, "child1 should be created"); - - SFSignInAnalytics* child2 = [child1 newSubTaskForEvent:@"initialsync"]; - XCTAssertNotNil(child2, "child2 should be created"); - - SFSignInAnalytics* child3 = [child2 newSubTaskForEvent:@"backup"]; - XCTAssertNotNil(child3, "child3 should be created"); - - SFSignInAnalytics* child4 = [child3 newSubTaskForEvent:@"processing one ring"]; - XCTAssertNotNil(child4, "child4 should be created"); - - [_metric signInCompleted]; - - NSString *expectedChain = [NSString stringWithFormat:@"%@, %@, %@, %@, %@", child1.signin_uuid, child1.my_uuid, child2.my_uuid, child3.my_uuid, child4.my_uuid]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "should not be nil"); - XCTAssertTrue([allEvents count] > 0, "should be events"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - - XCTAssertEqual([chains count], 1, "should be one list"); - XCTAssertTrue([expectedChain isEqualToString:[chains objectAtIndex:0]], "chains should be the same"); - - child1 = nil; - child2 = nil; - child3 = nil; - child4 = nil; - - child1 = nil; - child2 = nil; - child3 = nil; - child4 = nil; -} - --(void)testMultipleChildrenPerEvent -{ - SFSignInAnalytics* child1 = [_metric newSubTaskForEvent:@"piggyback"]; - XCTAssertNotNil(child1, "child1 should be created"); - - SFSignInAnalytics* child2 = [child1 newSubTaskForEvent:@"initialsync"]; - XCTAssertNotNil(child2, "child2 should be created"); - - SFSignInAnalytics* child3 = [child1 newSubTaskForEvent:@"backup"]; - XCTAssertNotNil(child3, "child3 should be created"); - - SFSignInAnalytics* child4 = [child1 newSubTaskForEvent:@"processing one ring"]; - XCTAssertNotNil(child4, "child4 should be created"); - - SFSignInAnalytics* child5 = [child2 newSubTaskForEvent:@"processing second ring"]; - XCTAssertNotNil(child5, "child5 should be created"); - - SFSignInAnalytics* child6 = [child2 newSubTaskForEvent:@"processing third ring"]; - XCTAssertNotNil(child6, "child6 should be created"); - - SFSignInAnalytics* child7 = [child2 newSubTaskForEvent:@"processing fourth ring"]; - XCTAssertNotNil(child7, "child7 should be created"); - - SFSignInAnalytics* child8 = [child7 newSubTaskForEvent:@"processing fifth ring"]; - XCTAssertNotNil(child8, "child8 should be created"); - - SFSignInAnalytics* child9 = [child7 newSubTaskForEvent:@"processing one ring"]; - XCTAssertNotNil(child9, "child9 should be created"); - - NSString *expectedChain = [NSString stringWithFormat:@"%@, %@, %@, %@", _metric.signin_uuid, child1.my_uuid, child2.my_uuid, child5.my_uuid]; - - NSString *expectedChain1 = [NSString stringWithFormat:@"%@, %@, %@", _metric.signin_uuid, child1.my_uuid, child3.my_uuid]; - - NSString *expectedChain2 = [NSString stringWithFormat:@"%@, %@, %@", _metric.signin_uuid, child1.my_uuid, child4.my_uuid]; - - NSString *expectedChain3 = [NSString stringWithFormat:@"%@, %@, %@, %@", _metric.signin_uuid, child1.my_uuid, child2.my_uuid, child5.my_uuid]; - - NSString *expectedChain4 = [NSString stringWithFormat:@"%@, %@, %@, %@, %@", _metric.signin_uuid, child1.my_uuid, child2.my_uuid, child7.my_uuid, child8.my_uuid]; - - NSString *expectedChain5 = [NSString stringWithFormat:@"%@, %@, %@, %@, %@", _metric.signin_uuid, child1.my_uuid, child2.my_uuid, child7.my_uuid, child9.my_uuid]; - - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertTrue([allEvents count] > 0, "array should not be empty"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - - XCTAssertEqual([chains count], 6, "should be one list"); - - XCTAssertTrue([chains containsObject:expectedChain], "chains should contain expectedChain"); - XCTAssertTrue([chains containsObject:expectedChain1], "chains should contain expectedChain1"); - XCTAssertTrue([chains containsObject:expectedChain2], "chains should contain expectedChain2"); - XCTAssertTrue([chains containsObject:expectedChain3], "chains should contain expectedChain3"); - XCTAssertTrue([chains containsObject:expectedChain4], "chains should contain expectedChain4"); - XCTAssertTrue([chains containsObject:expectedChain5], "chains should contain expectedChain5"); - - [[SFSIALoggerObject logger] removeState]; - - child1 = nil; - child2 = nil; - child3 = nil; - child4 = nil; - child5 = nil; - child6 = nil; - child7 = nil; - child8 = nil; - child9 = nil; - -} - --(void)testSOSCCWaitForInitialSync -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - bool worked = SOSCCWaitForInitialSyncWithAnalytics(parentData, &error); - XCTAssertTrue(worked, "should have worked"); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCRemoveThisDeviceFromCircle -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - bool worked = SOSCCRemoveThisDeviceFromCircleWithAnalytics(parentData, &error); - XCTAssertTrue(worked, "should have worked"); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCRequestToJoinCircle -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - SOSCCRequestToJoinCircleWithAnalytics(parentData, &error); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCRequestToJoinCircleAfterRestore -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - SOSCCRequestToJoinCircleAfterRestoreWithAnalytics(parentData, &error); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCRemovePeersFromCircle -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - NSArray* peers = [NSArray array]; - SOSCCRemovePeersFromCircleWithAnalytics((__bridge CFArrayRef)peers, parentData, &error); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - - --(void)testSOSCCViewSet -{ - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - CFSetRef enabledViews = nil; - CFSetRef disabledViews = nil; - SOSCCViewSetWithAnalytics(enabledViews, disabledViews, parentData); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCSetUserCredentialsAndDSID -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - CFStringRef label = nil; - CFDataRef password = nil; - CFStringRef dsid = nil; - SOSCCSetUserCredentialsAndDSIDWithAnalytics(label, password, dsid, parentData, &error); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - --(void)testSOSCCResetToEmpty -{ - CFErrorRef error = nil; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; - XCTAssertNotNil(archiver, "should not be nil"); - [_metric encodeWithCoder:archiver]; - CFDataRef parentData = (__bridge CFDataRef)archiver.encodedData; - XCTAssertNotNil((__bridge NSData*)parentData, "should not be nil"); - SOSCCResetToEmptyWithAnalytics(parentData, &error); - - [_metric signInCompleted]; - - NSArray *allEvents = [[SFSIALoggerObject logger].database allEvents]; - XCTAssertNotNil(allEvents, "array is not nil"); - XCTAssertEqual([allEvents count], 1, "array should not contain 1 entry"); - - NSDictionary *dependencyEntry = [allEvents objectAtIndex:[allEvents count]-1]; - NSArray *chains = [dependencyEntry objectForKey:@"dependencyChains"]; - XCTAssertNotNil(chains, "chains is not nil"); - XCTAssertEqual([chains count], 1, "array should not contain 1 entry"); -} - -- (void)testMultipleDBConnections -{ - NSError* error = [NSError errorWithDomain:OctagonErrorDomain code:OTErrorBottleID userInfo:@{NSLocalizedDescriptionKey: @"Failed to deserialize bottle peer"}]; - dispatch_queue_t test_queue = dispatch_queue_create("com.apple.security.signin.tests", DISPATCH_QUEUE_CONCURRENT_WITH_AUTORELEASE_POOL); - - for(int i = 0; i < 1000; i++){ - SFSignInAnalytics *test1 = [_metric newSubTaskForEvent:@"connection1"]; - SFSignInAnalytics *test2 = [_metric newSubTaskForEvent:@"connection2"]; - - dispatch_async(test_queue, ^{ - [test1 logRecoverableError:error]; - }); - dispatch_async(test_queue, ^{ - [test2 stopWithAttributes:nil]; - }); - dispatch_async(test_queue, ^{ - [self->_metric logRecoverableError:error]; - }); - } -} -@end diff --git a/keychain/Trieste/OctagonTestHarnessXPCService/SecRemoteDevice.m b/keychain/Trieste/OctagonTestHarnessXPCService/SecRemoteDevice.m index db9d9914..b19065e8 100644 --- a/keychain/Trieste/OctagonTestHarnessXPCService/SecRemoteDevice.m +++ b/keychain/Trieste/OctagonTestHarnessXPCService/SecRemoteDevice.m @@ -67,8 +67,7 @@ - (instancetype)initAsInitiator:(bool)initiator version:(KCPairingChannelContext *)peerVersionContext device:(SecRemoteDevice *)device { - self = [super init]; - if (self) { + if ((self = [super init])) { self.remoteVersionContext = peerVersionContext; self.initiator = initiator; self.device = device; @@ -135,7 +134,7 @@ - (void)sosCircleStatus:(void(^)(SOSCCStatus status, NSError *error))complete { - SOSCloudKeychainFlush(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef __unused returnedValues, CFErrorRef __unused sync_error) { + SOSCloudKeychainFlush(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(CFDictionaryRef __unused returnedValues, CFErrorRef __unused sync_error) { CFErrorRef cferror = NULL; SOSCCStatus status = SOSCCThisDeviceIsInCircle(&cferror); complete(status, (__bridge NSError *)cferror); @@ -145,7 +144,7 @@ - (void)sosCircleStatusNonCached:(void(^)(SOSCCStatus status, NSError *error))complete { - SOSCloudKeychainFlush(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef __unused returnedValues, CFErrorRef __unused sync_error) { + SOSCloudKeychainFlush(dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0), ^(CFDictionaryRef __unused returnedValues, CFErrorRef __unused sync_error) { CFErrorRef cferror = NULL; SOSCCStatus status = SOSCCThisDeviceIsInCircleNonCached(&cferror); complete(status, (__bridge NSError *)cferror); diff --git a/keychain/Trieste/OctagonTriesteTests/Tests/OctagonTriesteTests/OctagonTests.swift b/keychain/Trieste/OctagonTriesteTests/Tests/OctagonTriesteTests/OctagonTests.swift index 9689ecae..b63671b2 100644 --- a/keychain/Trieste/OctagonTriesteTests/Tests/OctagonTriesteTests/OctagonTests.swift +++ b/keychain/Trieste/OctagonTriesteTests/Tests/OctagonTriesteTests/OctagonTests.swift @@ -16,7 +16,6 @@ extension CDAIOSDevice { } final class OctagonTests: CDTTestCase { - let username: String? = nil let password: String? = nil var signedIn: Bool = false @@ -111,7 +110,6 @@ final class OctagonTests: CDTTestCase { } func compareCKKSZone(name zone: String, status1: NSDictionary, status2: NSDictionary) -> Bool { - let zone1 = status1[zone] as! NSDictionary let zone2 = status2[zone] as! NSDictionary @@ -136,7 +134,6 @@ final class OctagonTests: CDTTestCase { } func compareCKKSStatus(c1: NSDictionary, c2: NSDictionary) -> Bool { - let status1 = c1["status"] as! NSDictionary let status2 = c2["status"] as! NSDictionary @@ -165,7 +162,6 @@ final class OctagonTests: CDTTestCase { func sosApplication(_ device: CDAIOSDevice, verbose: Bool = false) throws { if self.password != nil { - print("submitting application\n") let password = try device.executeFile(atPath: securityTool, withArguments: ["sync", "-P", self.password!]) @@ -183,7 +179,6 @@ final class OctagonTests: CDTTestCase { func sosApprove(_ device: CDAIOSDevice, verbose: Bool = false) throws { if self.password != nil { - print("approving applications\n") let password = try device.executeFile(atPath: securityTool, withArguments: ["sync", "-P", self.password!]) diff --git a/keychain/TrustedPeersHelper/BottledPeer/BottledPeer.swift b/keychain/TrustedPeersHelper/BottledPeer/BottledPeer.swift index d18c8a9f..415e5d4b 100644 --- a/keychain/TrustedPeersHelper/BottledPeer/BottledPeer.swift +++ b/keychain/TrustedPeersHelper/BottledPeer/BottledPeer.swift @@ -25,22 +25,21 @@ import Foundation import SecurityFoundation class BottledPeer: NSObject { + var escrowKeys: EscrowKeys + var secret: Data + var peerID: String + var bottleID: String + var peerKeys: OctagonSelfPeerKeys - public var escrowKeys: EscrowKeys - public var secret: Data - public var peerID: String - public var bottleID: String - public var peerKeys: OctagonSelfPeerKeys + var signatureUsingEscrowKey: Data + var signatureUsingPeerKey: Data + var escrowSigningPublicKey: Data + var escrowSigningSPKI: Data + var peersigningSPKI: Data - public var signatureUsingEscrowKey: Data - public var signatureUsingPeerKey: Data - public var escrowSigningPublicKey: Data - public var escrowSigningSPKI: Data - public var peersigningSPKI: Data + var contents: Data - public var contents: Data - - public class func encryptionOperation() -> (_SFAuthenticatedEncryptionOperation) { + class func encryptionOperation() -> (_SFAuthenticatedEncryptionOperation) { let keySpecifier = _SFAESKeySpecifier.init(bitSize: TPHObjectiveC.aes256BitSize()) return _SFAuthenticatedEncryptionOperation.init(keySpecifier: keySpecifier) } @@ -48,8 +47,7 @@ class BottledPeer: NSObject { // Given a peer's details including private key material, and // the keys generated from the escrow secret, encrypt the peer private keys, // make a bottled peer object and serialize it into data. - public init (peerID: String, bottleID: String, peerSigningKey: _SFECKeyPair, peerEncryptionKey: _SFECKeyPair, bottleSalt: String) throws { - + init (peerID: String, bottleID: String, peerSigningKey: _SFECKeyPair, peerEncryptionKey: _SFECKeyPair, bottleSalt: String) throws { let secret = try BottledPeer.makeMeSomeEntropy(requiredLength: Int(OTMasterSecretLength)) self.secret = secret @@ -130,8 +128,7 @@ class BottledPeer: NSObject { // Deserialize a bottle (data) and decrypt the contents (peer keys) // using the keys generated from the escrow secret, and signatures from signing keys - public init (contents: Data, secret: Data, bottleSalt: String, signatureUsingEscrow: Data, signatureUsingPeerKey: Data) throws { - + init (contents: Data, secret: Data, bottleSalt: String, signatureUsingEscrow: Data, signatureUsingPeerKey: Data) throws { self.secret = secret self.escrowKeys = try EscrowKeys(secret: self.secret, bottleSalt: bottleSalt) @@ -210,24 +207,24 @@ class BottledPeer: NSObject { try xso.verify(peerSigned, with: peerPublicKey) } - public func escrowSigningPublicKeyHash() -> String { + func escrowSigningPublicKeyHash() -> String { return TPHObjectiveC.digest(usingSha384: self.escrowSigningPublicKey) } - public class func signingOperation() -> (_SFEC_X962SigningOperation) { + class func signingOperation() -> (_SFEC_X962SigningOperation) { let keySpecifier = _SFECKeySpecifier.init(curve: SFEllipticCurve.nistp384) let digestOperation = _SFSHA384DigestOperation.init() return _SFEC_X962SigningOperation.init(keySpecifier: keySpecifier, digestOperation: digestOperation) } - public class func verifyBottleSignature(data: Data, signature: Data, pubKey: _SFECPublicKey) throws -> (Bool) { + class func verifyBottleSignature(data: Data, signature: Data, pubKey: _SFECPublicKey) throws -> (Bool) { let xso = BottledPeer.signingOperation() let peerSigned = _SFSignedData.init(data: data, signature: signature) try xso.verify(peerSigned, with: pubKey) return true } - public class func makeMeSomeEntropy(requiredLength: Int) throws -> Data { + class func makeMeSomeEntropy(requiredLength: Int) throws -> Data { let bytesPointer = UnsafeMutableRawPointer.allocate(byteCount: requiredLength, alignment: 1) if SecRandomCopyBytes(kSecRandomDefault, requiredLength, bytesPointer) != 0 { @@ -253,7 +250,7 @@ extension BottledPeer { } extension BottledPeer.Error: LocalizedError { - public var errorDescription: String? { + var errorDescription: String? { switch self { case .OTErrorDeserializationFailure: return "Failed to deserialize bottle peer" diff --git a/keychain/TrustedPeersHelper/BottledPeer/EscrowKeys.swift b/keychain/TrustedPeersHelper/BottledPeer/EscrowKeys.swift index 4669d72f..206463d0 100644 --- a/keychain/TrustedPeersHelper/BottledPeer/EscrowKeys.swift +++ b/keychain/TrustedPeersHelper/BottledPeer/EscrowKeys.swift @@ -35,14 +35,14 @@ enum EscrowKeyType: Int { } class EscrowKeys: NSObject { - public var encryptionKey: _SFECKeyPair - public var signingKey: _SFECKeyPair - public var symmetricKey: _SFAESKey + var encryptionKey: _SFECKeyPair + var signingKey: _SFECKeyPair + var symmetricKey: _SFAESKey - public var secret: Data - public var bottleSalt: String + var secret: Data + var bottleSalt: String - public init (secret: Data, bottleSalt: String) throws { + init (secret: Data, bottleSalt: String) throws { self.secret = secret self.bottleSalt = bottleSalt @@ -86,7 +86,6 @@ class EscrowKeys: NSObject { let infoString = Array("Escrow Signing Private Key".utf8) info = Data(bytes: infoString, count: infoString.count) - } guard let cp = ccec_cp_384() else { @@ -122,7 +121,7 @@ class EscrowKeys: NSObject { } else if keyType == EscrowKeyType.kOTEscrowKeyEncryption || keyType == EscrowKeyType.kOTEscrowKeySigning { status = ccec_generate_key_deterministic(cp, derivedKeyBytes.count, derivedKeyBytes.bindMemory(to: UInt8.self).baseAddress!, - ccDRBGGetRngState(), + ccrng(nil), UInt32(CCEC_GENKEY_DETERMINISTIC_FIPS), fullKey) @@ -195,7 +194,6 @@ class EscrowKeys: NSObject { } class func storeEscrowedEncryptionKeyPair(keyData: Data, label: String) throws -> (Bool) { - let query: [CFString: Any] = [ kSecClass: kSecClassKey, kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, @@ -284,15 +282,15 @@ class EscrowKeys: NSObject { let keyTypeData = item[kSecAttrApplicationLabel as CFString] as! Data let keyType = String(data: keyTypeData, encoding: .utf8)! - if keyType.range(of: "Symmetric") != nil { + if keyType.contains("Symmetric") { let keyData = item[kSecValueData as CFString] as! Data let specifier = _SFAESKeySpecifier.init(bitSize: TPHObjectiveC.aes256BitSize()) symmetricKey = try _SFAESKey.init(data: keyData, specifier: specifier) - } else if keyType.range(of: "Encryption") != nil { + } else if keyType.contains("Encryption") { let keyData = item[kSecValueData as CFString] as! Data let encryptionSecKey = try EscrowKeys.createSecKey(keyData: keyData) encryptionKey = _SFECKeyPair.init(secKey: encryptionSecKey) - } else if keyType.range(of: "Signing") != nil { + } else if keyType.contains("Signing") { let keyData = item[kSecValueData as CFString] as! Data let signingSecKey = try EscrowKeys.createSecKey(keyData: keyData) signingKey = _SFECKeyPair.init(secKey: signingSecKey) @@ -314,7 +312,7 @@ enum EscrowKeysError: Error { } extension EscrowKeysError: LocalizedError { - public var errorDescription: String? { + var errorDescription: String? { switch self { case .keyGeneration: return "Key generation failed" @@ -331,12 +329,11 @@ extension EscrowKeysError: LocalizedError { } extension EscrowKeysError: CustomNSError { - - public static var errorDomain: String { + static var errorDomain: String { return "com.apple.security.trustedpeers.EscrowKeys" } - public var errorCode: Int { + var errorCode: Int { switch self { case .keyGeneration: return 1 @@ -351,7 +348,7 @@ extension EscrowKeysError: CustomNSError { } } - public var errorUserInfo: [String: Any] { + var errorUserInfo: [String: Any] { var userInfo: [String: Any] = [:] if let desc = self.errorDescription { userInfo[NSLocalizedDescriptionKey] = desc diff --git a/keychain/TrustedPeersHelper/Client.swift b/keychain/TrustedPeersHelper/Client.swift index 64dfe9f1..a414db52 100644 --- a/keychain/TrustedPeersHelper/Client.swift +++ b/keychain/TrustedPeersHelper/Client.swift @@ -23,6 +23,38 @@ import Foundation +extension Error { + func sanitizeForClientXPC() -> Error { + let nserror = self as NSError + + // CoreData errors might have extra things in them that need removal. + if nserror.domain == NSCocoaErrorDomain { + return nserror.cleanAllButDescription() + } + + // The docs for CKXPCSuitableError say it only returns nil if you pass it nil, but swift can't read those. + guard let ckCleanedError = CKXPCSuitableError(self) else { + return ContainerError.unknownCloudKitError + } + return ckCleanedError + } +} + +extension NSError { + func cleanAllButDescription() -> NSError { + let userInfo: [String: AnyHashable]? + if let description = self.userInfo[NSLocalizedDescriptionKey] as? AnyHashable { + userInfo = [NSLocalizedDescriptionKey: description] + } else { + userInfo = nil + } + + return NSError(domain: self.domain, + code: self.code, + userInfo: userInfo) + } +} + class Client: TrustedPeersHelperProtocol { let endpoint: NSXPCListenerEndpoint? @@ -57,11 +89,11 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.dump { result, error in self.logComplete(function: "Dumping", container: container.name, error: error) - reply(result, CKXPCSuitableError(error)) + reply(result, error?.sanitizeForClientXPC()) } } catch { os_log("Dumping failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + reply(nil, error.sanitizeForClientXPC()) } } @@ -74,11 +106,11 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.dumpEgoPeer { peerID, perm, stable, dyn, error in self.logComplete(function: "Dumping peer", container: container.name, error: error) - reply(peerID, perm, stable, dyn, CKXPCSuitableError(error)) + reply(peerID, perm, stable, dyn, error?.sanitizeForClientXPC()) } } catch { os_log("Dumping peer failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, nil, nil, error.sanitizeForClientXPC()) } } @@ -86,7 +118,9 @@ class Client: TrustedPeersHelperProtocol { do { let containerName = ContainerName(container: container, context: context) let container = try self.containerMap.findOrCreate(name: containerName) - container.trustStatus(reply: reply) + container.trustStatus { egoPeerStatus, error in + reply(egoPeerStatus, error?.sanitizeForClientXPC()) + } } catch { os_log("Trust status failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) reply(TrustedPeersHelperEgoPeerStatus(egoPeerID: nil, @@ -95,7 +129,7 @@ class Client: TrustedPeersHelperProtocol { peerCountsByMachineID: [:], isExcluded: false, isLocked: false), - CKXPCSuitableError(error)) + error.sanitizeForClientXPC()) } } @@ -104,10 +138,12 @@ class Client: TrustedPeersHelperProtocol { let containerName = ContainerName(container: container, context: context) os_log("Fetch Trust State for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.fetchTrustState(reply: reply) + container.fetchTrustState { peerState, peerList, error in + reply(peerState, peerList, error?.sanitizeForClientXPC()) + } } catch { os_log("Fetch Trust State failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, error.sanitizeForClientXPC()) } } @@ -118,10 +154,10 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.reset(resetReason: resetReason) { error in self.logComplete(function: "Resetting", container: container.name, error: error) - reply(CKXPCSuitableError(error)) } + reply(error?.sanitizeForClientXPC()) } } catch { os_log("Resetting failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + reply(error.sanitizeForClientXPC()) } } @@ -132,11 +168,11 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.localReset { error in self.logComplete(function: "Local reset", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { os_log("Local reset failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + reply(error.sanitizeForClientXPC()) } } @@ -151,11 +187,11 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.setAllowedMachineIDs(allowedMachineIDs, honorIDMSListChanges: honorIDMSListChanges) { differences, error in self.logComplete(function: "Setting allowed machineIDs", container: container.name, error: error) - reply(differences, CKXPCSuitableError(error)) + reply(differences, error?.sanitizeForClientXPC()) } } catch { os_log("Setting allowed machineIDs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(false, CKXPCSuitableError(error)) + reply(false, error.sanitizeForClientXPC()) } } @@ -169,11 +205,11 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.addAllow(machineIDs) { error in self.logComplete(function: "Adding allowed machineIDs", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { os_log("Adding allowed machineID failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + reply(error.sanitizeForClientXPC()) } } @@ -187,11 +223,11 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.removeAllow(machineIDs) { error in self.logComplete(function: "Removing allowed machineIDs", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { os_log("Removing allowed machineID failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + reply(error.sanitizeForClientXPC()) } } @@ -202,11 +238,11 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.fetchAllowedMachineIDs { mids, error in self.logComplete(function: "Fetched allowed machineIDs", container: container.name, error: error) - reply(mids, CKXPCSuitableError(error)) + reply(mids, error?.sanitizeForClientXPC()) } } catch { os_log("Fetching allowed machineIDs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + reply(nil, error.sanitizeForClientXPC()) } } @@ -216,11 +252,11 @@ class Client: TrustedPeersHelperProtocol { os_log("retrieving epoch for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.getEgoEpoch { epoch, error in - reply(epoch, CKXPCSuitableError(error)) + reply(epoch, error?.sanitizeForClientXPC()) } } catch { os_log("Epoch retrieval failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(0, CKXPCSuitableError(error)) + reply(0, error.sanitizeForClientXPC()) } } @@ -232,13 +268,14 @@ class Client: TrustedPeersHelperProtocol { bottleID: String, modelID: String, deviceName: String?, - serialNumber: String, + serialNumber: String?, osVersion: String, policyVersion: TPPolicyVersion?, policySecrets: [String: Data]?, + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus, signingPrivKeyPersistentRef: Data?, encPrivKeyPersistentRef: Data?, - reply: @escaping (String?, Data?, Data?, Data?, Data?, Set?, TPPolicy?, Error?) -> Void) { + reply: @escaping (String?, Data?, Data?, Data?, Data?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) os_log("Preparing new identity for %{public}@", log: tplogDebug, type: .default, containerName.description) @@ -253,14 +290,15 @@ class Client: TrustedPeersHelperProtocol { osVersion: osVersion, policyVersion: policyVersion, policySecrets: policySecrets, + syncUserControllableViews: syncUserControllableViews, signingPrivateKeyPersistentRef: signingPrivKeyPersistentRef, - encryptionPrivateKeyPersistentRef: encPrivKeyPersistentRef) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, views, policy, error in + encryptionPrivateKeyPersistentRef: encPrivKeyPersistentRef) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, policy, error in self.logComplete(function: "Prepare", container: container.name, error: error) - reply(peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, views, policy, CKXPCSuitableError(error)) + reply(peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, policy, error?.sanitizeForClientXPC()) } } catch { os_log("Prepare failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, nil, nil, nil, nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, nil, nil, nil, nil, error.sanitizeForClientXPC()) } } @@ -269,19 +307,19 @@ class Client: TrustedPeersHelperProtocol { ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], preapprovedKeys: [Data]?, - reply: @escaping (String?, [CKRecord]?, Error?) -> Void) { + reply: @escaping (String?, [CKRecord]?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) os_log("Establishing %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.establish(ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, error in + preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in self.logComplete(function: "Establishing", container: container.name, error: error) - reply(peerID, keyHierarchyRecords, CKXPCSuitableError(error)) } + reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC()) } } catch { os_log("Establishing failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, nil, error.sanitizeForClientXPC()) } } @@ -305,27 +343,27 @@ class Client: TrustedPeersHelperProtocol { stableInfoSig: stableInfoSig, ckksKeys: ckksKeys) { voucher, voucherSig, error in self.logComplete(function: "Vouching", container: container.name, error: error) - reply(voucher, voucherSig, CKXPCSuitableError(error)) } + reply(voucher, voucherSig, error?.sanitizeForClientXPC()) } } catch { os_log("Vouching failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, error.sanitizeForClientXPC()) } } func preflightVouchWithBottle(withContainer container: String, context: String, bottleID: String, - reply: @escaping (String?, Set?, TPPolicy?, Error?) -> Void) { + reply: @escaping (String?, TPSyncingPolicy?, Bool, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) os_log("Preflight Vouch With Bottle %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.preflightVouchWithBottle(bottleID: bottleID) { peerID, viewSet, policy, error in + container.preflightVouchWithBottle(bottleID: bottleID) { peerID, policy, refetched, error in self.logComplete(function: "Preflight Vouch With Bottle", container: container.name, error: error) - reply(peerID, viewSet, policy, CKXPCSuitableError(error)) } + reply(peerID, policy, refetched, error?.sanitizeForClientXPC()) } } catch { os_log("Preflighting Vouch With Bottle failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, false, error.sanitizeForClientXPC()) } } @@ -342,28 +380,28 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.vouchWithBottle(bottleID: bottleID, entropy: entropy, bottleSalt: bottleSalt, tlkShares: tlkShares) { voucher, voucherSig, uniqueTLKsRecovered, totalTLKSharesRecovered, error in self.logComplete(function: "Vouching With Bottle", container: container.name, error: error) - reply(voucher, voucherSig, uniqueTLKsRecovered, totalTLKSharesRecovered, CKXPCSuitableError(error)) } + reply(voucher, voucherSig, uniqueTLKsRecovered, totalTLKSharesRecovered, error?.sanitizeForClientXPC()) } } catch { os_log("Vouching with Bottle failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, 0, 0, CKXPCSuitableError(error)) + reply(nil, nil, 0, 0, error.sanitizeForClientXPC()) } } func preflightVouchWithRecoveryKey(withContainer container: String, - context: String, - recoveryKey: String, - salt: String, - reply: @escaping (String?, Set?, TPPolicy?, Error?) -> Void) { + context: String, + recoveryKey: String, + salt: String, + reply: @escaping (String?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) os_log("Preflight Vouch With RecoveryKey %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.preflightVouchWithRecoveryKey(recoveryKey: recoveryKey, salt: salt) { rkID, viewSet, policy, error in + container.preflightVouchWithRecoveryKey(recoveryKey: recoveryKey, salt: salt) { rkID, policy, error in self.logComplete(function: "Preflight Vouch With RecoveryKey", container: container.name, error: error) - reply(rkID, viewSet, policy, CKXPCSuitableError(error)) } + reply(rkID, policy, error?.sanitizeForClientXPC()) } } catch { os_log("Preflighting Vouch With RecoveryKey failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, error.sanitizeForClientXPC()) } } @@ -379,10 +417,10 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.vouchWithRecoveryKey(recoveryKey: recoveryKey, salt: salt, tlkShares: tlkShares) { voucher, voucherSig, error in self.logComplete(function: "Vouching With Recovery Key", container: container.name, error: error) - reply(voucher, voucherSig, CKXPCSuitableError(error)) } + reply(voucher, voucherSig, error?.sanitizeForClientXPC()) } } catch { os_log("Vouching with Recovery Key failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, error.sanitizeForClientXPC()) } } @@ -392,8 +430,8 @@ class Client: TrustedPeersHelperProtocol { voucherSig: Data, ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data], - reply: @escaping (String?, [CKRecord]?, Set?, TPPolicy?, Error?) -> Void) { + preapprovedKeys: [Data]?, + reply: @escaping (String?, [CKRecord]?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) os_log("Joining %{public}@", log: tplogDebug, type: .default, containerName.description) @@ -402,27 +440,27 @@ class Client: TrustedPeersHelperProtocol { voucherSig: voucherSig, ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, views, policy, error in - reply(peerID, keyHierarchyRecords, views, policy, CKXPCSuitableError(error)) - + preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in + reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC()) } } catch { os_log("Joining failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, nil, error.sanitizeForClientXPC()) } } func preflightPreapprovedJoin(withContainer container: String, context: String, + preapprovedKeys: [Data]?, reply: @escaping (Bool, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) os_log("Attempting to preflight a preapproved join for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.preflightPreapprovedJoin { success, error in reply(success, CKXPCSuitableError(error)) } + container.preflightPreapprovedJoin(preapprovedKeys: preapprovedKeys) { success, error in reply(success, error?.sanitizeForClientXPC()) } } catch { os_log("preflightPreapprovedJoin failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(false, CKXPCSuitableError(error)) + reply(false, error.sanitizeForClientXPC()) } } @@ -430,19 +468,19 @@ class Client: TrustedPeersHelperProtocol { context: String, ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data], - reply: @escaping (String?, [CKRecord]?, Set?, TPPolicy?, Error?) -> Void) { + preapprovedKeys: [Data]?, + reply: @escaping (String?, [CKRecord]?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) os_log("Attempting a preapproved join for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.preapprovedJoin(ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, viewSet, policy, error in - reply(peerID, keyHierarchyRecords, viewSet, policy, CKXPCSuitableError(error)) } + preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in + reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC()) } } catch { os_log("attemptPreapprovedJoin failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, nil, error.sanitizeForClientXPC()) } } @@ -453,19 +491,38 @@ class Client: TrustedPeersHelperProtocol { osVersion: String?, policyVersion: NSNumber?, policySecrets: [String: Data]?, - reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { + syncUserControllableViews: NSNumber?, + reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) os_log("Updating %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) + + let syncUserControllableSetting: TPPBPeerStableInfo_UserControllableViewStatus? + if let value = syncUserControllableViews?.int32Value { + switch value { + case TPPBPeerStableInfo_UserControllableViewStatus.ENABLED.rawValue: + syncUserControllableSetting = .ENABLED + case TPPBPeerStableInfo_UserControllableViewStatus.DISABLED.rawValue: + syncUserControllableSetting = .DISABLED + case TPPBPeerStableInfo_UserControllableViewStatus.FOLLOWING.rawValue: + syncUserControllableSetting = .FOLLOWING + default: + throw ContainerError.unknownSyncUserControllableViewsValue(value: value) + } + } else { + syncUserControllableSetting = nil + } + container.update(deviceName: deviceName, serialNumber: serialNumber, osVersion: osVersion, policyVersion: policyVersion?.uint64Value, - policySecrets: policySecrets) { state, error in reply(state, CKXPCSuitableError(error)) } + policySecrets: policySecrets, + syncUserControllableViews: syncUserControllableSetting) { state, policy, error in reply(state, policy, error?.sanitizeForClientXPC()) } } catch { os_log("update failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + reply(nil, nil, error.sanitizeForClientXPC()) } } @@ -477,10 +534,10 @@ class Client: TrustedPeersHelperProtocol { let containerName = ContainerName(container: container, context: context) os_log("setPreapprovedKeysWithContainer %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.set(preapprovedKeys: preapprovedKeys) { state, error in reply(state, CKXPCSuitableError(error)) } + container.set(preapprovedKeys: preapprovedKeys) { state, error in reply(state, error?.sanitizeForClientXPC()) } } catch { os_log("setPreapprovedKeysWithContainer failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + reply(nil, error.sanitizeForClientXPC()) } } @@ -494,11 +551,12 @@ class Client: TrustedPeersHelperProtocol { os_log("Updating TLKs for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.updateTLKs(ckksKeys: ckksKeys, - tlkShares: tlkShares, - reply: reply) + tlkShares: tlkShares) { records, error in + reply(records, error?.sanitizeForClientXPC()) + } } catch { os_log("updateTLKs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + reply(nil, error.sanitizeForClientXPC()) } } @@ -510,11 +568,11 @@ class Client: TrustedPeersHelperProtocol { os_log("Departing %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.departByDistrustingSelf { error in - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { os_log("departByDistrustingSelf failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + reply(error.sanitizeForClientXPC()) } } @@ -527,11 +585,11 @@ class Client: TrustedPeersHelperProtocol { os_log("Distrusting %{public}@ in %{public}@", log: tplogDebug, type: .default, peerIDs, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.distrust(peerIDs: peerIDs) { error in - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { os_log("distrustPeerIDs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + reply(error.sanitizeForClientXPC()) } } @@ -541,11 +599,24 @@ class Client: TrustedPeersHelperProtocol { os_log("fetchViableBottles in %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.fetchViableBottles { sortedBottleIDs, partialBottleIDs, error in - reply(sortedBottleIDs, partialBottleIDs, CKXPCSuitableError(error)) + reply(sortedBottleIDs, partialBottleIDs, error?.sanitizeForClientXPC()) } } catch { os_log("fetchViableBottles failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, error.sanitizeForClientXPC()) + } + } + + func fetchViableEscrowRecords(withContainer container: String, context: String, forceFetch: Bool, reply: @escaping ([Data]?, Error?) -> Void) { + do { + let containerName = ContainerName(container: container, context: context) + os_log("fetchViableEscrowRecords in %@", log: tplogDebug, type: .default, containerName.description) + let container = try self.containerMap.findOrCreate(name: containerName) + container.fetchEscrowRecords(forceFetch: forceFetch) { recordDatas, error in + reply(recordDatas, error?.sanitizeForClientXPC()) + } + } catch { + reply(nil, error.sanitizeForClientXPC()) } } @@ -555,27 +626,28 @@ class Client: TrustedPeersHelperProtocol { os_log("fetchEscrowContents in %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.fetchEscrowContents { entropy, bottleID, signingPublicKey, error in - reply(entropy, bottleID, signingPublicKey, CKXPCSuitableError(error)) + reply(entropy, bottleID, signingPublicKey, error?.sanitizeForClientXPC()) } } catch { os_log("fetchEscrowContents failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, nil, CKXPCSuitableError(error)) + reply(nil, nil, nil, error.sanitizeForClientXPC()) } } func fetchCurrentPolicy(withContainer container: String, context: String, - reply: @escaping (Set?, TPPolicy?, Error?) -> Void) { + modelIDOverride: String?, + reply: @escaping (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) os_log("Fetching policy+views for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.fetchCurrentPolicy { viewList, policy, error in - reply(viewList, policy, CKXPCSuitableError(error)) + container.fetchCurrentPolicy(modelIDOverride: modelIDOverride) { policy, peersOpinion, error in + reply(policy, peersOpinion, error?.sanitizeForClientXPC()) } } catch { os_log("fetchCurrentPolicy failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, nil, CKXPCSuitableError(error)) + reply(nil, .UNKNOWN, error.sanitizeForClientXPC()) } } @@ -588,11 +660,11 @@ class Client: TrustedPeersHelperProtocol { os_log("Fetching policy documents %{public}@ with versions: %{public}@", log: tplogDebug, type: .default, containerName.description, versions) let container = try self.containerMap.findOrCreate(name: containerName) container.fetchPolicyDocuments(versions: versions) { entries, error in - reply(entries, CKXPCSuitableError(error)) + reply(entries, error?.sanitizeForClientXPC()) } } catch { os_log("fetchPolicyDocuments failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + reply(nil, error.sanitizeForClientXPC()) } } @@ -604,26 +676,31 @@ class Client: TrustedPeersHelperProtocol { let request = ValidatePeersRequest() container.validatePeers(request: request) { result, error in self.logComplete(function: "validatePeers", container: container.name, error: error) - reply(result, CKXPCSuitableError(error)) + reply(result, error?.sanitizeForClientXPC()) } } catch { os_log("ValidatePeers failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + reply(nil, error.sanitizeForClientXPC()) } } - func setRecoveryKeyWithContainer(_ container: String, context: String, recoveryKey: String, salt: String, ckksKeys: [CKKSKeychainBackedKeySet], reply: @escaping (Error?) -> Void) { + func setRecoveryKeyWithContainer(_ container: String, + context: String, + recoveryKey: String, + salt: String, + ckksKeys: [CKKSKeychainBackedKeySet], + reply: @escaping ([CKRecord]?, Error?) -> Void) { do { let containerName = ContainerName(container: container, context: context) os_log("SetRecoveryKey for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) - container.setRecoveryKey(recoveryKey: recoveryKey, salt: salt, ckksKeys: ckksKeys) { error in + container.setRecoveryKey(recoveryKey: recoveryKey, salt: salt, ckksKeys: ckksKeys) { records, error in self.logComplete(function: "setRecoveryKey", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(records, error?.sanitizeForClientXPC()) } } catch { os_log("SetRecoveryKey failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + reply(nil, error.sanitizeForClientXPC()) } } @@ -637,11 +714,11 @@ class Client: TrustedPeersHelperProtocol { } container.reportHealth(request: request) { error in self.logComplete(function: "reportHealth", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { os_log("ReportHealth failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + reply(error.sanitizeForClientXPC()) } } @@ -652,11 +729,11 @@ class Client: TrustedPeersHelperProtocol { let container = try self.containerMap.findOrCreate(name: containerName) container.pushHealthInquiry { error in self.logComplete(function: "pushHealthInquiry", container: container.name, error: error) - reply(CKXPCSuitableError(error)) + reply(error?.sanitizeForClientXPC()) } } catch { os_log("PushHealthInquiry failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(CKXPCSuitableError(error)) + reply(error.sanitizeForClientXPC()) } } @@ -666,26 +743,38 @@ class Client: TrustedPeersHelperProtocol { os_log("Health Check! requiring escrow check? %d for %{public}@", log: tplogDebug, type: .default, requiresEscrowCheck, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.requestHealthCheck(requiresEscrowCheck: requiresEscrowCheck) { postRepair, postEscrow, postReset, leaveTrust, error in - reply(postRepair, postEscrow, postReset, leaveTrust, CKXPCSuitableError(error)) + reply(postRepair, postEscrow, postReset, leaveTrust, error?.sanitizeForClientXPC()) } } catch { os_log("Health Check! failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(false, false, false, false, CKXPCSuitableError(error)) + reply(false, false, false, false, error.sanitizeForClientXPC()) } } func getSupportAppInfo(withContainer container: String, context: String, reply: @escaping (Data?, Error?) -> Void) { - do { + do { let containerName = ContainerName(container: container, context: context) - os_log("getSupportInfo %d for %{public}@", log: tplogDebug, type: .default, containerName.description) + os_log("getSupportAppInfo for %{public}@", log: tplogDebug, type: .default, containerName.description) let container = try self.containerMap.findOrCreate(name: containerName) container.getSupportAppInfo { info, error in - reply(info, CKXPCSuitableError(error)) + reply(info, error?.sanitizeForClientXPC()) } } catch { os_log("getSupportInfo failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) - reply(nil, CKXPCSuitableError(error)) + reply(nil, error.sanitizeForClientXPC()) + } + } + func removeEscrowCache(withContainer container: String, context: String, reply: @escaping (Error?) -> Void) { + do { + let containerName = ContainerName(container: container, context: context) + os_log("removeEscrowCache for %{public}@", log: tplogDebug, type: .default, containerName.description) + let container = try self.containerMap.findOrCreate(name: containerName) + container.removeEscrowCache { error in + reply(error?.sanitizeForClientXPC()) + } + } catch { + os_log("removeEscrowCache failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg) + reply(error.sanitizeForClientXPC()) } - } } diff --git a/keychain/TrustedPeersHelper/Container.swift b/keychain/TrustedPeersHelper/Container.swift index ad1e321b..cd3b61e7 100644 --- a/keychain/TrustedPeersHelper/Container.swift +++ b/keychain/TrustedPeersHelper/Container.swift @@ -22,6 +22,7 @@ */ import CloudKitCode +import CloudKitCodeProtobuf import CoreData import Foundation import os @@ -30,9 +31,14 @@ import SecurityFoundation let tplogDebug = OSLog(subsystem: "com.apple.security.trustedpeers", category: "debug") let tplogTrace = OSLog(subsystem: "com.apple.security.trustedpeers", category: "trace") - let egoIdentitiesAccessGroup = "com.apple.security.egoIdentities" +enum Viability { + case full + case partial + case none +} + extension ResetReason { static func from(cuttlefishResetReason: CuttlefishResetReason) -> ResetReason { switch cuttlefishResetReason { @@ -51,7 +57,7 @@ extension ResetReason { case .testGenerated: return ResetReason.testGenerated @unknown default: - fatalError() + fatalError("unknown reset reason: \(cuttlefishResetReason)") } } } @@ -100,6 +106,9 @@ public enum ContainerError: Error { case unknownSecurityFoundationError case failedToSerializeData case unknownInternalError + case unknownSyncUserControllableViewsValue(value: Int32) + case noPeersPreapprovedBySelf + case peerRegisteredButNotStored(String) } extension ContainerError: LocalizedError { @@ -191,12 +200,17 @@ extension ContainerError: LocalizedError { return "Failed to encode protobuf data" case .unknownInternalError: return "Internal code failed, but didn't return error" + case .unknownSyncUserControllableViewsValue(value: let value): + return "Unknown syncUserControllableViews number: \(value)" + case .noPeersPreapprovedBySelf: + return "No peers preapproved by the local peer" + case .peerRegisteredButNotStored(let s): + return "Peer \(s) not found in database" } } } extension ContainerError: CustomNSError { - public static var errorDomain: String { return "com.apple.security.trustedpeers.container" } @@ -291,6 +305,12 @@ extension ContainerError: CustomNSError { return 44 case .unknownInternalError: return 45 + case .unknownSyncUserControllableViewsValue: + return 46 + case .noPeersPreapprovedBySelf: + return 47 + case .peerRegisteredButNotStored: + return 48 } } @@ -326,7 +346,6 @@ internal func traceError(_ error: Error?) -> String { } func saveSecret(_ secret: Data, label: String) throws { - let query: [CFString: Any] = [ kSecClass: kSecClassInternetPassword, kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, @@ -545,12 +564,19 @@ func makeTLKShares(ckksTLKs: [CKKSKeychainBackedKey]?, asPeer: CKKSSelfPeer, toP throw error } } - }.compactMap { $0 } + } + .compactMap { $0 } } @discardableResult func extract(tlkShares: [CKKSTLKShare], peer: OctagonSelfPeerKeys, model: TPModel) -> (Int64, Int64) { os_log("Attempting to recover %d TLK shares for peer %{public}@", log: tplogDebug, type: .default, tlkShares.count, peer.peerID) + + return extract(tlkShares: tlkShares, peer: peer, sponsorPeerID: nil, model: model) +} + +@discardableResult +func extract(tlkShares: [CKKSTLKShare], peer: OctagonSelfPeerKeys, sponsorPeerID: String?, model: TPModel) -> (Int64, Int64) { var tlksRecovered: Set = Set() var sharesRecovered: Int64 = 0 @@ -563,7 +589,7 @@ func extract(tlkShares: [CKKSTLKShare], peer: OctagonSelfPeerKeys, model: TPMode do { var trustedPeers: [AnyHashable] = [peer] - if let egoPeer = model.peer(withID: peer.peerID) { + if let egoPeer = model.peer(withID: sponsorPeerID ?? peer.peerID) { egoPeer.trustedPeerIDs.forEach { trustedPeerID in if let peer = model.peer(withID: trustedPeerID) { let peerObj = CKKSActualPeer(peerID: trustedPeerID, @@ -601,6 +627,7 @@ struct ContainerState { var peers: [String: TPPeer] = [:] var vouchers: [TPVoucher] = [] var bottles = Set() + var escrowRecords = Set() var recoverySigningKey: Data? var recoveryEncryptionKey: Data? } @@ -611,11 +638,13 @@ internal struct StableChanges { let osVersion: String? let policyVersion: UInt64? let policySecrets: [String: Data]? + let setSyncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus? } // CoreData doesn't handle creating an identical model from an identical URL. Help it out. private var nsObjectModels: [URL: NSManagedObjectModel] = [:] private let nsObjectModelsQueue = DispatchQueue(label: "com.apple.security.TrustedPeersHelper.nsObjectModels") + func getOrMakeModel(url: URL) -> NSManagedObjectModel { return nsObjectModelsQueue.sync { if let model = nsObjectModels[url] { @@ -649,7 +678,7 @@ extension ContainerMO { func egoStableInfo() -> TPPeerStableInfo? { guard let egoStableData = self.egoPeerStableInfo, let egoStableSig = self.egoPeerStableInfoSig else { - return nil + return nil } return TPPeerStableInfo(data: egoStableData, sig: egoStableSig) @@ -678,12 +707,20 @@ class Container: NSObject { // that queue. internal let moc: NSManagedObjectContext + // To facilitate CoreData tear down, we need to keep the PersistentContainer around. + internal let persistentContainer: NSPersistentContainer + // Rather than Container having its own dispatch queue, we use moc's queue // to synchronise access to our own state as well. So the following instance // variables must only be accessed within blocks executed by calling // moc.perform() or moc.performAndWait(). internal var containerMO: ContainerMO internal var model: TPModel + internal var escrowCacheTimeout: TimeInterval + + // Used in tests only. Set when an identity is prepared using a policy version override + internal var policyVersionOverride: TPPolicyVersion? + /** Construct a Container. @@ -704,17 +741,17 @@ class Container: NSObject { // Set up Core Data stack let url = Bundle(for: type(of: self)).url(forResource: "TrustedPeersHelper", withExtension: "momd")! let mom = getOrMakeModel(url: url) - let persistentContainer = NSPersistentContainer(name: "TrustedPeersHelper", managedObjectModel: mom) - persistentContainer.persistentStoreDescriptions = [persistentStoreDescription] + self.persistentContainer = NSPersistentContainer(name: "TrustedPeersHelper", managedObjectModel: mom) + self.persistentContainer.persistentStoreDescriptions = [persistentStoreDescription] - persistentContainer.loadPersistentStores { _, error in + self.persistentContainer.loadPersistentStores { _, error in initError = error } if let initError = initError { throw initError } - let moc = persistentContainer.newBackgroundContext() + let moc = self.persistentContainer.newBackgroundContext() moc.mergePolicy = NSMergePolicy.mergeByPropertyStoreTrump moc.performAndWait { @@ -734,6 +771,9 @@ class Container: NSObject { Container.onqueueUpgradeMachineIDSetToModel(container: containerMO!, moc: moc) Container.onqueueUpgradeMachineIDSetToUseStatus(container: containerMO!, moc: moc) + //remove duplicate vouchers on all the peers + Container.onqueueRemoveDuplicateVouchersPerPeer(container: containerMO!, moc: moc) + model = Container.loadModel(from: containerMO!) Container.ensureEgoConsistency(from: containerMO!, model: model!) try moc.save() @@ -751,9 +791,23 @@ class Container: NSObject { self.containerMO = containerMO! self.cuttlefish = cuttlefish self.model = model! + self.escrowCacheTimeout = 60.0 * 15.0 //15 minutes super.init() } + func deletePersistentStore() throws { + // Call this to entirely destroy the persistent store. + // This container should not be used after this event. + + try self.persistentContainer.persistentStoreDescriptions.forEach { storeDescription in + if let url = storeDescription.url { + try self.moc.persistentStoreCoordinator?.destroyPersistentStore(at: url, + ofType: storeDescription.type, + options: [:]) + } + } + } + // Must be on containerMO's moc queue to call this internal static func loadModel(from containerMO: ContainerMO) -> TPModel { // Populate model from persistent store @@ -804,9 +858,12 @@ class Container: NSObject { } } - if let recoveryKeySigningSPKI = containerMO.recoveryKeySigningSPKI, - let recoveryKeyEncyryptionSPKI = containerMO.recoveryKeyEncryptionSPKI { - model.setRecoveryKeys(TPRecoveryKeyPair(signingSPKI: recoveryKeySigningSPKI, encryptionSPKI: recoveryKeyEncyryptionSPKI)) + os_log("loadModel: loaded %{public}d vouchers", log: tplogDebug, type: .default, model.allVouchers().count) + + // Note: the containerMO objects are misnamed; they are key data, and not SPKI. + if let recoveryKeySigningKeyData = containerMO.recoveryKeySigningSPKI, + let recoveryKeyEncyryptionKeyData = containerMO.recoveryKeyEncryptionSPKI { + model.setRecoveryKeys(TPRecoveryKeyPair(signingKeyData: recoveryKeySigningKeyData, encryptionKeyData: recoveryKeyEncyryptionKeyData)) } else { // If the ego peer has an RK set, tell the model to use that one // This is a hack to work around TPH databases which don't have the RK set on the container due to previously running old software @@ -814,7 +871,7 @@ class Container: NSObject { egoStableInfo.recoverySigningPublicKey.count > 0, egoStableInfo.recoveryEncryptionPublicKey.count > 0 { os_log("loadModel: recovery key not set in model, but is set on ego peer", log: tplogDebug, type: .default) - model.setRecoveryKeys(TPRecoveryKeyPair(signingSPKI: egoStableInfo.recoverySigningPublicKey, encryptionSPKI: egoStableInfo.recoveryEncryptionPublicKey)) + model.setRecoveryKeys(TPRecoveryKeyPair(signingKeyData: egoStableInfo.recoverySigningPublicKey, encryptionKeyData: egoStableInfo.recoveryEncryptionPublicKey)) } } @@ -872,7 +929,6 @@ class Container: NSObject { containerMO.egoPeerStableInfo = modelStableInfo.data containerMO.egoPeerStableInfoSig = modelStableInfo.sig } - } static func dictionaryRepresentation(bottle: BottleMO) -> [String: Any] { @@ -961,7 +1017,6 @@ class Container: NSObject { reply(egoStatus, nil) return } - } else { // With no ego peer ID, either return 'excluded' if there are extant peers, or 'unknown' to signal no peers at all if self.model.allPeerIDs().isEmpty { @@ -1002,7 +1057,7 @@ class Container: NSObject { self.moc.performAndWait { // Knowledge of your peer status only exists if you know about other peers. If you haven't fetched, fetch. if self.containerMO.changeToken == nil { - self.fetchAndPersistChanges { fetchError in + self.onqueueFetchAndPersistChanges { fetchError in guard fetchError == nil else { if let error = fetchError { os_log("Unable to fetch changes, trust status is unknown: %{public}@", log: tplogDebug, type: .default, error as CVarArg) @@ -1037,9 +1092,8 @@ class Container: NSObject { self.moc.performAndWait { if let egoPeerID = self.containerMO.egoPeerID, - let egoPermData = self.containerMO.egoPeerPermanentInfo, - let egoPermSig = self.containerMO.egoPeerPermanentInfoSig { - + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig { let keyFactory = TPECPublicKeyFactory() guard let permanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { os_log("fetchTrustState failed to create TPPeerPermanentInfo", log: tplogDebug, type: .error) @@ -1075,6 +1129,21 @@ class Container: NSObject { os_log("No peer for trusted ID %{public}@", log: tplogDebug, type: .default, trustedPeerID) } } + + if let stableInfo = egoPeer.stableInfo, stableInfo.recoveryEncryptionPublicKey.count > 0, stableInfo.recoverySigningPublicKey.count > 0 { + let recoveryKeyPair = TPRecoveryKeyPair(stableInfo: stableInfo) + + do { + // The RK should have all views. So, claim that it should have all views that this peer has. + let rkViews = try self.model.getViewsForPeer(egoPeer.permanentInfo, + stableInfo: egoPeer.stableInfo) + + tphPeers.append(try RecoveryKey.asPeer(recoveryKeys: recoveryKeyPair, + viewList: rkViews)) + } catch { + os_log("Unable to add RK as a trusted peer: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + } + } } else { os_log("No ego peer in model; no trusted peers", log: tplogDebug, type: .default) } @@ -1094,8 +1163,8 @@ class Container: NSObject { os_log("dump complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) reply($0, $1) - } - self.moc.performAndWait { + } + self.moc.performAndWait { var d: [AnyHashable: Any] = [:] if let egoPeerID = self.containerMO.egoPeerID { @@ -1131,11 +1200,11 @@ class Container: NSObject { } func dumpEgoPeer(reply: @escaping (String?, TPPeerPermanentInfo?, TPPeerStableInfo?, TPPeerDynamicInfo?, Error?) -> Void) { - let reply: (String?, TPPeerPermanentInfo?, TPPeerStableInfo?, TPPeerDynamicInfo?, Error?) -> Void = { - os_log("dumpEgoPeer complete: %{public}@", log: tplogTrace, type: .info, traceError($4)) - reply($0, $1, $2, $3, $4) - } - self.moc.performAndWait { + let reply: (String?, TPPeerPermanentInfo?, TPPeerStableInfo?, TPPeerDynamicInfo?, Error?) -> Void = { + os_log("dumpEgoPeer complete: %{public}@", log: tplogTrace, type: .info, traceError($4)) + reply($0, $1, $2, $3, $4) + } + self.moc.performAndWait { guard let egoPeerID = self.containerMO.egoPeerID else { reply(nil, nil, nil, nil, ContainerError.noPreparedIdentity) return @@ -1159,7 +1228,6 @@ class Container: NSObject { } self.cuttlefish.validatePeers(request) { response, error in - os_log("ValidatePeers(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { os_log("validatePeers failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, error ?? ContainerError.cloudkitResponseMissing) @@ -1188,7 +1256,6 @@ class Container: NSObject { $0.resetReason = resetReason } self.cuttlefish.reset(request) { response, error in - os_log("Reset(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { os_log("reset failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(error ?? ContainerError.cloudkitResponseMissing) @@ -1257,19 +1324,20 @@ class Container: NSObject { bottleID: String, modelID: String, deviceName: String?, - serialNumber: String, + serialNumber: String?, osVersion: String, policyVersion: TPPolicyVersion?, policySecrets: [String: Data]?, + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus, signingPrivateKeyPersistentRef: Data?, encryptionPrivateKeyPersistentRef: Data?, - reply: @escaping (String?, Data?, Data?, Data?, Data?, Set?, TPPolicy?, Error?) -> Void) { + reply: @escaping (String?, Data?, Data?, Data?, Data?, TPSyncingPolicy?, Error?) -> Void) { self.semaphore.wait() - let reply: (String?, Data?, Data?, Data?, Data?, Set?, TPPolicy?, Error?) -> Void = { + let reply: (String?, Data?, Data?, Data?, Data?, TPSyncingPolicy?, Error?) -> Void = { os_log("prepare complete peerID: %{public}@ %{public}@", - log: tplogTrace, type: .info, ($0 ?? "NULL") as CVarArg, traceError($7)) + log: tplogTrace, type: .info, ($0 ?? "NULL") as CVarArg, traceError($6)) self.semaphore.signal() - reply($0, $1, $2, $3, $4, $5, $6, $7) + reply($0, $1, $2, $3, $4, $5, $6) } // Create a new peer identity with random keys, and store the keys in keychain @@ -1287,9 +1355,8 @@ class Container: NSObject { signing: signingKeyPair, encryptionKeyPair: encryptionKeyPair, peerIDHashAlgo: TPHashAlgo.SHA256) - } catch { - reply(nil, nil, nil, nil, nil, nil, nil, error) + reply(nil, nil, nil, nil, nil, nil, error) return } @@ -1306,47 +1373,55 @@ class Container: NSObject { _ = try saveSecret(bottle.secret, label: peerID) } catch { os_log("bottle creation failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, nil, nil, nil, nil, nil, error) + reply(nil, nil, nil, nil, nil, nil, error) return } saveEgoKeyPair(signingKeyPair, identifier: signingKeyIdentifier(peerID: peerID)) { success, error in guard success else { os_log("Unable to save signing key: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") - reply(nil, nil, nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity) + reply(nil, nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity) return } saveEgoKeyPair(encryptionKeyPair, identifier: encryptionKeyIdentifier(peerID: peerID)) { success, error in guard success else { os_log("Unable to save encryption key: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") - reply(nil, nil, nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity) + reply(nil, nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity) return } - let policyVersion = policyVersion ?? prevailingPolicyVersion - self.fetchPolicyDocumentWithSemaphore(version: policyVersion) { policyDoc, policyFetchError in + let actualPolicyVersion = policyVersion ?? prevailingPolicyVersion + self.fetchPolicyDocumentWithSemaphore(version: actualPolicyVersion) { policyDoc, policyFetchError in guard let policyDoc = policyDoc, policyFetchError == nil else { os_log("Unable to fetch policy: %{public}@", log: tplogDebug, type: .default, (policyFetchError as CVarArg?) ?? "error missing") - reply(nil, nil, nil, nil, nil, nil, nil, error ?? ContainerError.unknownInternalError) + reply(nil, nil, nil, nil, nil, nil, error ?? ContainerError.unknownInternalError) return } + if policyVersion != nil { + self.policyVersionOverride = policyDoc.version + } + // Save the prepared identity as containerMO.egoPeer* and its bottle self.moc.performAndWait { do { - - let stableInfo = TPPeerStableInfo(clock: 1, - frozenPolicyVersion: frozenPolicyVersion, - flexiblePolicyVersion: policyDoc.version, - policySecrets: policySecrets, - deviceName: deviceName, - serialNumber: serialNumber, - osVersion: osVersion, - signing: signingKeyPair, - recoverySigningPubKey: nil, - recoveryEncryptionPubKey: nil, - error: nil) - + // Note: the client chooses for syncUserControllableViews here. + // if they pass in UNKNOWN, we'll fix it later at join time, following the peers we trust. + let syncUserViews = syncUserControllableViews.sanitizeForPlatform(permanentInfo: permanentInfo) + + let useFrozenPolicyVersion = policyDoc.version.versionNumber >= frozenPolicyVersion.versionNumber + + let stableInfo = try TPPeerStableInfo(clock: 1, + frozenPolicyVersion: useFrozenPolicyVersion ? frozenPolicyVersion : policyDoc.version, + flexiblePolicyVersion: useFrozenPolicyVersion ? policyDoc.version : nil, + policySecrets: policySecrets, + syncUserControllableViews: syncUserViews, + deviceName: deviceName, + serialNumber: serialNumber, + osVersion: osVersion, + signing: signingKeyPair, + recoverySigningPubKey: nil, + recoveryEncryptionPubKey: nil) self.containerMO.egoPeerID = permanentInfo.peerID self.containerMO.egoPeerPermanentInfo = permanentInfo.data self.containerMO.egoPeerPermanentInfoSig = permanentInfo.sig @@ -1363,14 +1438,14 @@ class Container: NSObject { self.containerMO.addToBottles(bottleMO) - let (syncingViews, policy) = try self.policyAndViewsFor(permanentInfo: permanentInfo, stableInfo: stableInfo) + let syncingPolicy = try self.syncingPolicyFor(modelID: permanentInfo.modelID, stableInfo: stableInfo) try self.moc.save() - reply(permanentInfo.peerID, permanentInfo.data, permanentInfo.sig, stableInfo.data, stableInfo.sig, syncingViews, policy, nil) + reply(permanentInfo.peerID, permanentInfo.data, permanentInfo.sig, stableInfo.data, stableInfo.sig, syncingPolicy, nil) } catch { os_log("Unable to save identity: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, nil, nil, nil, nil, nil, error) + reply(nil, nil, nil, nil, nil, nil, error) } } } @@ -1399,22 +1474,21 @@ class Container: NSObject { func establish(ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], preapprovedKeys: [Data]?, - reply: @escaping (String?, [CKRecord], Error?) -> Void) { + reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) { self.semaphore.wait() - let reply: (String?, [CKRecord], Error?) -> Void = { + let reply: (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void = { os_log("establish complete peer: %{public}@ %{public}@", - log: tplogTrace, type: .default, ($0 ?? "NULL") as CVarArg, traceError($2)) + log: tplogTrace, type: .default, ($0 ?? "NULL") as CVarArg, traceError($3)) self.semaphore.signal() - reply($0, $1, $2) + reply($0, $1, $2, $3) } self.moc.performAndWait { self.onqueueEstablish(ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys, - reply: { peerID, ckrecords, _, _, error in - reply(peerID, ckrecords, error) - }) + preapprovedKeys: preapprovedKeys) { peerID, ckrecords, syncingPolicy, error in + reply(peerID, ckrecords, syncingPolicy, error) + } } } @@ -1427,63 +1501,63 @@ class Container: NSObject { func fetchAfterEstablish(ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - reply: @escaping (String?, [CKRecord], Set?, TPPolicy?, Error?) -> Void) { + reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) { self.moc.performAndWait { do { try self.deleteLocalCloudKitData() } catch { os_log("fetchAfterEstablish failed to reset local data: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } self.onqueueFetchAndPersistChanges { error in guard error == nil else { os_log("fetchAfterEstablish failed to fetch changes: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } self.moc.performAndWait { guard let egoPeerID = self.containerMO.egoPeerID, - let egoPermData = self.containerMO.egoPeerPermanentInfo, - let egoPermSig = self.containerMO.egoPeerPermanentInfoSig, - let egoStableData = self.containerMO.egoPeerStableInfo, - let egoStableSig = self.containerMO.egoPeerStableInfoSig - else { - os_log("fetchAfterEstablish: failed to fetch egoPeerID", log: tplogDebug, type: .default) - reply(nil, [], nil, nil, ContainerError.noPreparedIdentity) - return + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig, + let egoStableData = self.containerMO.egoPeerStableInfo, + let egoStableSig = self.containerMO.egoPeerStableInfoSig + else { + os_log("fetchAfterEstablish: failed to fetch egoPeerID", log: tplogDebug, type: .default) + reply(nil, [], nil, ContainerError.noPreparedIdentity) + return } guard self.model.hasPeer(withID: egoPeerID) else { os_log("fetchAfterEstablish: did not find peer %{public}@ in model", log: tplogDebug, type: .default, egoPeerID) - reply(nil, [], nil, nil, ContainerError.invalidPeerID) + reply(nil, [], nil, ContainerError.invalidPeerID) return } let keyFactory = TPECPublicKeyFactory() guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - reply(nil, [], nil, nil, ContainerError.invalidPermanentInfoOrSig) + reply(nil, [], nil, ContainerError.invalidPermanentInfoOrSig) return } guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else { os_log("cannot create TPPeerStableInfo", log: tplogDebug, type: .default) - reply(nil, [], nil, nil, ContainerError.invalidStableInfoOrSig) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) return } self.onqueueUpdateTLKs(ckksKeys: ckksKeys, tlkShares: tlkShares) { ckrecords, error in guard error == nil else { os_log("fetchAfterEstablish failed to update TLKs: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } do { - let (syncingViews, policy) = try self.policyAndViewsFor(permanentInfo: selfPermanentInfo, - stableInfo: selfStableInfo) + let syncingPolicy = try self.syncingPolicyFor(modelID: selfPermanentInfo.modelID, + stableInfo: selfStableInfo) os_log("fetchAfterEstablish succeeded", log: tplogDebug, type: .default) - reply(egoPeerID, ckrecords ?? [], syncingViews, policy, nil) + reply(egoPeerID, ckrecords ?? [], syncingPolicy, nil) } catch { os_log("fetchAfterEstablish failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg)) - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) } } } @@ -1494,7 +1568,7 @@ class Container: NSObject { func onqueueEstablish(ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], preapprovedKeys: [Data]?, - reply: @escaping (String?, [CKRecord], Set?, TPPolicy?, Error?) -> Void) { + reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) { // Fetch ego peer identity from local storage. guard let egoPeerID = self.containerMO.egoPeerID, let egoPermData = self.containerMO.egoPeerPermanentInfo, @@ -1502,31 +1576,31 @@ class Container: NSObject { let egoStableData = self.containerMO.egoPeerStableInfo, let egoStableSig = self.containerMO.egoPeerStableInfoSig else { - reply(nil, [], nil, nil, ContainerError.noPreparedIdentity) + reply(nil, [], nil, ContainerError.noPreparedIdentity) return } let keyFactory = TPECPublicKeyFactory() guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - reply(nil, [], nil, nil, ContainerError.invalidPermanentInfoOrSig) + reply(nil, [], nil, ContainerError.invalidPermanentInfoOrSig) return } guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else { os_log("cannot create TPPeerStableInfo", log: tplogDebug, type: .default) - reply(nil, [], nil, nil, ContainerError.invalidStableInfoOrSig) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) return } guard self.onqueueMachineIDAllowedByIDMS(machineID: selfPermanentInfo.machineID) else { os_log("establish: self machineID %{public}@ not on list", log: tplogDebug, type: .debug, selfPermanentInfo.machineID) self.onqueueTTRUntrusted() - reply(nil, [], nil, nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) + reply(nil, [], nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) return } loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in - guard let egoPeerKeys = egoPeerKeys else { + guard let egoPeerKeys = egoPeerKeys else { os_log("Don't have my own peer keys; can't establish: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } self.moc.performAndWait { @@ -1539,40 +1613,39 @@ class Container: NSObject { allTLKShares = octagonShares + sosShares } catch { os_log("Unable to make TLKShares for self: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } - let dynamicInfo: TPPeerDynamicInfo + let peer: Peer + let newDynamicInfo: TPPeerDynamicInfo do { - dynamicInfo = try self.model.dynamicInfo(forJoiningPeerID: egoPeerID, - peerPermanentInfo: selfPermanentInfo, - peerStableInfo: selfStableInfo, - sponsorID: nil, - preapprovedKeys: preapprovedKeys, - signing: egoPeerKeys.signingKey, - currentMachineIDs: self.onqueueCurrentMIDList()) - - os_log("dynamic info: %{public}@", log: tplogDebug, type: .default, dynamicInfo) + (peer, newDynamicInfo) = try self.onqueuePreparePeerForJoining(egoPeerID: egoPeerID, + peerPermanentInfo: selfPermanentInfo, + stableInfo: selfStableInfo, + sponsorID: nil, + preapprovedKeys: preapprovedKeys, + vouchers: [], + egoPeerKeys: egoPeerKeys) + + os_log("dynamic info: %{public}@", log: tplogDebug, type: .default, newDynamicInfo) } catch { - reply(nil, [], nil, nil, error) + os_log("Unable to create peer for joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, [], nil, error) return } - let peer = Peer.with { - $0.peerID = egoPeerID - $0.permanentInfoAndSig.peerPermanentInfo = egoPermData - $0.permanentInfoAndSig.sig = egoPermSig - $0.stableInfoAndSig.peerStableInfo = egoStableData - $0.stableInfoAndSig.sig = egoStableSig - $0.dynamicInfoAndSig = SignedPeerDynamicInfo(dynamicInfo) + guard let newPeerStableInfo = peer.stableInfoAndSig.toStableInfo() else { + os_log("Unable to create new peer stable info for joining", log: tplogDebug, type: .default) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) + return } let bottle: Bottle do { bottle = try self.assembleBottle(egoPeerID: egoPeerID) } catch { - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } os_log("Beginning establish for peer %{public}@", log: tplogDebug, type: .default, egoPeerID) @@ -1599,7 +1672,6 @@ class Container: NSObject { $0.tlkShares = allTLKShares } self.cuttlefish.establish(request) { response, error in - os_log("Establish(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") os_log("Establish: viewKeys: %{public}@", String(describing: viewKeys)) guard let response = response, error == nil else { switch error { @@ -1609,7 +1681,7 @@ class Container: NSObject { return default: os_log("establish failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, [], nil, nil, error ?? ContainerError.cloudkitResponseMissing) + reply(nil, [], nil, error ?? ContainerError.cloudkitResponseMissing) return } } @@ -1623,8 +1695,8 @@ class Container: NSObject { let keyHierarchyRecords = response.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } do { - let (syncingViews, policy) = try self.policyAndViewsFor(permanentInfo: selfPermanentInfo, - stableInfo: selfStableInfo) + let syncingPolicy = try self.syncingPolicyFor(modelID: selfPermanentInfo.modelID, + stableInfo: newPeerStableInfo) try self.persist(changes: response.changes) @@ -1635,33 +1707,33 @@ class Container: NSObject { guard fetchError == nil else { // This is an odd error condition: we might be able to fetch again and be in a good state... os_log("fetch-after-establish failed: %{public}@", log: tplogDebug, type: .default, (fetchError as CVarArg?) ?? "no error") - reply(nil, keyHierarchyRecords, nil, nil, fetchError) + reply(nil, keyHierarchyRecords, nil, fetchError) return } os_log("fetch-after-establish succeeded", log: tplogDebug, type: .default) - reply(egoPeerID, keyHierarchyRecords, nil, nil, nil) + reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil) } return } os_log("establish succeeded", log: tplogDebug, type: .default) - reply(egoPeerID, keyHierarchyRecords, syncingViews, policy, nil) + reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil) } catch { os_log("establish handling failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg)) - reply(nil, keyHierarchyRecords, nil, nil, error) + reply(nil, keyHierarchyRecords, nil, error) } } } } } - func setRecoveryKey(recoveryKey: String, salt: String, ckksKeys: [CKKSKeychainBackedKeySet], reply: @escaping (Error?) -> Void) { + func setRecoveryKey(recoveryKey: String, salt: String, ckksKeys: [CKKSKeychainBackedKeySet], reply: @escaping ([CKRecord]?, Error?) -> Void) { self.semaphore.wait() - let reply: (Error?) -> Void = { - os_log("setRecoveryKey complete: %{public}@", log: tplogTrace, type: .info, traceError($0)) + let reply: ([CKRecord]?, Error?) -> Void = { + os_log("setRecoveryKey complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) self.semaphore.signal() - reply($0) + reply($0, $1) } os_log("beginning a setRecoveryKey", log: tplogDebug, type: .default) @@ -1669,7 +1741,7 @@ class Container: NSObject { self.moc.performAndWait { guard let egoPeerID = self.containerMO.egoPeerID else { os_log("no prepared identity, cannot set recovery key", log: tplogDebug, type: .default) - reply(ContainerError.noPreparedIdentity) + reply(nil, ContainerError.noPreparedIdentity) return } @@ -1678,7 +1750,7 @@ class Container: NSObject { recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) } catch { os_log("failed to create recovery keys: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(ContainerError.failedToCreateRecoveryKey) + reply(nil, ContainerError.failedToCreateRecoveryKey) return } @@ -1690,40 +1762,40 @@ class Container: NSObject { guard let stableInfoData = self.containerMO.egoPeerStableInfo else { os_log("stableInfo does not exist", log: tplogDebug, type: .default) - reply(ContainerError.nonMember) + reply(nil, ContainerError.nonMember) return } guard let stableInfoSig = self.containerMO.egoPeerStableInfoSig else { os_log("stableInfoSig does not exist", log: tplogDebug, type: .default) - reply(ContainerError.nonMember) + reply(nil, ContainerError.nonMember) return } guard let permInfoData = self.containerMO.egoPeerPermanentInfo else { os_log("permanentInfo does not exist", log: tplogDebug, type: .default) - reply(ContainerError.nonMember) + reply(nil, ContainerError.nonMember) return } guard let permInfoSig = self.containerMO.egoPeerPermanentInfoSig else { os_log("permInfoSig does not exist", log: tplogDebug, type: .default) - reply(ContainerError.nonMember) + reply(nil, ContainerError.nonMember) return } guard let stableInfo = TPPeerStableInfo(data: stableInfoData, sig: stableInfoSig) else { os_log("cannot create TPPeerStableInfo", log: tplogDebug, type: .default) - reply(ContainerError.invalidStableInfoOrSig) + reply(nil, ContainerError.invalidStableInfoOrSig) return } let keyFactory = TPECPublicKeyFactory() guard let permanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: permInfoData, sig: permInfoSig, keyFactory: keyFactory) else { os_log("cannot create TPPeerPermanentInfo", log: tplogDebug, type: .default) - reply(ContainerError.invalidStableInfoOrSig) + reply(nil, ContainerError.invalidStableInfoOrSig) return } loadEgoKeyPair(identifier: signingKeyIdentifier(peerID: egoPeerID)) { signingKeyPair, error in guard let signingKeyPair = signingKeyPair else { os_log("handle: no signing key pair: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(error) + reply(nil, error) return } self.moc.performAndWait { @@ -1736,17 +1808,17 @@ class Container: NSObject { let policyVersion = stableInfo.bestPolicyVersion() let policyDoc = try self.getPolicyDoc(policyVersion.versionNumber) - let updatedStableInfo = TPPeerStableInfo(clock: stableInfo.clock + 1, - frozenPolicyVersion: frozenPolicyVersion, - flexiblePolicyVersion: policyDoc.version, - policySecrets: stableInfo.policySecrets, - deviceName: stableInfo.deviceName, - serialNumber: stableInfo.serialNumber, - osVersion: stableInfo.osVersion, - signing: signingKeyPair, - recoverySigningPubKey: signingPublicKey, - recoveryEncryptionPubKey: encryptionPublicKey, - error: nil) + let updatedStableInfo = try TPPeerStableInfo(clock: stableInfo.clock + 1, + frozenPolicyVersion: frozenPolicyVersion, + flexiblePolicyVersion: policyDoc.version, + policySecrets: stableInfo.policySecrets, + syncUserControllableViews: stableInfo.syncUserControllableViews, + deviceName: stableInfo.deviceName, + serialNumber: stableInfo.serialNumber, + osVersion: stableInfo.osVersion, + signing: signingKeyPair, + recoverySigningPubKey: signingPublicKey, + recoveryEncryptionPubKey: encryptionPublicKey) let signedStableInfo = SignedPeerStableInfo(updatedStableInfo) let request = SetRecoveryKeyRequest.with { @@ -1759,10 +1831,9 @@ class Container: NSObject { } self.cuttlefish.setRecoveryKey(request) { response, error in - os_log("SetRecoveryKey(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { os_log("setRecoveryKey failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(error ?? ContainerError.cloudkitResponseMissing) + reply(nil, error ?? ContainerError.cloudkitResponseMissing) return } @@ -1773,142 +1844,23 @@ class Container: NSObject { try self.onQueuePersist(changes: response.changes) os_log("setRecoveryKey succeeded", log: tplogDebug, type: .default) - reply(nil) + + let keyHierarchyRecords = response.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } + reply(keyHierarchyRecords, nil) } catch { os_log("setRecoveryKey handling failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg)) - reply(error) + reply(nil, error) } } } } catch { - reply(error) + reply(nil, error) } } } } } - func currentSetContainerBottleID(bottleMOs: Set, bottleID: String) -> (Bool) { - let bmos = bottleMOs.filter { - $0.bottleID == bottleID - } - return !bmos.isEmpty - } - - func onqueueFindBottle(bottleID: String, reply: @escaping (BottleMO?, Error?) -> Void) { - - var bmo: BottleMO? - var bottles: Set = [] - var shouldPerformFetch = false - - if let containerBottles = self.containerMO.bottles as? Set { - if self.currentSetContainerBottleID(bottleMOs: containerBottles, bottleID: bottleID) == false { - shouldPerformFetch = true - } else { - bottles = containerBottles - } - } else { - shouldPerformFetch = true - } - - if shouldPerformFetch == true { - self.fetchViableBottlesWithSemaphore { _, _, error in - guard error == nil else { - os_log("fetchViableBottles failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, error) - return - } - - guard let newBottles = self.containerMO.bottles as? Set else { - os_log("no bottles on container: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, ContainerError.noBottlesPresent) - return - } - - guard self.currentSetContainerBottleID(bottleMOs: newBottles, bottleID: bottleID) == true else { - reply(nil, ContainerError.noBottlesForEscrowRecordID) - return - } - - os_log("onqueueFindBottle found bottle: %{public}@", log: tplogDebug, type: .default, newBottles) - - bottles = newBottles.filter { - $0.bottleID == bottleID - } - if bottles.count > 1 { - reply(nil, ContainerError.tooManyBottlesForPeer) - return - } - bmo = bottles.removeFirst() - reply(bmo, nil) - } - } else { - var filteredBottles = bottles.filter { - $0.bottleID == bottleID - } - if filteredBottles.count > 1 { - reply(nil, ContainerError.tooManyBottlesForPeer) - return - } - bmo = filteredBottles.removeFirst() - reply(bmo, nil) - } - } - - func onqueueRecoverBottle(managedBottle: BottleMO, entropy: Data, bottleSalt: String) throws -> BottledPeer { - guard let bottledContents = managedBottle.contents else { - throw ContainerError.bottleDoesNotContainContents - } - guard let signatureUsingEscrowKey = managedBottle.signatureUsingEscrowKey else { - throw ContainerError.bottleDoesNotContainEscrowKeySignature - } - - guard let signatureUsingPeerKey = managedBottle.signatureUsingPeerKey else { - throw ContainerError.bottleDoesNotContainerPeerKeySignature - } - guard let sponsorPeerID = managedBottle.peerID else { - throw ContainerError.bottleDoesNotContainPeerID - } - - //verify bottle signature using peer - do { - guard let sponsorPeer = self.model.peer(withID: sponsorPeerID) else { - os_log("recover bottle: Unable to find peer that created the bottle", log: tplogDebug, type: .default) - throw ContainerError.bottleCreatingPeerNotFound - } - guard let signingKey: _SFECPublicKey = sponsorPeer.permanentInfo.signingPubKey as? _SFECPublicKey else { - os_log("recover bottle: Unable to create a sponsor public key", log: tplogDebug, type: .default) - throw ContainerError.signatureVerificationFailed - } - - _ = try BottledPeer.verifyBottleSignature(data: bottledContents, signature: signatureUsingPeerKey, pubKey: signingKey) - } catch { - os_log("Verification of bottled signature failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - throw ContainerError.failedToCreateBottledPeer - } - - do { - return try BottledPeer(contents: bottledContents, - secret: entropy, - bottleSalt: bottleSalt, - signatureUsingEscrow: signatureUsingEscrowKey, - signatureUsingPeerKey: signatureUsingPeerKey) - } catch { - os_log("Creation of Bottled Peer failed with bottle salt: %@,\nAttempting with empty bottle salt", bottleSalt) - - do { - return try BottledPeer(contents: bottledContents, - secret: entropy, - bottleSalt: "", - signatureUsingEscrow: signatureUsingEscrowKey, - signatureUsingPeerKey: signatureUsingPeerKey) - } catch { - os_log("Creation of Bottled Peer failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - throw ContainerError.failedToCreateBottledPeer - } - } - } - func vouchWithBottle(bottleID: String, entropy: Data, bottleSalt: String, @@ -1922,148 +1874,137 @@ class Container: NSObject { reply($0, $1, $2, $3, $4) } - self.fetchAndPersistChangesIfNeeded { error in - guard error == nil else { - os_log("vouchWithBottle unable to fetch changes: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") + // A preflight should have been successful before calling this function. So, we can assume that all required data is stored locally. + + self.moc.performAndWait { + let bmo: BottleMO + + do { + (bmo, _, _) = try self.onMOCQueuePerformPreflight(bottleID: bottleID) + } catch { + os_log("vouchWithBottle failed preflight: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") reply(nil, nil, 0, 0, error) return } - self.onqueueFindBottle(bottleID: bottleID) { returnedBMO, error in - self.moc.performAndWait { - guard error == nil else { - os_log("vouchWithBottle unable to find bottle for escrow record id: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(nil, nil, 0, 0, error) - return - } - - guard let bmo: BottleMO = returnedBMO else { - os_log("vouchWithBottle bottle is nil: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(nil, nil, 0, 0, error) - return - } - - guard let bottledContents = bmo.contents else { - reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainContents) - return - } - guard let signatureUsingEscrowKey = bmo.signatureUsingEscrowKey else { - reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainEscrowKeySignature) - return - } - - guard let signatureUsingPeerKey = bmo.signatureUsingPeerKey else { - reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainerPeerKeySignature) - return - } - guard let sponsorPeerID = bmo.peerID else { - reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainPeerID) - return - } + guard let bottledContents = bmo.contents else { + reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainContents) + return + } + guard let signatureUsingEscrowKey = bmo.signatureUsingEscrowKey else { + reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainEscrowKeySignature) + return + } - //verify bottle signature using peer - do { - guard let sponsorPeer = self.model.peer(withID: sponsorPeerID) else { - os_log("vouchWithBottle: Unable to find peer that created the bottle", log: tplogDebug, type: .default) - reply(nil, nil, 0, 0, ContainerError.bottleCreatingPeerNotFound) - return - } - guard let signingKey: _SFECPublicKey = sponsorPeer.permanentInfo.signingPubKey as? _SFECPublicKey else { - os_log("vouchWithBottle: Unable to create a sponsor public key", log: tplogDebug, type: .default) - reply(nil, nil, 0, 0, ContainerError.signatureVerificationFailed) - return - } + guard let signatureUsingPeerKey = bmo.signatureUsingPeerKey else { + reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainerPeerKeySignature) + return + } + guard let sponsorPeerID = bmo.peerID else { + reply(nil, nil, 0, 0, ContainerError.bottleDoesNotContainPeerID) + return + } - _ = try BottledPeer.verifyBottleSignature(data: bottledContents, signature: signatureUsingPeerKey, pubKey: signingKey) - } catch { - os_log("vouchWithBottle: Verification of bottled signature failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, 0, 0, ContainerError.failedToCreateBottledPeer) - return - } + //verify bottle signature using peer + do { + guard let sponsorPeer = self.model.peer(withID: sponsorPeerID) else { + os_log("vouchWithBottle: Unable to find peer that created the bottle", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.bottleCreatingPeerNotFound) + return + } + guard let signingKey: _SFECPublicKey = sponsorPeer.permanentInfo.signingPubKey as? _SFECPublicKey else { + os_log("vouchWithBottle: Unable to create a sponsor public key", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.signatureVerificationFailed) + return + } - //create bottled peer - let bottledPeer: BottledPeer - do { - bottledPeer = try BottledPeer(contents: bottledContents, - secret: entropy, - bottleSalt: bottleSalt, - signatureUsingEscrow: signatureUsingEscrowKey, - signatureUsingPeerKey: signatureUsingPeerKey) - } catch { - os_log("Creation of Bottled Peer failed with bottle salt: %@,\nAttempting with empty bottle salt", bottleSalt) + _ = try BottledPeer.verifyBottleSignature(data: bottledContents, signature: signatureUsingPeerKey, pubKey: signingKey) + } catch { + os_log("vouchWithBottle: Verification of bottled signature failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, 0, 0, ContainerError.failedToCreateBottledPeer) + return + } - do { - bottledPeer = try BottledPeer(contents: bottledContents, - secret: entropy, - bottleSalt: "", - signatureUsingEscrow: signatureUsingEscrowKey, - signatureUsingPeerKey: signatureUsingPeerKey) - } catch { + //create bottled peer + let bottledPeer: BottledPeer + do { + bottledPeer = try BottledPeer(contents: bottledContents, + secret: entropy, + bottleSalt: bottleSalt, + signatureUsingEscrow: signatureUsingEscrowKey, + signatureUsingPeerKey: signatureUsingPeerKey) + } catch { + os_log("Creation of Bottled Peer failed with bottle salt: %@,\nAttempting with empty bottle salt", bottleSalt) - os_log("Creation of Bottled Peer failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, 0, 0, ContainerError.failedToCreateBottledPeer) - return - } - } + do { + bottledPeer = try BottledPeer(contents: bottledContents, + secret: entropy, + bottleSalt: "", + signatureUsingEscrow: signatureUsingEscrowKey, + signatureUsingPeerKey: signatureUsingPeerKey) + } catch { + os_log("Creation of Bottled Peer failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, 0, 0, ContainerError.failedToCreateBottledPeer) + return + } + } - os_log("Have a bottle for peer %{public}@", log: tplogDebug, type: .default, bottledPeer.peerID) + os_log("Have a bottle for peer %{public}@", log: tplogDebug, type: .default, bottledPeer.peerID) - // Extract any TLKs we have been given - let (uniqueTLKsRecovered, totalSharesRecovered) = extract(tlkShares: tlkShares, peer: bottledPeer.peerKeys, model: self.model) + // Extract any TLKs we have been given + let (uniqueTLKsRecovered, totalSharesRecovered) = extract(tlkShares: tlkShares, peer: bottledPeer.peerKeys, model: self.model) - self.moc.performAndWait { - // I must have an ego identity in order to vouch using bottle - guard let egoPeerID = self.containerMO.egoPeerID else { - os_log("As a nonmember, can't vouch for someone else", log: tplogDebug, type: .default) - reply(nil, nil, 0, 0, ContainerError.nonMember) - return - } - guard let permanentInfo = self.containerMO.egoPeerPermanentInfo else { - os_log("permanentInfo does not exist", log: tplogDebug, type: .default) - reply(nil, nil, 0, 0, ContainerError.nonMember) - return - } - guard let permanentInfoSig = self.containerMO.egoPeerPermanentInfoSig else { - os_log("permanentInfoSig does not exist", log: tplogDebug, type: .default) - reply(nil, nil, 0, 0, ContainerError.nonMember) - return - } - guard let stableInfo = self.containerMO.egoPeerStableInfo else { - os_log("stableInfo does not exist", log: tplogDebug, type: .default) - reply(nil, nil, 0, 0, ContainerError.nonMember) - return - } - guard let stableInfoSig = self.containerMO.egoPeerStableInfoSig else { - os_log("stableInfoSig does not exist", log: tplogDebug, type: .default) - reply(nil, nil, 0, 0, ContainerError.nonMember) - return - } - let keyFactory = TPECPublicKeyFactory() - guard let beneficiaryPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: permanentInfo, sig: permanentInfoSig, keyFactory: keyFactory) else { - os_log("Invalid permenent info or signature; can't vouch for them", log: tplogDebug, type: .default) - reply(nil, nil, 0, 0, ContainerError.invalidPermanentInfoOrSig) - return - } - guard let beneficiaryStableInfo = TPPeerStableInfo(data: stableInfo, sig: stableInfoSig) else { - os_log("Invalid stableinfo or signature; van't vouch for them", log: tplogDebug, type: .default) - reply(nil, nil, 0, 0, ContainerError.invalidStableInfoOrSig) - return - } + self.moc.performAndWait { + // I must have an ego identity in order to vouch using bottle + guard let egoPeerID = self.containerMO.egoPeerID else { + os_log("As a nonmember, can't vouch for someone else", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.nonMember) + return + } + guard let permanentInfo = self.containerMO.egoPeerPermanentInfo else { + os_log("permanentInfo does not exist", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.nonMember) + return + } + guard let permanentInfoSig = self.containerMO.egoPeerPermanentInfoSig else { + os_log("permanentInfoSig does not exist", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.nonMember) + return + } + guard let stableInfo = self.containerMO.egoPeerStableInfo else { + os_log("stableInfo does not exist", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.nonMember) + return + } + guard let stableInfoSig = self.containerMO.egoPeerStableInfoSig else { + os_log("stableInfoSig does not exist", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.nonMember) + return + } + let keyFactory = TPECPublicKeyFactory() + guard let beneficiaryPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: permanentInfo, sig: permanentInfoSig, keyFactory: keyFactory) else { + os_log("Invalid permenent info or signature; can't vouch for them", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.invalidPermanentInfoOrSig) + return + } + guard let beneficiaryStableInfo = TPPeerStableInfo(data: stableInfo, sig: stableInfoSig) else { + os_log("Invalid stableinfo or signature; van't vouch for them", log: tplogDebug, type: .default) + reply(nil, nil, 0, 0, ContainerError.invalidStableInfoOrSig) + return + } - do { - let voucher = try self.model.createVoucher(forCandidate: beneficiaryPermanentInfo, - stableInfo: beneficiaryStableInfo, - withSponsorID: sponsorPeerID, - reason: TPVoucherReason.restore, - signing: bottledPeer.peerKeys.signingKey) - reply(voucher.data, voucher.sig, uniqueTLKsRecovered, totalSharesRecovered, nil) - return - } catch { - os_log("Error creating voucher with bottle: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, 0, 0, error) - return - } - } + do { + let voucher = try self.model.createVoucher(forCandidate: beneficiaryPermanentInfo, + stableInfo: beneficiaryStableInfo, + withSponsorID: sponsorPeerID, + reason: TPVoucherReason.restore, + signing: bottledPeer.peerKeys.signingKey) + reply(voucher.data, voucher.sig, uniqueTLKsRecovered, totalSharesRecovered, nil) + return + } catch { + os_log("Error creating voucher with bottle: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, nil, 0, 0, error) + return } } } @@ -2132,8 +2073,6 @@ class Container: NSObject { return } - extract(tlkShares: tlkShares, peer: recoveryKeys.peerKeys, model: self.model) - let signingPublicKey: Data = recoveryKeys.peerKeys.signingKey.publicKey.keyData let encryptionPublicKey: Data = recoveryKeys.peerKeys.encryptionKey.publicKey.keyData @@ -2147,12 +2086,16 @@ class Container: NSObject { } //find matching peer containing recovery keys - guard let sponsorPeerID = self.model.peerIDThatTrustsRecoveryKeys(TPRecoveryKeyPair(signingSPKI: signingPublicKey, encryptionSPKI: encryptionPublicKey)) else { + guard let sponsorPeerID = self.model.peerIDThatTrustsRecoveryKeys(TPRecoveryKeyPair(signingKeyData: signingPublicKey, encryptionKeyData: encryptionPublicKey)) else { os_log("Untrusted recovery key set", log: tplogDebug, type: .default) reply(nil, nil, ContainerError.untrustedRecoveryKeys) return } + // We're going to end up trusting every peer that the sponsor peer trusts. + // We might as well trust all TLKShares from those peers at this point. + extract(tlkShares: tlkShares, peer: recoveryKeys.peerKeys, sponsorPeerID: sponsorPeerID, model: self.model) + do { let voucher = try self.model.createVoucher(forCandidate: beneficiaryPermanentInfo, stableInfo: beneficiaryStableInfo, @@ -2340,7 +2283,6 @@ class Container: NSObject { func onqueueDistrust(peerIDs: Set, reply: @escaping (Error?) -> Void) { - guard let egoPeerID = self.containerMO.egoPeerID else { os_log("No dynamic info for self?", log: tplogDebug, type: .default) reply(ContainerError.noPreparedIdentity) @@ -2363,7 +2305,6 @@ class Container: NSObject { preapprovedKeys: nil, signing: signingKeyPair, currentMachineIDs: self.onqueueCurrentMIDList()) - } catch { os_log("Error preparing dynamic info: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "nil") reply(error) @@ -2379,7 +2320,6 @@ class Container: NSObject { $0.dynamicInfoAndSig = signedDynamicInfo } self.cuttlefish.updateTrust(request) { response, error in - os_log("UpdateTrust(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { os_log("updateTrust failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(error ?? ContainerError.cloudkitResponseMissing) @@ -2421,8 +2361,12 @@ class Container: NSObject { return } - var bmoSet = bottles.filter { $0.peerID == egoPeerID } - let bmo = bmoSet.removeFirst() + guard let bmo = bottles.filter({ $0.peerID == egoPeerID }).first else { + os_log("fetchEscrowContents no bottle matches peerID", log: tplogDebug, type: .default) + reply(nil, nil, nil, ContainerError.noBottleForPeer) + return + } + let bottleID = bmo.bottleID var entropy: Data @@ -2459,35 +2403,157 @@ class Container: NSObject { self.fetchViableBottlesWithSemaphore(reply: reply) } - func onqueueCachedBottlesContainEgoPeerBottle(cachedBottles: TPCachedViableBottles) -> Bool { - guard let egoPeerID = self.containerMO.egoPeerID else { - os_log("bottleForEgoPeer: No identity.", log: tplogDebug, type: .default) - return false + func handleFetchViableBottlesResponseWithSemaphore(response: FetchViableBottlesResponse?) { + guard let escrowPairs = response?.viableBottles else { + os_log("fetchViableBottles returned no viable bottles", log: tplogDebug, type: .default) + return + } + + var partialPairs: [EscrowPair] = [] + if let partial = response?.partialBottles { + partialPairs = partial + } else { + os_log("fetchViableBottles returned no partially viable bottles, but that's ok", log: tplogDebug, type: .default) } - guard let bottles: Set = self.containerMO.bottles as? Set else { - os_log("bottleForEgoPeer: No Bottles.", log: tplogDebug, type: .default) - return false + + var legacyEscrowInformations: [EscrowInformation] = [] + if let legacy = response?.legacyRecords { + legacyEscrowInformations = legacy + } else { + os_log("fetchViableBottles returned no legacy escrow records", log: tplogDebug, type: .default) + } + + escrowPairs.forEach { pair in + let bottle = pair.bottle + let record = pair.record + if pair.hasRecord { + // Save this escrow record only if we don't already have it + if let existingRecords = self.containerMO.fullyViableEscrowRecords as? Set { + let matchingRecords: Set = existingRecords.filter { existing in existing.label == record.label + && existing.escrowMetadata?.bottleID == record.escrowInformationMetadata.bottleID } + if !matchingRecords.isEmpty { + os_log("fetchViableBottles already knows about record, re-adding entry", log: tplogDebug, type: .default, record.label) + self.containerMO.removeFromFullyViableEscrowRecords(matchingRecords as NSSet) + } + self.setEscrowRecord(record: record, viability: .full) + } + } + // Save this bottle only if we don't already have it + if let existingBottles = self.containerMO.bottles as? Set { + let matchingBottles: Set = existingBottles.filter { existing in + existing.peerID == bottle.peerID && + existing.bottleID == bottle.bottleID && + existing.escrowedSigningSPKI == bottle.escrowedSigningSpki && + existing.signatureUsingEscrowKey == bottle.signatureUsingEscrowKey && + existing.signatureUsingPeerKey == bottle.signatureUsingPeerKey && + existing.contents == bottle.contents + } + if !matchingBottles.isEmpty { + os_log("fetchViableBottles already knows about bottle", log: tplogDebug, type: .default, bottle.bottleID) + return + } + } + + let bmo = BottleMO(context: self.moc) + bmo.peerID = bottle.peerID + bmo.bottleID = bottle.bottleID + bmo.escrowedSigningSPKI = bottle.escrowedSigningSpki + bmo.signatureUsingEscrowKey = bottle.signatureUsingEscrowKey + bmo.signatureUsingPeerKey = bottle.signatureUsingPeerKey + bmo.contents = bottle.contents + + os_log("fetchViableBottles saving new bottle: %{public}@", log: tplogDebug, type: .default, bmo) + self.containerMO.addToBottles(bmo) } - var matchesCached: Bool = false - for bottle in bottles { - guard let bottleID: String = bottle.bottleID else { - continue + + partialPairs.forEach { pair in + let bottle = pair.bottle + + let record = pair.record + // Save this escrow record only if we don't already have it + if pair.hasRecord { + if let existingRecords = self.containerMO.partiallyViableEscrowRecords as? Set { + let matchingRecords: Set = existingRecords.filter { existing in existing.label == record.label + && existing.escrowMetadata?.bottleID == record.escrowInformationMetadata.bottleID } + if !matchingRecords.isEmpty { + os_log("fetchViableBottles already knows about record, re-adding entry", log: tplogDebug, type: .default, record.label) + self.containerMO.removeFromPartiallyViableEscrowRecords(matchingRecords as NSSet) + } + self.setEscrowRecord(record: record, viability: Viability.partial) + } } - if bottle.peerID == egoPeerID && (cachedBottles.viableBottles.contains(bottleID) || cachedBottles.partialBottles.contains(bottleID)) { - matchesCached = true - break + + // Save this bottle only if we don't already have it + if let existingBottles = self.containerMO.bottles as? Set { + let matchingBottles: Set = existingBottles.filter { existing in + existing.peerID == bottle.peerID && + existing.bottleID == bottle.bottleID && + existing.escrowedSigningSPKI == bottle.escrowedSigningSpki && + existing.signatureUsingEscrowKey == bottle.signatureUsingEscrowKey && + existing.signatureUsingPeerKey == bottle.signatureUsingPeerKey && + existing.contents == bottle.contents + } + if !matchingBottles.isEmpty { + os_log("fetchViableBottles already knows about bottle", log: tplogDebug, type: .default, bottle.bottleID) + return + } + } + + let bmo = BottleMO(context: self.moc) + bmo.peerID = bottle.peerID + bmo.bottleID = bottle.bottleID + bmo.escrowedSigningSPKI = bottle.escrowedSigningSpki + bmo.signatureUsingEscrowKey = bottle.signatureUsingEscrowKey + bmo.signatureUsingPeerKey = bottle.signatureUsingPeerKey + bmo.contents = bottle.contents + + os_log("fetchViableBottles saving new bottle: %{public}@", log: tplogDebug, type: .default, bmo) + self.containerMO.addToBottles(bmo) + } + legacyEscrowInformations.forEach { record in + // Save this escrow record only if we don't already have it + if let existingRecords = self.containerMO.legacyEscrowRecords as? Set { + let matchingRecords: Set = existingRecords.filter { existing in existing.label == record.label } + if !matchingRecords.isEmpty { + os_log("fetchViableBottles already knows about legacy record %@, re-adding entry", log: tplogDebug, type: .default, record.label) + self.containerMO.removeFromLegacyEscrowRecords(matchingRecords as NSSet) + } + if record.label.hasSuffix(".double") { + os_log("ignoring double enrollment record %@", record.label) + } else { + self.setEscrowRecord(record: record, viability: Viability.none) + } } } - return matchesCached } func fetchViableBottlesWithSemaphore(reply: @escaping ([String]?, [String]?, Error?) -> Void) { os_log("beginning a fetchViableBottles", log: tplogDebug, type: .default) - let cachedBottles: TPCachedViableBottles = self.model.currentCachedViableBottlesSet() self.moc.performAndWait { - if self.onqueueCachedBottlesContainEgoPeerBottle(cachedBottles: cachedBottles) - && (!cachedBottles.viableBottles.isEmpty || !cachedBottles.partialBottles.isEmpty) { + var cachedBottles = TPCachedViableBottles(viableBottles: [], partialBottles: []) + + if OctagonIsOptimizationEnabled() { + if let lastDate = self.containerMO.escrowFetchDate { + if Date() < lastDate.addingTimeInterval(escrowCacheTimeout) { + os_log("escrow cache still valid", log: tplogDebug, type: .default) + cachedBottles = onqueueCachedBottlesFromEscrowRecords() + } else { + os_log("escrow cache no longer valid", log: tplogDebug, type: .default) + if let records = self.containerMO.fullyViableEscrowRecords { + self.containerMO.removeFromFullyViableEscrowRecords(records) + } + if let records = self.containerMO.partiallyViableEscrowRecords { + self.containerMO.removeFromPartiallyViableEscrowRecords(records) + } + self.containerMO.escrowFetchDate = nil + } + } + } else { + cachedBottles = self.model.currentCachedViableBottlesSet() + } + + if !cachedBottles.viableBottles.isEmpty || !cachedBottles.partialBottles.isEmpty { os_log("returning from fetchViableBottles, using cached bottles", log: tplogDebug, type: .default) reply(cachedBottles.viableBottles, cachedBottles.partialBottles, nil) return @@ -2501,7 +2567,6 @@ class Container: NSObject { } self.moc.performAndWait { - guard let escrowPairs = response?.viableBottles else { os_log("fetchViableBottles returned no viable bottles", log: tplogDebug, type: .default) reply([], [], nil) @@ -2521,87 +2586,138 @@ class Container: NSObject { let partialBottleIDs = partialPairs.compactMap { $0.bottle.bottleID } os_log("fetchViableBottles returned partial bottles: %{public}@", log: tplogDebug, type: .default, partialBottleIDs) - escrowPairs.forEach { pair in - let bottle = pair.bottle - - // Save this bottle only if we don't already have it - if let existingBottles = self.containerMO.bottles as? Set { - let matchingBottles: Set = existingBottles.filter { existing in - existing.peerID == bottle.peerID && - existing.bottleID == bottle.bottleID && - existing.escrowedSigningSPKI == bottle.escrowedSigningSpki && - existing.signatureUsingEscrowKey == bottle.signatureUsingEscrowKey && - existing.signatureUsingPeerKey == bottle.signatureUsingPeerKey && - existing.contents == bottle.contents - } - if !matchingBottles.isEmpty { - os_log("fetchViableBottles already knows about bottle", log: tplogDebug, type: .default, bottle.bottleID) - return - } - } - - let bmo = BottleMO(context: self.moc) - bmo.peerID = bottle.peerID - bmo.bottleID = bottle.bottleID - bmo.escrowedSigningSPKI = bottle.escrowedSigningSpki - bmo.signatureUsingEscrowKey = bottle.signatureUsingEscrowKey - bmo.signatureUsingPeerKey = bottle.signatureUsingPeerKey - bmo.contents = bottle.contents - - os_log("fetchViableBottles saving new bottle: %{public}@", log: tplogDebug, type: .default, bmo) - self.containerMO.addToBottles(bmo) - } - - partialPairs.forEach { pair in - let bottle = pair.bottle - - // Save this bottle only if we don't already have it - if let existingBottles = self.containerMO.bottles as? Set { - let matchingBottles: Set = existingBottles.filter { existing in - existing.peerID == bottle.peerID && - existing.bottleID == bottle.bottleID && - existing.escrowedSigningSPKI == bottle.escrowedSigningSpki && - existing.signatureUsingEscrowKey == bottle.signatureUsingEscrowKey && - existing.signatureUsingPeerKey == bottle.signatureUsingPeerKey && - existing.contents == bottle.contents - } - if !matchingBottles.isEmpty { - os_log("fetchViableBottles already knows about bottle", log: tplogDebug, type: .default, bottle.bottleID) - return - } - } - - let bmo = BottleMO(context: self.moc) - bmo.peerID = bottle.peerID - bmo.bottleID = bottle.bottleID - bmo.escrowedSigningSPKI = bottle.escrowedSigningSpki - bmo.signatureUsingEscrowKey = bottle.signatureUsingEscrowKey - bmo.signatureUsingPeerKey = bottle.signatureUsingPeerKey - bmo.contents = bottle.contents - - os_log("fetchViableBottles saving new bottle: %{public}@", log: tplogDebug, type: .default, bmo) - self.containerMO.addToBottles(bmo) - } + self.handleFetchViableBottlesResponseWithSemaphore(response: response) do { try self.moc.save() os_log("fetchViableBottles saved bottles", log: tplogDebug, type: .default) let cached = TPCachedViableBottles(viableBottles: viableBottleIDs, partialBottles: partialBottleIDs) self.model.setViableBottles(cached) + self.containerMO.escrowFetchDate = Date() reply(viableBottleIDs, partialBottleIDs, nil) } catch { os_log("fetchViableBottles unable to save bottles: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, nil, error) } + } + } + } + } + + func removeEscrowCache(reply: @escaping (Error?) -> Void) { + os_log("beginning a removeEscrowCache", log: tplogDebug, type: .default) + + self.semaphore.wait() + let reply: (Error?) -> Void = { + os_log("removeEscrowCache complete %{public}@", log: tplogTrace, type: .info, traceError($0)) + self.semaphore.signal() + reply($0) + } + + self.moc.performAndWait { + self.onQueueRemoveEscrowCache() + reply(nil) + } + } + + private func onQueueRemoveEscrowCache() { + if let records = self.containerMO.fullyViableEscrowRecords { + self.containerMO.removeFromFullyViableEscrowRecords(records) + } + if let records = self.containerMO.partiallyViableEscrowRecords { + self.containerMO.removeFromPartiallyViableEscrowRecords(records) + } + if let records = self.containerMO.legacyEscrowRecords { + self.containerMO.removeFromLegacyEscrowRecords(records) + } + self.containerMO.escrowFetchDate = nil + } + + func fetchEscrowRecordsWithSemaphore(forceFetch: Bool, reply: @escaping ([Data]?, Error?) -> Void) { + os_log("beginning a fetchEscrowRecords", log: tplogDebug, type: .default) + + self.moc.performAndWait { + var cachedRecords: [OTEscrowRecord] = [] + + if forceFetch == false { + os_log("fetchEscrowRecords: force fetch flag is off", log: tplogDebug, type: .default) + if let lastDate = self.containerMO.escrowFetchDate { + if Date() < lastDate.addingTimeInterval(escrowCacheTimeout) { + os_log("escrow cache still valid", log: tplogDebug, type: .default) + cachedRecords = onqueueCachedEscrowRecords() + } else { + os_log("escrow cache no longer valid", log: tplogDebug, type: .default) + self.onQueueRemoveEscrowCache() + } + } + } else { + os_log("fetchEscrowRecords: force fetch flag is on, removing escrow cache", log: tplogDebug, type: .default) + self.onQueueRemoveEscrowCache() + } + + if !cachedRecords.isEmpty { + os_log("returning from fetchEscrowRecords, using cached escrow records", log: tplogDebug, type: .default) + let recordData: [Data] = cachedRecords.map { $0.data } + reply(recordData, nil) + return + } + + self.cuttlefish.fetchViableBottles { response, error in + guard error == nil else { + os_log("fetchViableBottles failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, error) + return + } + + self.moc.performAndWait { + guard response?.viableBottles != nil else { + os_log("fetchViableBottles returned no viable bottles", log: tplogDebug, type: .default) + reply([], nil) + return + } + self.handleFetchViableBottlesResponseWithSemaphore(response: response) + } + + do { + try self.moc.save() + os_log("fetchViableBottles saved bottles and records", log: tplogDebug, type: .default) + self.containerMO.escrowFetchDate = Date() + + var allEscrowRecordData: [Data] = [] + if let fullyViableRecords = self.containerMO.fullyViableEscrowRecords as? Set { + for record in fullyViableRecords { + if let r = self.escrowRecordMOToEscrowRecords(record: record, viability: .full) { + allEscrowRecordData.append(r.data) + } + } + } + if let partiallyViableRecords = self.containerMO.partiallyViableEscrowRecords as? Set { + for record in partiallyViableRecords { + if let r = self.escrowRecordMOToEscrowRecords(record: record, viability: .partial) { + allEscrowRecordData.append(r.data) + } + } + } + if let legacyRecords = self.containerMO.legacyEscrowRecords as? Set { + for record in legacyRecords { + if let r = self.escrowRecordMOToEscrowRecords(record: record, viability: .none) { + allEscrowRecordData.append(r.data) + } + } + } + reply(allEscrowRecordData, nil) + } catch { + os_log("fetchViableBottles unable to save bottles and records: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") + reply(nil, error) } } } } - func fetchCurrentPolicy(reply: @escaping (Set?, TPPolicy?, Error?) -> Void) { + func fetchCurrentPolicy(modelIDOverride: String?, reply: @escaping (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) -> Void) { self.semaphore.wait() - let reply: (Set?, TPPolicy?, Error?) -> Void = { + let reply: (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) -> Void = { os_log("fetchCurrentPolicy complete: %{public}@", log: tplogTrace, type: .info, traceError($2)) self.semaphore.signal() reply($0, $1, $2) @@ -2613,46 +2729,88 @@ class Container: NSObject { let egoPermSig = self.containerMO.egoPeerPermanentInfoSig, let stableInfoData = self.containerMO.egoPeerStableInfo, let stableInfoSig = self.containerMO.egoPeerStableInfoSig else { - os_log("fetchCurrentPolicy failed to find ego peer information", log: tplogDebug, type: .error) - reply(nil, nil, ContainerError.noPreparedIdentity) + os_log("fetchCurrentPolicy failed to find ego peer information", log: tplogDebug, type: .error) + // This is technically an error, but we also need to know the prevailing syncing policy at CloudKit signin time, not just after we've started to join + + guard let modelID = modelIDOverride else { + os_log("no model ID override; returning error", log: tplogDebug, type: .default) + reply(nil, .UNKNOWN, ContainerError.noPreparedIdentity) return + } + + guard let policyDocument = self.model.policy(withVersion: prevailingPolicyVersion.versionNumber) else { + os_log("prevailing policy is missing?", log: tplogDebug, type: .default) + reply(nil, .UNKNOWN, ContainerError.noPreparedIdentity) + return + } + + do { + let prevailingPolicy = try policyDocument.policy(withSecrets: [:], decrypter: Decrypter()) + let syncingPolicy = try prevailingPolicy.syncingPolicy(forModel: modelID, syncUserControllableViews: .UNKNOWN) + + os_log("returning a policy for model ID %{public}@", log: tplogDebug, type: .default, modelID) + reply(syncingPolicy, .UNKNOWN, nil) + return + } catch { + os_log("fetchCurrentPolicy failed to prevailing policy: %{public}@", log: tplogDebug, type: .error) + reply(nil, .UNKNOWN, ContainerError.noPreparedIdentity) + return + } } let keyFactory = TPECPublicKeyFactory() guard let permanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { os_log("fetchCurrentPolicy failed to create TPPeerPermanentInfo", log: tplogDebug, type: .error) - reply(nil, nil, ContainerError.invalidPermanentInfoOrSig) + reply(nil, .UNKNOWN, ContainerError.invalidPermanentInfoOrSig) return } guard let stableInfo = TPPeerStableInfo(data: stableInfoData, sig: stableInfoSig) else { os_log("fetchCurrentPolicy failed to create TPPeerStableInfo", log: tplogDebug, type: .error) - reply(nil, nil, ContainerError.invalidStableInfoOrSig) + reply(nil, .UNKNOWN, ContainerError.invalidStableInfoOrSig) return } do { - let (views, policy) = try self.policyAndViewsFor(permanentInfo: permanentInfo, stableInfo: stableInfo) - reply(views, policy, nil) + let syncingPolicy = try self.syncingPolicyFor(modelID: modelIDOverride ?? permanentInfo.modelID, stableInfo: stableInfo) + + guard let peer = self.model.peer(withID: permanentInfo.peerID), let dynamicInfo = peer.dynamicInfo else { + os_log("fetchCurrentPolicy with no dynamic info", log: tplogDebug, type: .error) + reply(syncingPolicy, .UNKNOWN, nil) + return + } + + // Note: we specifically do not want to sanitize this value for the platform: returning FOLLOWING here isn't that helpful + let peersUserViewSyncability = self.model.userViewSyncabilityConsensusAmongTrustedPeers(dynamicInfo) + reply(syncingPolicy, peersUserViewSyncability, nil) return } catch { - os_log("TPPolicyDocument failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, error) + os_log("Fetching the syncing policy failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + reply(nil, .UNKNOWN, error) return } } } - func policyAndViewsFor(permanentInfo: TPPeerPermanentInfo, stableInfo: TPPeerStableInfo) throws -> (Set, TPPolicy) { - let policyVersion = stableInfo.bestPolicyVersion() - guard let policyDocument = self.model.policy(withVersion: policyVersion.versionNumber) else { - os_log("current policy is missing?", log: tplogDebug, type: .default) - throw ContainerError.unknownPolicyVersion(policyVersion.versionNumber) + func syncingPolicyFor(modelID: String, stableInfo: TPPeerStableInfo) throws -> TPSyncingPolicy { + let bestPolicyVersion : TPPolicyVersion + + let peerPolicyVersion = stableInfo.bestPolicyVersion() + if peerPolicyVersion.versionNumber < frozenPolicyVersion.versionNumber { + // This peer was from before CKKS4All, and we shouldn't listen to them when it comes to Syncing Policies + bestPolicyVersion = prevailingPolicyVersion + os_log("Ignoring policy version from pre-CKKS4All peer", log: tplogDebug, type: .default) + + } else { + bestPolicyVersion = peerPolicyVersion } - let policy = try policyDocument.policy(withSecrets: stableInfo.policySecrets, decrypter: Decrypter()) - let views = try policy.views(forModel: permanentInfo.modelID) + guard let policyDocument = self.model.policy(withVersion: bestPolicyVersion.versionNumber) else { + os_log("best policy is missing?", log: tplogDebug, type: .default) + throw ContainerError.unknownPolicyVersion(prevailingPolicyVersion.versionNumber) + } - return (views, policy) + let policy = try policyDocument.policy(withSecrets: stableInfo.policySecrets, decrypter: Decrypter()) + return try policy.syncingPolicy(forModel: modelID, syncUserControllableViews: stableInfo.syncUserControllableViews) } // All-or-nothing: return an error in case full list cannot be returned. @@ -2714,7 +2872,6 @@ class Container: NSObject { } self.cuttlefish.fetchPolicyDocuments(request) { response, error in - os_log("FetchPolicyDocuments(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { os_log("FetchPolicyDocuments failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, error ?? ContainerError.cloudkitResponseMissing) @@ -2732,7 +2889,7 @@ class Container: NSObject { return } - guard let expectedVersion = (remaining.filter { $0.versionNumber == doc.version.versionNumber }.first) else { + guard let expectedVersion = (remaining.first { $0.versionNumber == doc.version.versionNumber }) else { os_log("Received a policy version we didn't request: %d", log: tplogDebug, type: .default, doc.version.versionNumber) reply(nil, ContainerError.policyDocumentDoesNotValidate) return @@ -2800,10 +2957,13 @@ class Container: NSObject { } vouchers?.forEach { voucher in self.model.register(voucher) - let voucherMO = VoucherMO(context: self.moc) - voucherMO.voucherInfo = voucher.data - voucherMO.voucherInfoSig = voucher.sig - peer.addToVouchers(voucherMO) + + if (peer.vouchers as? Set ?? Set()).filter({ $0.data == voucher.data && $0.sig == voucher.sig }).isEmpty { + let voucherMO = VoucherMO(context: self.moc) + voucherMO.voucherInfo = voucher.data + voucherMO.voucherInfoSig = voucher.sig + peer.addToVouchers(voucherMO) + } } return peer } @@ -2841,7 +3001,6 @@ class Container: NSObject { } peerShares += viewPeerShares - } catch { os_log("Unable to create TLKShares for keyset %@: %{public}@", log: tplogDebug, type: .default, String(describing: keyset), error as CVarArg) } @@ -2865,8 +3024,30 @@ class Container: NSObject { signing: egoPeerKeys.signingKey, currentMachineIDs: self.onqueueCurrentMIDList()) - let newStableInfo = try self.createNewStableInfoIfNeeded(stableChanges: nil, - egoPeerID: egoPeerID, + let userViewSyncability: TPPBPeerStableInfo_UserControllableViewStatus? + if [.ENABLED, .DISABLED].contains(stableInfo.syncUserControllableViews) { + // No change! + userViewSyncability = nil + } else { + let newUserViewSyncability: TPPBPeerStableInfo_UserControllableViewStatus + + if peerPermanentInfo.modelID.hasPrefix("AppleTV") || + peerPermanentInfo.modelID.hasPrefix("AudioAccessory") || + peerPermanentInfo.modelID.hasPrefix("Watch") { + // Watches, TVs, and AudioAccessories always join as FOLLOWING. + newUserViewSyncability = .FOLLOWING + } else { + // All other platforms select what the other devices say to do + newUserViewSyncability = self.model.userViewSyncabilityConsensusAmongTrustedPeers(dynamicInfo) + } + + os_log("join: setting 'user view sync' control as: %{public}@", log: tplogDebug, type: .default, + TPPBPeerStableInfo_UserControllableViewStatusAsString(newUserViewSyncability)) + userViewSyncability = newUserViewSyncability + } + + let newStableInfo = try self.createNewStableInfoIfNeeded(stableChanges: StableChanges.change(viewStatus: userViewSyncability), + permanentInfo: peerPermanentInfo, existingStableInfo: stableInfo, dynamicInfo: dynamicInfo, signingKeyPair: egoPeerKeys.signingKey) @@ -2887,17 +3068,17 @@ class Container: NSObject { ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], preapprovedKeys: [Data]?, - reply: @escaping (String?, [CKRecord], Set?, TPPolicy?, Error?) -> Void) { + reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) { self.semaphore.wait() - let reply: (String?, [CKRecord], Set?, TPPolicy?, Error?) -> Void = { - os_log("join complete: %{public}@", log: tplogTrace, type: .info, traceError($4)) + let reply: (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void = { + os_log("join complete: %{public}@", log: tplogTrace, type: .info, traceError($3)) self.semaphore.signal() - reply($0, $1, $2, $3, $4) + reply($0, $1, $2, $3) } self.fetchAndPersistChanges { error in guard error == nil else { - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } @@ -2910,11 +3091,11 @@ class Container: NSObject { self.moc.performAndWait { guard let voucher = TPVoucher(infoWith: voucherData, sig: voucherSig) else { - reply(nil, [], nil, nil, ContainerError.invalidVoucherOrSig) + reply(nil, [], nil, ContainerError.invalidVoucherOrSig) return } guard let sponsor = self.model.peer(withID: voucher.sponsorID) else { - reply(nil, [], nil, nil, ContainerError.sponsorNotRegistered(voucher.sponsorID)) + reply(nil, [], nil, ContainerError.sponsorNotRegistered(voucher.sponsorID)) return } @@ -2925,30 +3106,30 @@ class Container: NSObject { let egoStableData = self.containerMO.egoPeerStableInfo, let egoStableSig = self.containerMO.egoPeerStableInfoSig else { - reply(nil, [], nil, nil, ContainerError.noPreparedIdentity) + reply(nil, [], nil, ContainerError.noPreparedIdentity) return } let keyFactory = TPECPublicKeyFactory() guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - reply(nil, [], nil, nil, ContainerError.invalidPermanentInfoOrSig) + reply(nil, [], nil, ContainerError.invalidPermanentInfoOrSig) return } guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else { - reply(nil, [], nil, nil, ContainerError.invalidStableInfoOrSig) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) return } guard self.onqueueMachineIDAllowedByIDMS(machineID: selfPermanentInfo.machineID) else { os_log("join: self machineID %{public}@ not on list", log: tplogDebug, type: .debug, selfPermanentInfo.machineID) self.onqueueTTRUntrusted() - reply(nil, [], nil, nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) + reply(nil, [], nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) return } loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in guard let egoPeerKeys = egoPeerKeys else { os_log("Don't have my own peer keys; can't join: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } self.moc.performAndWait { @@ -2967,13 +3148,13 @@ class Container: NSObject { egoPeerKeys: egoPeerKeys) } catch { os_log("Unable to create peer for joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } guard let peerStableInfo = peer.stableInfoAndSig.toStableInfo() else { - os_log("Unable to create new peer stable new for joining", log: tplogDebug, type: .default) - reply(nil, [], nil, nil, ContainerError.invalidStableInfoOrSig) + os_log("Unable to create new peer stable info for joining", log: tplogDebug, type: .default) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) return } @@ -2987,7 +3168,7 @@ class Container: NSObject { epoch: Int(selfPermanentInfo.epoch)) } catch { os_log("Unable to process keys before joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } @@ -2997,7 +3178,7 @@ class Container: NSObject { withSponsorID: sponsor.peerID) } catch { os_log("Error checking introduction: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } @@ -3005,7 +3186,7 @@ class Container: NSObject { do { bottle = try self.assembleBottle(egoPeerID: egoPeerID) } catch { - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } @@ -3037,10 +3218,9 @@ class Container: NSObject { $0.viewKeys = viewKeys } self.cuttlefish.joinWithVoucher(request) { response, error in - os_log("JoinWithVoucher(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { os_log("joinWithVoucher failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, [], nil, nil, error ?? ContainerError.cloudkitResponseMissing) + reply(nil, [], nil, error ?? ContainerError.cloudkitResponseMissing) return } @@ -3049,17 +3229,17 @@ class Container: NSObject { self.containerMO.egoPeerStableInfo = peer.stableInfoAndSig.peerStableInfo self.containerMO.egoPeerStableInfoSig = peer.stableInfoAndSig.sig - let (syncingViews, policy) = try self.policyAndViewsFor(permanentInfo: selfPermanentInfo, - stableInfo: peerStableInfo) + let syncingPolicy = try self.syncingPolicyFor(modelID: selfPermanentInfo.modelID, + stableInfo: peerStableInfo) try self.onQueuePersist(changes: response.changes) os_log("JoinWithVoucher succeeded", log: tplogDebug) let keyHierarchyRecords = response.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } - reply(egoPeerID, keyHierarchyRecords, syncingViews, policy, nil) + reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil) } catch { os_log("JoinWithVoucher failed: %{public}@", log: tplogDebug, String(describing: error)) - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) } } } @@ -3135,8 +3315,6 @@ class Container: NSObject { } self.cuttlefish.getSupportAppInfo { response, error in - os_log("getSupportAppInfo(): %{public}@, error: %{public}@", log: tplogDebug, - "(\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { os_log("getSupportAppInfo failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") reply(nil, error ?? ContainerError.cloudkitResponseMissing) @@ -3150,10 +3328,10 @@ class Container: NSObject { reply(data, nil) } - } - func preflightPreapprovedJoin(reply: @escaping (Bool, Error?) -> Void) { + func preflightPreapprovedJoin(preapprovedKeys: [Data]?, + reply: @escaping (Bool, Error?) -> Void) { self.semaphore.wait() let reply: (Bool, Error?) -> Void = { os_log("preflightPreapprovedJoin complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) @@ -3205,6 +3383,16 @@ class Container: NSObject { return } + let keysApprovingPeers = preapprovedKeys?.filter { key in + self.model.hasPotentiallyTrustedPeer(withSigningKey: key) + } + + guard (keysApprovingPeers?.count ?? 0) > 0 else { + os_log("preflightPreapprovedJoin: no reciprocal trust for existing peers", log: tplogDebug, type: .debug) + reply(false, ContainerError.noPeersPreapprovedBySelf) + return + } + reply(true, nil) } } @@ -3213,18 +3401,18 @@ class Container: NSObject { func preapprovedJoin(ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], preapprovedKeys: [Data]?, - reply: @escaping (String?, [CKRecord], Set?, TPPolicy?, Error?) -> Void) { + reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) { self.semaphore.wait() - let reply: (String?, [CKRecord], Set?, TPPolicy?, Error?) -> Void = { - os_log("preapprovedJoin complete: %{public}@", log: tplogTrace, type: .info, traceError($4)) + let reply: (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void = { + os_log("preapprovedJoin complete: %{public}@", log: tplogTrace, type: .info, traceError($3)) self.semaphore.signal() - reply($0, $1, $2, $3, $4) + reply($0, $1, $2, $3) } self.fetchAndPersistChangesIfNeeded { error in guard error == nil else { os_log("preapprovedJoin unable to fetch changes: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } self.moc.performAndWait { @@ -3233,10 +3421,11 @@ class Container: NSObject { // That's up to the caller. if self.model.allPeerIDs().isEmpty { os_log("preapprovedJoin but no existing peers, attempting establish", log: tplogDebug, type: .debug) + self.onqueueEstablish(ckksKeys: ckksKeys, - tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys, - reply: reply) + tlkShares: tlkShares, + preapprovedKeys: preapprovedKeys, + reply: reply) return } @@ -3248,41 +3437,40 @@ class Container: NSObject { let egoStableSig = self.containerMO.egoPeerStableInfoSig else { os_log("preapprovedJoin: no prepared identity", log: tplogDebug, type: .debug) - reply(nil, [], nil, nil, ContainerError.noPreparedIdentity) + reply(nil, [], nil, ContainerError.noPreparedIdentity) return } let keyFactory = TPECPublicKeyFactory() guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - reply(nil, [], nil, nil, ContainerError.invalidPermanentInfoOrSig) + reply(nil, [], nil, ContainerError.invalidPermanentInfoOrSig) return } guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else { - reply(nil, [], nil, nil, ContainerError.invalidStableInfoOrSig) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) return } guard self.onqueueMachineIDAllowedByIDMS(machineID: selfPermanentInfo.machineID) else { os_log("preapprovedJoin: self machineID %{public}@ (me) not on list", log: tplogDebug, type: .debug, selfPermanentInfo.machineID) self.onqueueTTRUntrusted() - reply(nil, [], nil, nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) + reply(nil, [], nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID)) return } loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in guard let egoPeerKeys = egoPeerKeys else { os_log("preapprovedJoin: Don't have my own keys: can't join", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } guard self.model.hasPotentiallyTrustedPeerPreapprovingKey(egoPeerKeys.signingKey.publicKey().spki()) else { os_log("preapprovedJoin: no peers preapprove our key", log: tplogDebug, type: .debug) - reply(nil, [], nil, nil, ContainerError.noPeersPreapprovePreparedIdentity) + reply(nil, [], nil, ContainerError.noPeersPreapprovePreparedIdentity) return } self.moc.performAndWait { - let peer: Peer let newDynamicInfo: TPPeerDynamicInfo do { @@ -3295,13 +3483,13 @@ class Container: NSObject { egoPeerKeys: egoPeerKeys) } catch { os_log("Unable to create peer for joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } guard let peerStableInfo = peer.stableInfoAndSig.toStableInfo() else { - os_log("Unable to create new peer stable new for joining", log: tplogDebug, type: .default) - reply(nil, [], nil, nil, ContainerError.invalidStableInfoOrSig) + os_log("Unable to create new peer stable info for joining", log: tplogDebug, type: .default) + reply(nil, [], nil, ContainerError.invalidStableInfoOrSig) return } @@ -3309,13 +3497,13 @@ class Container: NSObject { let viewKeys: [ViewKeys] do { (viewKeys, allTLKShares) = try self.makeSharesForNewKeySets(ckksKeys: ckksKeys, - tlkShares: tlkShares, - egoPeerKeys: egoPeerKeys, - egoPeerDynamicInfo: newDynamicInfo, - epoch: Int(selfPermanentInfo.epoch)) + tlkShares: tlkShares, + egoPeerKeys: egoPeerKeys, + egoPeerDynamicInfo: newDynamicInfo, + epoch: Int(selfPermanentInfo.epoch)) } catch { os_log("Unable to process keys before joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } @@ -3323,7 +3511,7 @@ class Container: NSObject { do { bottle = try self.assembleBottle(egoPeerID: egoPeerID) } catch { - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) return } @@ -3355,10 +3543,9 @@ class Container: NSObject { $0.viewKeys = viewKeys } self.cuttlefish.joinWithVoucher(request) { response, error in - os_log("preapprovedJoin(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { os_log("preapprovedJoin failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, [], nil, nil, error ?? ContainerError.cloudkitResponseMissing) + reply(nil, [], nil, error ?? ContainerError.cloudkitResponseMissing) return } @@ -3367,17 +3554,17 @@ class Container: NSObject { self.containerMO.egoPeerStableInfo = peer.stableInfoAndSig.peerStableInfo self.containerMO.egoPeerStableInfoSig = peer.stableInfoAndSig.sig - let (syncingViews, policy) = try self.policyAndViewsFor(permanentInfo: selfPermanentInfo, - stableInfo: peerStableInfo) + let syncingPolicy = try self.syncingPolicyFor(modelID: selfPermanentInfo.modelID, + stableInfo: peerStableInfo) try self.onQueuePersist(changes: response.changes) os_log("preapprovedJoin succeeded", log: tplogDebug) let keyHierarchyRecords = response.zoneKeyHierarchyRecords.compactMap { CKRecord($0) } - reply(egoPeerID, keyHierarchyRecords, syncingViews, policy, nil) + reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil) } catch { os_log("preapprovedJoin failed: %{public}@", log: tplogDebug, String(describing: error)) - reply(nil, [], nil, nil, error) + reply(nil, [], nil, error) } } } @@ -3392,12 +3579,13 @@ class Container: NSObject { osVersion: String?, policyVersion: UInt64?, policySecrets: [String: Data]?, - reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus?, + reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) { self.semaphore.wait() - let reply: (TrustedPeersHelperPeerState?, Error?) -> Void = { - os_log("update complete: %{public}@", log: tplogTrace, type: .info, traceError($1)) + let reply: (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void = { + os_log("update complete: %{public}@", log: tplogTrace, type: .info, traceError($2)) self.semaphore.signal() - reply($0, $1) + reply($0, $1, $2) } // Get (and save) the latest from cuttlefish @@ -3405,7 +3593,8 @@ class Container: NSObject { serialNumber: serialNumber, osVersion: osVersion, policyVersion: policyVersion, - policySecrets: policySecrets) + policySecrets: policySecrets, + setSyncUserControllableViews: syncUserControllableViews) self.fetchChangesAndUpdateTrustIfNeeded(stableChanges: stableChanges, reply: reply) } @@ -3455,7 +3644,9 @@ class Container: NSObject { os_log("setPreapprovedKeys: no change; nothing to do.", log: tplogDebug, type: .default) // Calling this will fill in the peer status - self.updateTrustIfNeeded(reply: reply) + self.updateTrustIfNeeded { status, _, error in + reply(status, error) + } return } @@ -3466,7 +3657,7 @@ class Container: NSObject { $0.dynamicInfoAndSig = SignedPeerDynamicInfo(dynamicInfo) } - self.perform(updateTrust: request) { state, error in + self.perform(updateTrust: request) { state, _, error in guard error == nil else { os_log("setPreapprovedKeys: failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg? ?? "no error") reply(state, error) @@ -3496,11 +3687,11 @@ class Container: NSObject { self.moc.performAndWait { self.onqueueUpdateTLKs(ckksKeys: ckksKeys, tlkShares: tlkShares, reply: reply) } - } + } - func onqueueUpdateTLKs(ckksKeys: [CKKSKeychainBackedKeySet], - tlkShares: [CKKSTLKShare], - reply: @escaping ([CKRecord]?, Error?) -> Void) { + func onqueueUpdateTLKs(ckksKeys: [CKKSKeychainBackedKeySet], + tlkShares: [CKKSTLKShare], + reply: @escaping ([CKRecord]?, Error?) -> Void) { guard let egoPeerID = self.containerMO.egoPeerID, let egoPermData = self.containerMO.egoPeerPermanentInfo, let egoPermSig = self.containerMO.egoPeerPermanentInfoSig @@ -3518,7 +3709,7 @@ class Container: NSObject { loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in guard let egoPeerKeys = egoPeerKeys else { - os_log("Don't have my own peer keys; can't upload new TLKs: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") + os_log("Don't have my own peer keys; can't upload new TLKs: %@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing") reply(nil, error) return } @@ -3551,8 +3742,6 @@ class Container: NSObject { } self.cuttlefish.updateTrust(request) { response, error in - os_log("UpdateTrust(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") - guard error == nil else { reply(nil, error) return @@ -3584,6 +3773,18 @@ class Container: NSObject { } } + if self.containerMO.fullyViableEscrowRecords != nil { + self.containerMO.fullyViableEscrowRecords!.forEach { record in + state.escrowRecords.insert(record as! EscrowRecordMO) + } + } + + if self.containerMO.partiallyViableEscrowRecords != nil { + self.containerMO.partiallyViableEscrowRecords!.forEach { record in + state.escrowRecords.insert(record as! EscrowRecordMO) + } + } + self.model.allPeers().forEach { peer in state.peers[peer.peerID] = peer } @@ -3603,7 +3804,7 @@ class Container: NSObject { } } - private func fetchAndPersistChanges(reply: @escaping (Error?) -> Void) { + func fetchAndPersistChanges(reply: @escaping (Error?) -> Void) { self.moc.performAndWait { self.onqueueFetchAndPersistChanges(reply: reply) } @@ -3616,7 +3817,6 @@ class Container: NSObject { os_log("Fetching with change token: %{public}@", log: tplogDebug, type: .default, !request.changeToken.isEmpty ? request.changeToken : "empty") self.cuttlefish.fetchChanges(request) { response, error in - os_log("FetchChanges(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { switch error { case CuttlefishErrorMatcher(code: CuttlefishErrorCode.changeTokenExpired): @@ -3693,11 +3893,11 @@ class Container: NSObject { // (i.e. after reply is invoked). internal func fetchChangesAndUpdateTrustIfNeeded(stableChanges: StableChanges? = nil, peerChanges: Bool = false, - reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { + reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) { self.fetchAndPersistChanges { error in if let error = error { os_log("fetchChangesAndUpdateTrustIfNeeded: fetching failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, error) + reply(nil, nil, error) return } @@ -3716,18 +3916,22 @@ class Container: NSObject { // (i.e. after reply is invoked). private func updateTrustIfNeeded(stableChanges: StableChanges? = nil, peerChanges: Bool = false, - reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { + reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) { self.moc.performAndWait { guard let egoPeerID = self.containerMO.egoPeerID else { // No identity, nothing to do os_log("updateTrustIfNeeded: No identity.", log: tplogDebug, type: .default) - reply(TrustedPeersHelperPeerState(peerID: nil, isPreapproved: false, status: .unknown, memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil), nil) + reply(TrustedPeersHelperPeerState(peerID: nil, isPreapproved: false, status: .unknown, memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil), + nil, + nil) return } loadEgoKeyPair(identifier: signingKeyIdentifier(peerID: egoPeerID)) { signingKeyPair, error in guard let signingKeyPair = signingKeyPair else { os_log("updateTrustIfNeeded: no signing key pair: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(TrustedPeersHelperPeerState(peerID: nil, isPreapproved: false, status: .unknown, memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil), error) + reply(TrustedPeersHelperPeerState(peerID: nil, isPreapproved: false, status: .unknown, memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil), + nil, + error) return } guard let currentSelfInModel = self.model.peer(withID: egoPeerID) else { @@ -3740,6 +3944,7 @@ class Container: NSObject { memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil), + nil, nil) return } @@ -3755,7 +3960,6 @@ class Container: NSObject { let dynamicInfo: TPPeerDynamicInfo var stableInfo: TPPeerStableInfo? do { - // FIXME We should be able to calculate the contents of dynamicInfo without the signingKeyPair, // and then only load the key if it has changed and we need to sign a new one. This would also // help make our detection of change immune from non-canonical serialization of dynamicInfo. @@ -3767,7 +3971,7 @@ class Container: NSObject { currentMachineIDs: self.onqueueCurrentMIDList()) stableInfo = try self.createNewStableInfoIfNeeded(stableChanges: stableChanges, - egoPeerID: egoPeerID, + permanentInfo: currentSelfInModel.permanentInfo, existingStableInfo: currentSelfInModel.stableInfo, dynamicInfo: dynamicInfo, signingKeyPair: signingKeyPair) @@ -3779,6 +3983,7 @@ class Container: NSObject { memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil), + nil, error) return } @@ -3798,12 +4003,25 @@ class Container: NSObject { os_log("updateTrustIfNeeded: unable to remove untrusted MachineIDs: %{public}@", log: tplogDebug, type: .default, error as CVarArg) } + let syncingPolicy: TPSyncingPolicy? + do { + if let peer = self.model.peer(withID: egoPeerID), let stableInfo = peer.stableInfo { + syncingPolicy = try self.syncingPolicyFor(modelID: peer.permanentInfo.modelID, stableInfo: stableInfo) + } else { + syncingPolicy = nil + } + } catch { + os_log("updateTrustIfNeeded: unable to compute a new syncing policy: %{public}@", log: tplogDebug, type: .default, error as CVarArg) + syncingPolicy = nil + } + reply(TrustedPeersHelperPeerState(peerID: egoPeerID, isPreapproved: false, status: self.model.statusOfPeer(withID: egoPeerID), memberChanges: peerChanges, unknownMachineIDs: self.onqueueFullIDMSListWouldBeHelpful(), osVersion: peer?.stableInfo?.osVersion), + syncingPolicy, nil) return } @@ -3811,7 +4029,7 @@ class Container: NSObject { let havePeerChanges = peerChanges || self.haveTrustMemberChanges(newDynamicInfo: dynamicInfo, oldDynamicInfo: peer?.dynamicInfo) let signedDynamicInfo = SignedPeerDynamicInfo(dynamicInfo) - os_log("updateTrustIfNeeded: attempting updateTrust for %{public}@ with: %{public}@", log: tplogDebug, type: .default, egoPeerID, dynamicInfo) + os_log("updateTrustIfNeeded: attempting updateTrust for %{public}@ with: %{public}@", log: tplogDebug, type: .default, egoPeerID, dynamicInfo) var request = UpdateTrustRequest.with { $0.changeToken = self.containerMO.changeToken ?? "" $0.peerID = egoPeerID @@ -3831,13 +4049,11 @@ class Container: NSObject { private func perform(updateTrust request: UpdateTrustRequest, stableChanges: StableChanges? = nil, peerChanges: Bool = false, - reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) { - + reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) { self.cuttlefish.updateTrust(request) { response, error in - os_log("UpdateTrust(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") guard let response = response, error == nil else { os_log("UpdateTrust failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error") - reply(nil, error ?? ContainerError.cloudkitResponseMissing) + reply(nil, nil, error ?? ContainerError.cloudkitResponseMissing) return } @@ -3845,7 +4061,7 @@ class Container: NSObject { try self.persist(changes: response.changes) } catch { os_log("UpdateTrust failed: %{public}@", log: tplogDebug, String(describing: error)) - reply(nil, error) + reply(nil, nil, error) return } @@ -3892,15 +4108,14 @@ class Container: NSObject { if !changes.differences.isEmpty { self.model.clearViableBottles() + os_log("escrow cache and viable bottles are no longer valid", log: tplogDebug, type: .default) + self.onQueueRemoveEscrowCache() } try changes.differences.forEach { peerDifference in if let operation = peerDifference.operation { switch operation { - case .add(let peer): - try self.addOrUpdate(peer: peer) - - case .update(let peer): + case .add(let peer), .update(let peer): try self.addOrUpdate(peer: peer) // Update containerMO ego data if it has changed. if peer.peerID == self.containerMO.egoPeerID { @@ -3939,12 +4154,25 @@ class Container: NSObject { peerRequest.predicate = NSPredicate(format: "container == %@", self.containerMO) try self.moc.execute(NSBatchDeleteRequest(fetchRequest: peerRequest)) - let bottleRequest = NSFetchRequest(entityName: "Bottle") - bottleRequest.predicate = NSPredicate(format: "container == %@", self.containerMO) - try self.moc.execute(NSBatchDeleteRequest(fetchRequest: bottleRequest)) + // If we have an ego peer ID, keep the bottle associated with it + if let peerID = self.containerMO.egoPeerID, let bottles = self.containerMO.bottles { + let nonPeerBottles = NSSet(array: bottles.filter { + switch $0 { + case let bottleMO as BottleMO: + return bottleMO.peerID != peerID + default: + return false + } + }) + self.containerMO.removeFromBottles(nonPeerBottles as NSSet) + } else { + let bottleRequest = NSFetchRequest(entityName: "Bottle") + bottleRequest.predicate = NSPredicate(format: "container == %@", self.containerMO) + try self.moc.execute(NSBatchDeleteRequest(fetchRequest: bottleRequest)) + self.containerMO.bottles = nil + } self.containerMO.peers = nil - self.containerMO.bottles = nil self.containerMO.changeToken = nil self.containerMO.moreChanges = false @@ -3961,7 +4189,7 @@ class Container: NSObject { // Must be on moc queue to call this. private func addOrUpdate(signingKey: Data, encryptionKey: Data) { self.model.setRecoveryKeys( - TPRecoveryKeyPair(signingSPKI: signingKey, encryptionSPKI: encryptionKey)) + TPRecoveryKeyPair(signingKeyData: signingKey, encryptionKeyData: encryptionKey)) self.containerMO.recoveryKeySigningSPKI = signingKey self.containerMO.recoveryKeyEncryptionSPKI = encryptionKey @@ -3989,7 +4217,9 @@ class Container: NSObject { } else { // Update: // The assertion here is that every peer registered in model is also present in containerMO - let peerMO = try self.fetchPeerMO(peerID: peer.peerID)! + guard let peerMO = try self.fetchPeerMO(peerID: peer.peerID) else { + throw ContainerError.peerRegisteredButNotStored(peer.peerID) + } if let stableInfo = peer.stableInfoAndSig.toStableInfo() { try self.model.update(stableInfo, forPeerWithID: peer.peerID) @@ -4010,10 +4240,12 @@ class Container: NSObject { peer.vouchers.forEach { if let voucher = TPVoucher(infoWith: $0.voucher, sig: $0.sig) { self.model.register(voucher) - let voucherMO = VoucherMO(context: self.moc) - voucherMO.voucherInfo = voucher.data - voucherMO.voucherInfoSig = voucher.sig - peerMO.addToVouchers(voucherMO) + if peer.vouchers.filter({ $0.voucher == voucher.data && $0.sig == voucher.sig }).isEmpty { + let voucherMO = VoucherMO(context: self.moc) + voucherMO.voucherInfo = voucher.data + voucherMO.voucherInfoSig = voucher.sig + peerMO.addToVouchers(voucherMO) + } } } } @@ -4041,7 +4273,7 @@ class Container: NSObject { // Must be on moc queue to call this. private func createNewStableInfoIfNeeded(stableChanges: StableChanges?, - egoPeerID: String, + permanentInfo: TPPeerPermanentInfo, existingStableInfo: TPPeerStableInfo?, dynamicInfo: TPPeerDynamicInfo, signingKeyPair: _SFECKeyPair) throws -> TPPeerStableInfo? { @@ -4050,41 +4282,53 @@ class Container: NSObject { } let policyOfPeers = try? self.model.policy(forPeerIDs: dynamicInfo.includedPeerIDs, - candidatePeerID: egoPeerID, + candidatePeerID: permanentInfo.peerID, candidateStableInfo: existingStableInfo) // Pick the best version of: // 1. The policy version asked for by the client - // 2. The max of our existing policyVersion, the highest policy used by our trusted peers, and the compile-time prevailing policy version + // 2. The policy override set on this object (tests only) + // 3. The max of our existing policyVersion, the highest policy used by our trusted peers, and the compile-time prevailing policy version let optimalPolicyVersionNumber = stableChanges?.policyVersion ?? - max(existingStableInfo?.bestPolicyVersion().versionNumber ?? prevailingPolicyVersion.versionNumber, - policyOfPeers?.version.versionNumber ?? prevailingPolicyVersion.versionNumber, - prevailingPolicyVersion.versionNumber) + self.policyVersionOverride?.versionNumber ?? + max(existingStableInfo?.bestPolicyVersion().versionNumber ?? prevailingPolicyVersion.versionNumber, + policyOfPeers?.version.versionNumber ?? prevailingPolicyVersion.versionNumber, + prevailingPolicyVersion.versionNumber) // Determine which recovery key we'd like to be using, given our current idea of who to trust let optimalRecoveryKey = self.model.bestRecoveryKey(for: existingStableInfo, dynamicInfo: dynamicInfo) + let intendedSyncUserControllableViews = stableChanges?.setSyncUserControllableViews?.sanitizeForPlatform(permanentInfo: permanentInfo) + if noChange(stableChanges?.deviceName, existingStableInfo?.deviceName) && noChange(stableChanges?.serialNumber, existingStableInfo?.serialNumber) && noChange(stableChanges?.osVersion, existingStableInfo?.osVersion) && noChange(optimalPolicyVersionNumber, existingStableInfo?.bestPolicyVersion().versionNumber) && noChange(stableChanges?.policySecrets, existingStableInfo?.policySecrets) && - noChange(optimalRecoveryKey?.signingSPKI, existingStableInfo?.recoverySigningPublicKey) && - noChange(optimalRecoveryKey?.encryptionSPKI, existingStableInfo?.recoveryEncryptionPublicKey) { + noChange(optimalRecoveryKey?.signingKeyData, existingStableInfo?.recoverySigningPublicKey) && + noChange(optimalRecoveryKey?.encryptionKeyData, existingStableInfo?.recoveryEncryptionPublicKey) && + noChange(intendedSyncUserControllableViews, existingStableInfo?.syncUserControllableViews) { return nil } + // If a test has asked a policy version before we froze this policy, then don't set a flexible version--it's trying to build a peer from before the policy was frozen let optimalPolicyVersion = try self.getPolicyDoc(optimalPolicyVersionNumber).version + let useFrozenPolicyVersion = optimalPolicyVersion.versionNumber >= frozenPolicyVersion.versionNumber + + if let intendedSyncUserControllableViews = intendedSyncUserControllableViews { + os_log("Intending to set user-controllable views to %{public}@", log: tplogTrace, type: .info, TPPBPeerStableInfo_UserControllableViewStatusAsString(intendedSyncUserControllableViews)) + } - return try self.model.createStableInfo(withFrozenPolicyVersion: frozenPolicyVersion, - flexiblePolicyVersion: optimalPolicyVersion, + return try self.model.createStableInfo(withFrozenPolicyVersion: useFrozenPolicyVersion ? frozenPolicyVersion : optimalPolicyVersion, + flexiblePolicyVersion: useFrozenPolicyVersion ? optimalPolicyVersion : nil, policySecrets: stableChanges?.policySecrets ?? existingStableInfo?.policySecrets, + syncUserControllableViews: intendedSyncUserControllableViews ?? existingStableInfo?.syncUserControllableViews ?? .UNKNOWN, deviceName: stableChanges?.deviceName ?? existingStableInfo?.deviceName ?? "", serialNumber: stableChanges?.serialNumber ?? existingStableInfo?.serialNumber ?? "", osVersion: stableChanges?.osVersion ?? existingStableInfo?.osVersion ?? "", signing: signingKeyPair, - recoverySigningPubKey: optimalRecoveryKey?.signingSPKI, - recoveryEncryptionPubKey: optimalRecoveryKey?.encryptionSPKI) + recoverySigningPubKey: optimalRecoveryKey?.signingKeyData, + recoveryEncryptionPubKey: optimalRecoveryKey?.encryptionKeyData) } private func assembleBottle(egoPeerID: String) throws -> Bottle { @@ -4097,7 +4341,9 @@ class Container: NSObject { if let count = bottleMOs?.count { if count > 1 { throw ContainerError.tooManyBottlesForPeer + // swiftlint:disable empty_count } else if count == 0 { + // swiftlint:enable empty_count throw ContainerError.noBottleForPeer } } else { @@ -4160,8 +4406,7 @@ class Container: NSObject { } self.moc.performAndWait { - self.cuttlefish.reportHealth(updatedRequest) { response, error in - os_log("reportHealth(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))") + self.cuttlefish.reportHealth(updatedRequest) { _, error in guard error == nil else { reply(error) return @@ -4180,8 +4425,7 @@ class Container: NSObject { } self.moc.performAndWait { - self.cuttlefish.pushHealthInquiry(PushHealthInquiryRequest()) { response, error in - os_log("pushHealthInquiry(): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: response))", "\(String(describing: error))") + self.cuttlefish.pushHealthInquiry(PushHealthInquiryRequest()) { _, error in guard error == nil else { reply(error) return diff --git a/keychain/TrustedPeersHelper/ContainerMap.swift b/keychain/TrustedPeersHelper/ContainerMap.swift index 73a8fdfa..7f6e03c5 100644 --- a/keychain/TrustedPeersHelper/ContainerMap.swift +++ b/keychain/TrustedPeersHelper/ContainerMap.swift @@ -47,7 +47,7 @@ func ~= (pattern: CKInternalErrorMatcher, value: Error?) -> Bool { return false } return error.domain == CKErrorDomain && error.code == pattern.code && - underlyingError.domain == CKInternalErrorDomain && underlyingError.code == pattern.internalCode + underlyingError.domain == CKInternalErrorDomain && underlyingError.code == pattern.internalCode } struct CKErrorMatcher { @@ -83,7 +83,7 @@ public class RetryingInvocable: CloudKitCode.Invocable { self.underlyingInvocable = retry } - public class func retryableError(error: Error?) -> Bool { + public class func retryableError(error: Error?) -> Bool { switch error { case NSURLErrorMatcher(code: NSURLErrorTimedOut): return true @@ -120,34 +120,33 @@ public class RetryingInvocable: CloudKitCode.Invocable { deadline: Date, minimumDelay: TimeInterval, completion: @escaping (ResponseType?, Error?) -> Void) { - self.underlyingInvocable.invoke(function: function, request: request) { (response: ResponseType?, error: Error?) in - if let error = error, RetryingInvocable.retryableError(error: error) { - let now = Date() - - // Check cuttlefish and CKError retry afters. - let cuttlefishDelay = CuttlefishRetryAfter(error: error) - let ckDelay = CKRetryAfterSecondsForError(error) - let delay = max(minimumDelay, cuttlefishDelay, ckDelay) - let cutoff = Date(timeInterval: delay, since: now) - - guard cutoff.compare(deadline) == ComparisonResult.orderedDescending else { - Thread.sleep(forTimeInterval: delay) - os_log("%{public}@ error: %{public}@ (retrying, now=%{public}@, deadline=%{public}@)", log: tplogDebug, - function, - "\(String(describing: error))", - "\(String(describing: now))", - "\(String(describing: deadline))") - self.invokeRetry(function: function, - request: request, - deadline: deadline, - minimumDelay: minimumDelay, - completion: completion) - return - } - } - completion(response, error) + if let error = error, RetryingInvocable.retryableError(error: error) { + let now = Date() + + // Check cuttlefish and CKError retry afters. + let cuttlefishDelay = CuttlefishRetryAfter(error: error) + let ckDelay = CKRetryAfterSecondsForError(error) + let delay = max(minimumDelay, cuttlefishDelay, ckDelay) + let cutoff = Date(timeInterval: delay, since: now) + + guard cutoff.compare(deadline) == ComparisonResult.orderedDescending else { + Thread.sleep(forTimeInterval: delay) + os_log("%{public}@ error: %{public}@ (retrying, now=%{public}@, deadline=%{public}@)", log: tplogDebug, + function, + "\(String(describing: error))", + "\(String(describing: now))", + "\(String(describing: deadline))") + self.invokeRetry(function: function, + request: request, + deadline: deadline, + minimumDelay: minimumDelay, + completion: completion) + return + } + } + completion(response, error) } } } @@ -172,10 +171,8 @@ public class MyCodeConnection: CloudKitCode.Invocable { public func invoke( function: String, request: RequestType, completion: @escaping (ResponseType?, Error?) -> Void) { - // Hack to fool CloudKit, real solution is tracked in self.queue.async { - let operation = CodeOperation( service: self.serviceName, functionName: function, @@ -213,8 +210,7 @@ public class MyCodeConnection: CloudKitCode.Invocable { operation.configuration.discretionaryNetworkBehavior = .nonDiscretionary operation.configuration.automaticallyRetryNetworkFailures = false operation.configuration.isCloudKitSupportOperation = true - - operation.configuration.sourceApplicationBundleIdentifier = CuttlefishPushTopicBundleIdentifier + operation.configuration.setApplicationBundleIdentifierOverride(CuttlefishPushTopicBundleIdentifier) let database = self.container.database(with: self.databaseScope) @@ -234,7 +230,7 @@ class CKCodeCuttlefishInvocableCreator: ContainerNameToCuttlefishInvocable { // Cuttlefish is using its own push topic. // To register for this push topic, we need to issue CK operations with a specific bundle identifier - ckContainer.sourceApplicationBundleIdentifier = CuttlefishPushTopicBundleIdentifier + ckContainer.options.setApplicationBundleIdentifierOverride(CuttlefishPushTopicBundleIdentifier) let ckDatabase = ckContainer.privateCloudDatabase return MyCodeConnection(service: "Cuttlefish", container: ckContainer, @@ -262,7 +258,6 @@ class ContainerMap { if let container = self.containers[name] { return container } else { - // Set up Core Data stack let persistentStoreURL = ContainerMap.urlForPersistentStore(name: name) let description = NSPersistentStoreDescription(url: persistentStoreURL) @@ -291,4 +286,12 @@ class ContainerMap { self.containers.removeAll() } } + + func deleteAllPersistentStores() throws { + try queue.sync { + try self.containers.forEach { + try $0.value.deletePersistentStore() + } + } + } } diff --git a/keychain/TrustedPeersHelper/Container_BottledPeers.swift b/keychain/TrustedPeersHelper/Container_BottledPeers.swift index ff281dae..e9908f5b 100644 --- a/keychain/TrustedPeersHelper/Container_BottledPeers.swift +++ b/keychain/TrustedPeersHelper/Container_BottledPeers.swift @@ -2,80 +2,105 @@ import CoreData import Foundation extension Container { + func onMOCQueueFindBottle(bottleID: String) throws -> (BottleMO) { + guard let containerBottles = self.containerMO.bottles as? Set else { + throw ContainerError.noBottlesPresent + } + + let bottles = containerBottles.filter { $0.bottleID == bottleID } + + guard let bottle = bottles.first else { + throw ContainerError.noBottlesForEscrowRecordID + } + + return bottle + } + func preflightVouchWithBottle(bottleID: String, - reply: @escaping (String?, Set?, TPPolicy?, Error?) -> Void) { + reply: @escaping (String?, TPSyncingPolicy?, Bool, Error?) -> Void) { self.semaphore.wait() - let reply: (String?, Set?, TPPolicy?, Error?) -> Void = { + let reply: (String?, TPSyncingPolicy?, Bool, Error?) -> Void = { os_log("preflightVouchWithBottle complete: %{public}@", log: tplogTrace, type: .info, traceError($3)) self.semaphore.signal() reply($0, $1, $2, $3) } - self.fetchAndPersistChangesIfNeeded { fetchError in - guard fetchError == nil else { - os_log("preflightVouchWithBottle unable to fetch current peers: %{public}@", log: tplogDebug, type: .default, (fetchError as CVarArg?) ?? "") - reply(nil, nil, nil, fetchError) - return - } + self.moc.performAndWait { + do { + let (_, peerID, syncingPolicy) = try self.onMOCQueuePerformPreflight(bottleID: bottleID) + reply(peerID, syncingPolicy, false, nil) + } catch { + os_log("preflightVouchWithBottle failed; forcing refetch and retrying: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - // Ensure we have all policy versions claimed by peers, including our sponsor - let allPolicyVersions = self.model.allPolicyVersions() - self.fetchPolicyDocumentsWithSemaphore(versions: allPolicyVersions) { _, fetchPolicyDocumentsError in - guard fetchPolicyDocumentsError == nil else { - os_log("preflightVouchWithBottle unable to fetch policy documents: %{public}@", log: tplogDebug, type: .default, (fetchPolicyDocumentsError as CVarArg?) ?? "no error") - reply(nil, nil, nil, fetchPolicyDocumentsError) - return - } - - self.moc.performAndWait { - guard let egoPeerID = self.containerMO.egoPeerID, - let egoPermData = self.containerMO.egoPeerPermanentInfo, - let egoPermSig = self.containerMO.egoPeerPermanentInfoSig else { - os_log("fetchCurrentPolicy failed to find ego peer information", log: tplogDebug, type: .error) - reply(nil, nil, nil, ContainerError.noPreparedIdentity) - return - } - - let keyFactory = TPECPublicKeyFactory() - guard let egoPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - os_log("fetchCurrentPolicy failed to create TPPeerPermanentInfo", log: tplogDebug, type: .error) - reply(nil, nil, nil, ContainerError.invalidPermanentInfoOrSig) + self.fetchAndPersistChanges { fetchError in + guard fetchError == nil else { + os_log("preflightVouchWithBottle unable to fetch current peers: %{public}@", log: tplogDebug, type: .default, (fetchError as CVarArg?) ?? "") + reply(nil, nil, true, fetchError) return } - self.onqueueFindBottle(bottleID: bottleID) { bottleMO, error in - guard let bottleMO = bottleMO else { - os_log("preflightVouchWithBottle found no bottle: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(nil, nil, nil, error) - return - } - - guard let sponsorPeer = self.model.peer(withID: bottleMO.peerID ?? "") else { - os_log("preflightVouchWithBottle found no peer to match bottle", log: tplogDebug, type: .default) - reply(nil, nil, nil, ContainerError.sponsorNotRegistered(bottleMO.peerID ?? "no peer ID given")) - return - } - - guard let sponsorPeerStableInfo = sponsorPeer.stableInfo else { - os_log("preflightVouchWithBottle sponsor peer has no stable info", log: tplogDebug, type: .default) - reply(nil, nil, nil, ContainerError.sponsorNotRegistered(bottleMO.peerID ?? "no peer ID given")) + // Ensure we have all policy versions claimed by peers, including our sponsor + let allPolicyVersions = self.model.allPolicyVersions() + self.fetchPolicyDocumentsWithSemaphore(versions: allPolicyVersions) { _, fetchPolicyDocumentsError in + guard fetchPolicyDocumentsError == nil else { + os_log("preflightVouchWithBottle unable to fetch policy documents: %{public}@", log: tplogDebug, type: .default, (fetchPolicyDocumentsError as CVarArg?) ?? "no error") + reply(nil, nil, true, fetchPolicyDocumentsError) return } - do { - // We need to extract the syncing policy that the remote peer would have used (if they were the type of device that we are) - // So, figure out their policy version... - let (views, policy) = try self.policyAndViewsFor(permanentInfo: egoPermanentInfo, stableInfo: sponsorPeerStableInfo) + self.fetchViableBottlesWithSemaphore { _, _, fetchBottlesError in + guard fetchBottlesError == nil else { + os_log("preflightVouchWithBottle unable to fetch viable bottles: %{public}@", log: tplogDebug, type: .default, (fetchPolicyDocumentsError as CVarArg?) ?? "no error") + reply(nil, nil, true, fetchBottlesError) + return + } - reply(bottleMO.peerID, views, policy, nil) - } catch { - os_log("preflightVouchWithBottle failed to fetch policy: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") - reply(nil, nil, nil, error) + // and try again: + self.moc.performAndWait { + do { + let (_, peerID, syncingPolicy) = try self.onMOCQueuePerformPreflight(bottleID: bottleID) + reply(peerID, syncingPolicy, true, nil) + } catch { + os_log("preflightVouchWithBottle failed after refetches; failing: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "") + reply(nil, nil, true, error) + } + } } } } } } } + + func onMOCQueuePerformPreflight(bottleID: String) throws -> (BottleMO, String, TPSyncingPolicy) { + guard let egoPeerID = self.containerMO.egoPeerID, + let egoPermData = self.containerMO.egoPeerPermanentInfo, + let egoPermSig = self.containerMO.egoPeerPermanentInfoSig else { + os_log("fetchCurrentPolicy failed to find ego peer information", log: tplogDebug, type: .error) + throw ContainerError.noPreparedIdentity + } + + let keyFactory = TPECPublicKeyFactory() + guard let egoPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { + os_log("fetchCurrentPolicy failed to create TPPeerPermanentInfo", log: tplogDebug, type: .error) + throw ContainerError.invalidPermanentInfoOrSig + } + + let bottleMO = try self.onMOCQueueFindBottle(bottleID: bottleID) + + guard let sponsorPeer = self.model.peer(withID: bottleMO.peerID ?? "") else { + os_log("preflightVouchWithBottle found no peer to match bottle", log: tplogDebug, type: .default) + throw ContainerError.sponsorNotRegistered(bottleMO.peerID ?? "no peer ID given") + } + + guard let sponsorPeerStableInfo = sponsorPeer.stableInfo else { + os_log("preflightVouchWithBottle sponsor peer has no stable info", log: tplogDebug, type: .default) + throw ContainerError.sponsorNotRegistered(bottleMO.peerID ?? "no peer ID given") + } + + // We need to extract the syncing policy that the remote peer would have used (if they were the type of device that we are) + let policy = try self.syncingPolicyFor(modelID: egoPermanentInfo.modelID, stableInfo: sponsorPeerStableInfo) + return (bottleMO, sponsorPeer.peerID, policy) + } } diff --git a/keychain/TrustedPeersHelper/Container_EscrowRecords.swift b/keychain/TrustedPeersHelper/Container_EscrowRecords.swift new file mode 100644 index 00000000..89bdc206 --- /dev/null +++ b/keychain/TrustedPeersHelper/Container_EscrowRecords.swift @@ -0,0 +1,202 @@ +import CoreData +import Foundation + +extension Container { + + func onqueueCachedRecordsContainEgoPeerBottle(cachedRecords: [OTEscrowRecord]) -> Bool { + guard let egoPeerID = self.containerMO.egoPeerID else { + os_log("onqueueCachedRecordsContainEgoPeerBottle: No identity.", log: tplogDebug, type: .default) + return false + } + guard let bottles: Set = self.containerMO.bottles as? Set else { + os_log("onqueueCachedRecordsContainEgoPeerBottle: No Bottles.", log: tplogDebug, type: .default) + return false + } + var matchesCached: Bool = false + for bottle in bottles { + guard let bottleID: String = bottle.bottleID else { + continue + } + if bottle.peerID == egoPeerID && (cachedRecords.compactMap { $0.escrowInformationMetadata.bottleId }).contains(bottleID) { + matchesCached = true + break + } + } + return matchesCached + } + + func escrowRecordMOToEscrowRecords(record: EscrowRecordMO, viability: Viability) -> OTEscrowRecord? { + let escrowRecord = OTEscrowRecord() + let escrowRecordMetadata = OTEscrowRecordMetadata() + let clientMetadata = OTEscrowRecordMetadataClientMetadata() + + if let e = escrowRecord { + if let creationDate = record.creationDate { + e.creationDate = UInt64(creationDate.timeIntervalSince1970) + } + e.label = record.label ?? "" + e.remainingAttempts = UInt64(record.remainingAttempts) + e.silentAttemptAllowed = UInt64(record.silentAttemptAllowed) + e.recordStatus = record.recordStatus == 0 ? .RECORD_STATUS_VALID : .RECORD_STATUS_INVALID + + switch viability { + case .full: + e.recordViability = .RECORD_VIABILITY_FULLY_VIABLE + case .partial: + e.recordViability = .RECORD_VIABILITY_PARTIALLY_VIABLE + case .none: + e.recordViability = .RECORD_VIABILITY_LEGACY + } + + switch record.sosViability { + case 0: + e.viabilityStatus = .SOS_VIABLE_UNKNOWN + case 1: + e.viabilityStatus = .SOS_VIABLE + case 2: + e.viabilityStatus = .SOS_NOT_VIABLE + default: + e.viabilityStatus = .SOS_VIABLE_UNKNOWN + } + + if let metadata = escrowRecordMetadata { + if let m = record.escrowMetadata { + metadata.backupKeybagDigest = m.backupKeybagDigest ?? Data() + if let timestamp = m.secureBackupTimestamp { + metadata.secureBackupTimestamp = UInt64(timestamp.timeIntervalSince1970) + } + metadata.secureBackupUsesMultipleIcscs = UInt64(m.secureBackupUsesMultipleiCSCS) + metadata.bottleId = m.bottleID ?? "" + metadata.escrowedSpki = m.escrowedSPKI ?? Data() + metadata.peerInfo = m.peerInfo ?? Data() + metadata.serial = m.serial ?? "" + if let cmToFill = clientMetadata { + if let cm = m.clientMetadata { + cmToFill.deviceMid = cm.deviceMid ?? "" + cmToFill.deviceColor = cm.deviceColor ?? "" + cmToFill.deviceModel = cm.deviceModel ?? "" + cmToFill.deviceName = cm.deviceName ?? "" + cmToFill.devicePlatform = UInt64(cm.devicePlatform) + cmToFill.deviceModelClass = cm.deviceModelClass ?? "" + cmToFill.deviceModelVersion = cm.deviceModelVersion ?? "" + cmToFill.deviceEnclosureColor = cm.deviceEnclosureColor ?? "" + if let timestamp = cm.secureBackupMetadataTimestamp { + cmToFill.secureBackupMetadataTimestamp = UInt64(timestamp.timeIntervalSince1970) + } + cmToFill.secureBackupUsesComplexPassphrase = UInt64(cm.secureBackupUsesComplexPassphrase) + cmToFill.secureBackupUsesNumericPassphrase = UInt64(cm.secureBackupUsesNumericPassphrase) + cmToFill.secureBackupNumericPassphraseLength = UInt64(cm.secureBackupNumericPassphraseLength) + } + } + metadata.clientMetadata = clientMetadata + } + e.escrowInformationMetadata = metadata + } + } + + return escrowRecord + } + + func setEscrowRecord(record: EscrowInformation, viability: Viability) { + let escrowRecordMO = EscrowRecordMO(context: self.moc) + escrowRecordMO.label = record.label + escrowRecordMO.creationDate = record.creationDate.date + escrowRecordMO.remainingAttempts = Int64(record.remainingAttempts) + escrowRecordMO.silentAttemptAllowed = Int64(record.silentAttemptAllowed) + escrowRecordMO.recordStatus = Int64(record.recordStatus.rawValue) + escrowRecordMO.sosViability = Int64(record.viabilityStatus.rawValue) + + let escrowRecordMetadataMO = EscrowMetadataMO(context: self.moc) + escrowRecordMetadataMO.backupKeybagDigest = record.escrowInformationMetadata.backupKeybagDigest + escrowRecordMetadataMO.secureBackupUsesMultipleiCSCS = Int64(record.escrowInformationMetadata.secureBackupUsesMultipleIcscs) + escrowRecordMetadataMO.bottleID = record.escrowInformationMetadata.bottleID + escrowRecordMetadataMO.secureBackupTimestamp = record.escrowInformationMetadata.secureBackupTimestamp.date + escrowRecordMetadataMO.escrowedSPKI = record.escrowInformationMetadata.escrowedSpki + escrowRecordMetadataMO.peerInfo = record.escrowInformationMetadata.peerInfo + escrowRecordMetadataMO.serial = record.escrowInformationMetadata.serial + escrowRecordMO.escrowMetadata = escrowRecordMetadataMO + + let escrowRecordClientMetadataMO = EscrowClientMetadataMO(context: self.moc) + escrowRecordClientMetadataMO.secureBackupMetadataTimestamp = record.escrowInformationMetadata.clientMetadata.secureBackupMetadataTimestamp.date + escrowRecordClientMetadataMO.secureBackupNumericPassphraseLength = Int64(record.escrowInformationMetadata.clientMetadata.secureBackupNumericPassphraseLength) + escrowRecordClientMetadataMO.secureBackupUsesComplexPassphrase = Int64(record.escrowInformationMetadata.clientMetadata.secureBackupUsesComplexPassphrase) + escrowRecordClientMetadataMO.secureBackupUsesNumericPassphrase = Int64(record.escrowInformationMetadata.clientMetadata.secureBackupUsesNumericPassphrase) + escrowRecordClientMetadataMO.deviceColor = record.escrowInformationMetadata.clientMetadata.deviceColor + escrowRecordClientMetadataMO.deviceEnclosureColor = record.escrowInformationMetadata.clientMetadata.deviceEnclosureColor + escrowRecordClientMetadataMO.deviceMid = record.escrowInformationMetadata.clientMetadata.deviceMid + escrowRecordClientMetadataMO.deviceModel = record.escrowInformationMetadata.clientMetadata.deviceModel + escrowRecordClientMetadataMO.deviceModelClass = record.escrowInformationMetadata.clientMetadata.deviceModelClass + escrowRecordClientMetadataMO.deviceModelVersion = record.escrowInformationMetadata.clientMetadata.deviceModelVersion + escrowRecordClientMetadataMO.deviceName = record.escrowInformationMetadata.clientMetadata.deviceName + escrowRecordClientMetadataMO.devicePlatform = Int64(record.escrowInformationMetadata.clientMetadata.devicePlatform) + + escrowRecordMetadataMO.clientMetadata = escrowRecordClientMetadataMO + + os_log("setEscrowRecord saving new escrow record: %@", log: tplogDebug, type: .default, escrowRecordMO) + switch viability { + case .full: + self.containerMO.addToFullyViableEscrowRecords(escrowRecordMO) + break + case .partial: + self.containerMO.addToPartiallyViableEscrowRecords(escrowRecordMO) + break + case .none: + self.containerMO.addToLegacyEscrowRecords(escrowRecordMO) + break + } + } + + func onqueueCachedBottlesFromEscrowRecords() -> (TPCachedViableBottles) { + var viableRecords: [String] = [] + var partiallyViableRecords: [String] = [] + + if let fullyViableEscrowRecords = self.containerMO.fullyViableEscrowRecords as? Set { + viableRecords = fullyViableEscrowRecords.compactMap { $0.escrowMetadata?.bottleID } + } + if let partiallyViableEscrowRecords = self.containerMO.partiallyViableEscrowRecords as? Set { + partiallyViableRecords = partiallyViableEscrowRecords.compactMap { $0.escrowMetadata?.bottleID } + } + return TPCachedViableBottles(viableBottles: viableRecords, partialBottles: partiallyViableRecords) + } + + func onqueueCachedEscrowRecords() -> ([OTEscrowRecord]) { + var escrowRecords: [OTEscrowRecord] = [] + + if let fullyViableEscrowRecords = self.containerMO.fullyViableEscrowRecords as? Set { + for record in fullyViableEscrowRecords { + let convertedRecord = escrowRecordMOToEscrowRecords(record: record, viability: .full) + if let r = convertedRecord { + escrowRecords.append(r) + } + } + } + if let partiallyViableEscrowRecords = self.containerMO.partiallyViableEscrowRecords as? Set { + for record in partiallyViableEscrowRecords { + let convertedRecord = escrowRecordMOToEscrowRecords(record: record, viability: .partial) + if let r = convertedRecord { + escrowRecords.append(r) + } + } + } + if let legacyEscrowRecords = self.containerMO.legacyEscrowRecords as? Set { + for record in legacyEscrowRecords { + let convertedRecord = escrowRecordMOToEscrowRecords(record: record, viability: .none) + if let r = convertedRecord { + escrowRecords.append(r) + } + } + } + return escrowRecords + } + + func fetchEscrowRecords(forceFetch: Bool, reply: @escaping ([Data]?, Error?) -> Void) { + self.semaphore.wait() + let reply: ([Data]?, Error?) -> Void = { + os_log("fetchEscrowRecords complete: %@", log: tplogTrace, type: .info, traceError($1)) + self.semaphore.signal() + reply($0, $1) + } + + self.fetchEscrowRecordsWithSemaphore(forceFetch: forceFetch, reply: reply) + } +} diff --git a/keychain/TrustedPeersHelper/Container_MachineIDs.swift b/keychain/TrustedPeersHelper/Container_MachineIDs.swift index 19e76cbb..b684c77e 100644 --- a/keychain/TrustedPeersHelper/Container_MachineIDs.swift +++ b/keychain/TrustedPeersHelper/Container_MachineIDs.swift @@ -57,7 +57,7 @@ extension Container { // Once we run this upgrade, we will set the allowed bool to false, since it's unused. // Therefore, if we have a single record with "allowed" set, we haven't run the upgrade. - let runUpgrade = !knownMachineMOs.filter { $0.allowed }.isEmpty + let runUpgrade = knownMachineMOs.contains { $0.allowed } if runUpgrade { knownMachineMOs.forEach { mo in if mo.allowed { @@ -132,7 +132,6 @@ extension Container { machine.modified = Date() os_log("Newly distrusted machine ID: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) differences = true - } else { if machine.modifiedInPast(hours: cutoffHours) { os_log("Allowed-but-unseen machine ID isn't on full list, last modified %{public}@, ignoring: %{public}@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID)) @@ -143,7 +142,6 @@ extension Container { differences = true } } - } else if machine.status == TPMachineIDStatus.unknown.rawValue { if machine.modifiedInPast(hours: cutoffHours) { os_log("Unknown machine ID last modified %{public}@; leaving unknown: %{public}@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID)) @@ -235,7 +233,6 @@ extension Container { os_log("Continue to trust machine ID: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) } } - } else { let machine = MachineMO(context: self.moc) machine.machineID = machineID @@ -285,7 +282,6 @@ extension Container { os_log("Now suspicious of machine ID: %{public}@", log: tplogDebug, type: .default, String(describing: machine.machineID)) } } - } else { let machine = MachineMO(context: self.moc) machine.machineID = machineID diff --git a/keychain/TrustedPeersHelper/Container_Peers.swift b/keychain/TrustedPeersHelper/Container_Peers.swift new file mode 100644 index 00000000..4c9903ed --- /dev/null +++ b/keychain/TrustedPeersHelper/Container_Peers.swift @@ -0,0 +1,42 @@ +import CloudKitCode +import CloudKitCodeProtobuf +import CoreData +import Foundation +import os +import Security +import SecurityFoundation + +extension Container { + internal static func removingDuplicates(vouchers: Set) -> Set { + var unique: Set = Set() + + for voucher in vouchers { + if !unique.contains(voucher) { + unique.insert(voucher) + } + } + return unique + } + + internal static func onqueueRemoveDuplicateVouchersPerPeer(container: ContainerMO, moc: NSManagedObjectContext) { + var peersWithUniqueSetOfVouchers: Set = Set() + let peers = container.peers as? Set ?? Set() + for peer in peers { + let vouchers = peer.vouchers as? Set ?? Set() + let uniqueSet = Container.removingDuplicates(vouchers: vouchers) + for voucher in vouchers { + peer.removeFromVouchers(voucher) + } + for voucher in uniqueSet { + peer.addToVouchers(voucher) + } + peersWithUniqueSetOfVouchers.insert(peer) + } + for peer in peers { + container.removeFromPeers(peer) + } + for peer in peersWithUniqueSetOfVouchers { + container.addToPeers(peer) + } + } +} diff --git a/keychain/TrustedPeersHelper/Container_RecoveryKey.swift b/keychain/TrustedPeersHelper/Container_RecoveryKey.swift index 165764a9..0d7fe828 100644 --- a/keychain/TrustedPeersHelper/Container_RecoveryKey.swift +++ b/keychain/TrustedPeersHelper/Container_RecoveryKey.swift @@ -4,19 +4,19 @@ import Foundation extension Container { func preflightVouchWithRecoveryKey(recoveryKey: String, salt: String, - reply: @escaping (String?, Set?, TPPolicy?, Error?) -> Void) { + reply: @escaping (String?, TPSyncingPolicy?, Error?) -> Void) { self.semaphore.wait() - let reply: (String?, Set?, TPPolicy?, Error?) -> Void = { + let reply: (String?, TPSyncingPolicy?, Error?) -> Void = { os_log("preflightRecoveryKey complete: %{public}@", - log: tplogTrace, type: .info, traceError($3)) + log: tplogTrace, type: .info, traceError($2)) self.semaphore.signal() - reply($0, $1, $2, $3) + reply($0, $1, $2) } self.fetchAndPersistChangesIfNeeded { fetchError in guard fetchError == nil else { os_log("preflightRecoveryKey unable to fetch current peers: %{public}@", log: tplogDebug, type: .default, (fetchError as CVarArg?) ?? "") - reply(nil, nil, nil, fetchError) + reply(nil, nil, fetchError) return } @@ -24,7 +24,7 @@ extension Container { self.fetchPolicyDocumentsWithSemaphore(versions: self.model.allPolicyVersions()) { _, fetchPolicyDocumentsError in guard fetchPolicyDocumentsError == nil else { os_log("preflightRecoveryKey unable to fetch policy documents: %{public}@", log: tplogDebug, type: .default, (fetchPolicyDocumentsError as CVarArg?) ?? "no error") - reply(nil, nil, nil, fetchPolicyDocumentsError) + reply(nil, nil, fetchPolicyDocumentsError) return } @@ -32,14 +32,14 @@ extension Container { guard let egoPeerID = self.containerMO.egoPeerID, let egoPermData = self.containerMO.egoPeerPermanentInfo, let egoPermSig = self.containerMO.egoPeerPermanentInfoSig else { - os_log("preflightRecoveryKey: no ego peer ID", log: tplogDebug, type: .default) - reply(nil, nil, nil, ContainerError.noPreparedIdentity) - return + os_log("preflightRecoveryKey: no ego peer ID", log: tplogDebug, type: .default) + reply(nil, nil, ContainerError.noPreparedIdentity) + return } let keyFactory = TPECPublicKeyFactory() guard let selfPermanentInfo = TPPeerPermanentInfo(peerID: egoPeerID, data: egoPermData, sig: egoPermSig, keyFactory: keyFactory) else { - reply(nil, nil, nil, ContainerError.invalidPermanentInfoOrSig) + reply(nil, nil, ContainerError.invalidPermanentInfoOrSig) return } @@ -48,27 +48,27 @@ extension Container { recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) } catch { os_log("preflightRecoveryKey: failed to create recovery keys: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, nil, ContainerError.failedToCreateRecoveryKey) + reply(nil, nil, ContainerError.failedToCreateRecoveryKey) return } // Dear model: if i were to use this recovery key, what peers would I end up using? guard self.model.isRecoveryKeyEnrolled() else { os_log("preflightRecoveryKey: recovery Key is not enrolled", log: tplogDebug, type: .default) - reply(nil, nil, nil, ContainerError.recoveryKeysNotEnrolled) + reply(nil, nil, ContainerError.recoveryKeysNotEnrolled) return } - guard let sponsorPeerID = self.model.peerIDThatTrustsRecoveryKeys(TPRecoveryKeyPair(signingSPKI: recoveryKeys.peerKeys.signingKey.publicKey.keyData, - encryptionSPKI: recoveryKeys.peerKeys.encryptionKey.publicKey.keyData)) else { + guard let sponsorPeerID = self.model.peerIDThatTrustsRecoveryKeys(TPRecoveryKeyPair(signingKeyData: recoveryKeys.peerKeys.signingKey.publicKey.keyData, + encryptionKeyData: recoveryKeys.peerKeys.encryptionKey.publicKey.keyData)) else { os_log("preflightRecoveryKey Untrusted recovery key set", log: tplogDebug, type: .default) - reply(nil, nil, nil, ContainerError.untrustedRecoveryKeys) + reply(nil, nil, ContainerError.untrustedRecoveryKeys) return } guard let sponsor = self.model.peer(withID: sponsorPeerID) else { os_log("preflightRecoveryKey Failed to find peer with ID", log: tplogDebug, type: .default) - reply(nil, nil, nil, ContainerError.sponsorNotRegistered(sponsorPeerID)) + reply(nil, nil, ContainerError.sponsorNotRegistered(sponsorPeerID)) return } @@ -76,12 +76,13 @@ extension Container { let bestPolicy = try self.model.policy(forPeerIDs: sponsor.dynamicInfo?.includedPeerIDs ?? [sponsor.peerID], candidatePeerID: egoPeerID, candidateStableInfo: sponsor.stableInfo) + let syncingPolicy = try bestPolicy.syncingPolicy(forModel: selfPermanentInfo.modelID, + syncUserControllableViews: sponsor.stableInfo?.syncUserControllableViews ?? .UNKNOWN) - let views = try bestPolicy.views(forModel: selfPermanentInfo.modelID) - reply(recoveryKeys.peerKeys.peerID, views, bestPolicy, nil) + reply(recoveryKeys.peerKeys.peerID, syncingPolicy, nil) } catch { os_log("preflightRecoveryKey: error fetching policy: %{public}@", log: tplogDebug, type: .default, error as CVarArg) - reply(nil, nil, nil, error) + reply(nil, nil, error) return } } diff --git a/keychain/TrustedPeersHelper/Container_UserSync.swift b/keychain/TrustedPeersHelper/Container_UserSync.swift new file mode 100644 index 00000000..498f4a7d --- /dev/null +++ b/keychain/TrustedPeersHelper/Container_UserSync.swift @@ -0,0 +1,41 @@ +import Foundation + +// Apple TVs and watches have no UI to enable or disable this status. +// So, help them out by ignoring all efforts. +extension TPPBPeerStableInfo_UserControllableViewStatus { + func sanitizeForPlatform(permanentInfo: TPPeerPermanentInfo) -> TPPBPeerStableInfo_UserControllableViewStatus { + // Unknown is the unknown for any platform + if self == .UNKNOWN { + return .UNKNOWN + } + + if permanentInfo.modelID.hasPrefix("AppleTV") || + permanentInfo.modelID.hasPrefix("AudioAccessory") { + // Apple TVs, and HomePods don't have UI to set this bit. So, they should always sync the + // user-controlled views to which they have access. + // + // Some watches don't have UI to set the bit, but some do. + // + // Note that we want this sanitization behavior to be baked into the local OS, which is what owns + // the UI software, and not in the Policy, which can change. + return .FOLLOWING + } else { + // All other platforms can choose their own fate + return self + } + } +} + +extension StableChanges { + static func change(viewStatus: TPPBPeerStableInfo_UserControllableViewStatus?) -> StableChanges? { + if viewStatus == nil { + return nil + } + return StableChanges(deviceName: nil, + serialNumber: nil, + osVersion: nil, + policyVersion: nil, + policySecrets: nil, + setSyncUserControllableViews: viewStatus) + } +} diff --git a/keychain/TrustedPeersHelper/OctagonPeerKeys.swift b/keychain/TrustedPeersHelper/OctagonPeerKeys.swift index 535ef221..8014ccbb 100644 --- a/keychain/TrustedPeersHelper/OctagonPeerKeys.swift +++ b/keychain/TrustedPeersHelper/OctagonPeerKeys.swift @@ -29,7 +29,7 @@ class OctagonSelfPeerKeys: NSObject, CKKSSelfPeer { self.publicSigningKey = signingKey.publicKey as? _SFECPublicKey guard let encryptionVerificationKey = self.publicEncryptionKey, - let signingVerificationKey = self.publicSigningKey else { + let signingVerificationKey = self.publicSigningKey else { throw OctagonSelfPeerKeysError.noPublicKeys } diff --git a/keychain/TrustedPeersHelper/Policy.swift b/keychain/TrustedPeersHelper/Policy.swift index ce1c3eef..df6e00a9 100644 --- a/keychain/TrustedPeersHelper/Policy.swift +++ b/keychain/TrustedPeersHelper/Policy.swift @@ -29,14 +29,13 @@ struct RawPolicy { let plaintextPolicy: TPPolicyDocument } -let prevailingPolicyVersion = TPPolicyVersion(version: 6, hash: "SHA256:L2Px1aYyR1tgChe8dIyTBSmCHCWEFJirZ3ELMFXz2PY=") +let prevailingPolicyVersion = TPPolicyVersion(version: 7, hash: "SHA256:dL8Qujqzprhp6FdH5GzNMtPlnZtLWMwfiiF7aykr8WU=") // Some peers don't know how to handle new policies when pairing. If we're pairing with one of those, // we must prepare our identity using this policy. let frozenPolicyVersion = TPPolicyVersion(version: 5, hash: "SHA256:O/ECQlWhvNlLmlDNh2+nal/yekUC87bXpV3k+6kznSo=") func builtInPolicyDocuments() -> [TPPolicyDocument] { - // swiftlint:disable force_try // These bytes are generated by tppolicy let rawPolicies = [ @@ -64,6 +63,8 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { ], redactions: [:], keyViewMapping: [], + userControllableViewList: [], + piggybackViews: [], hashAlgo: .SHA256) ), @@ -92,6 +93,8 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { ], redactions: [:], keyViewMapping: [], + userControllableViewList: [], + piggybackViews: [], hashAlgo: .SHA256) ), @@ -208,6 +211,8 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule: TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com.apple.cfnetwork$")), ], + userControllableViewList: [], + piggybackViews: [], hashAlgo: .SHA256) ), RawPolicy(version: TPPolicyVersion(version: 4, hash: "SHA256:Tjdu5QrWGvKWMx7k3VWFrEWSsBDPZAwCql9ybDkvFs8="), @@ -318,6 +323,8 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WatchMigration$"), ])), ], + userControllableViewList: [], + piggybackViews: [], hashAlgo: .SHA256) ), @@ -435,6 +442,8 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule: TPDictionaryMatchingRule.trueMatch()), ], + userControllableViewList: [], + piggybackViews: [], hashAlgo: .SHA256) ), @@ -552,8 +561,135 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule: TPDictionaryMatchingRule.trueMatch()), ], + userControllableViewList: [], + piggybackViews: [], + hashAlgo: .SHA256) + ), + RawPolicy(version: TPPolicyVersion(version: 7, hash: "SHA256:dL8Qujqzprhp6FdH5GzNMtPlnZtLWMwfiiF7aykr8WU="), + policyData: "CAcSDgoGaVBob25lEgRmdWxsEgwKBGlQYWQSBGZ1bGwSDAoEaVBvZBIEZnVsbBILCgNNYWMSBGZ1bGwSDAoEaU1hYxIEZnVsbBINCgdBcHBsZVRWEgJ0dhIOCgVXYXRjaBIFd2F0Y2gSFwoOQXVkaW9BY2Nlc3NvcnkSBWF1ZGlvGh4KBEhvbWUSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aJAoVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlEgRmdWxsEgV3YXRjaBoYCglQYXNzd29yZHMSBGZ1bGwSBXdhdGNoGh8KEFNlY3VyZU9iamVjdFN5bmMSBGZ1bGwSBXdhdGNoGh4KBFdpRmkSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aGgoLQ3JlZGl0Q2FyZHMSBGZ1bGwSBXdhdGNoGhcKCEFwcGxlUGF5EgRmdWxsEgV3YXRjaBoVCgZIZWFsdGgSBGZ1bGwSBXdhdGNoGhkKCkF1dG9VbmxvY2sSBGZ1bGwSBXdhdGNoGi0KE0xpbWl0ZWRQZWVyc0FsbG93ZWQSBGZ1bGwSBXdhdGNoEgJ0dhIFYXVkaW8aHAoNRGV2aWNlUGFpcmluZxIEZnVsbBIFd2F0Y2gaFgoHTWFuYXRlZRIEZnVsbBIFd2F0Y2gaFQoGRW5ncmFtEgRmdWxsEgV3YXRjaBoXCghCYWNrc3RvcBIEZnVsbBIFd2F0Y2gaGwoMQXBwbGljYXRpb25zEgRmdWxsEgV3YXRjaCITCgRmdWxsEgRmdWxsEgV3YXRjaCIVCgJ0dhIEZnVsbBIFd2F0Y2gSAnR2IhQKBXdhdGNoEgRmdWxsEgV3YXRjaCIbCgVhdWRpbxIEZnVsbBIFd2F0Y2gSBWF1ZGlvMiIKFgAEIhICBHZ3aHQKCl5BcHBsZVBheSQSCEFwcGxlUGF5MiYKGAAEIhQCBHZ3aHQKDF5BdXRvVW5sb2NrJBIKQXV0b1VubG9jazIeChQABCIQAgR2d2h0CgheRW5ncmFtJBIGRW5ncmFtMh4KFAAEIhACBHZ3aHQKCF5IZWFsdGgkEgZIZWFsdGgyGgoSAAQiDgIEdndodAoGXkhvbWUkEgRIb21lMiAKFQAEIhECBHZ3aHQKCV5NYW5hdGVlJBIHTWFuYXRlZTI4CiEABCIdAgR2d2h0ChVeTGltaXRlZFBlZXJzQWxsb3dlZCQSE0xpbWl0ZWRQZWVyc0FsbG93ZWQyXQpQAAISHgAEIhoCBHZ3aHQKEl5Db250aW51aXR5VW5sb2NrJBIVAAQiEQIEdndodAoJXkhvbWVLaXQkEhUABCIRAgR2d2h0CgleQXBwbGVUViQSCU5vdFN5bmNlZDIrChsABCIXAgRhZ3JwCg9eWzAtOUEtWl17MTB9XC4SDEFwcGxpY2F0aW9uczLKAQq1AQACEjYAAQoTAAQiDwIFY2xhc3MKBl5nZW5wJAodAAQiGQIEYWdycAoRXmNvbVwuYXBwbGVcLnNiZCQSQAABChMABCIPAgVjbGFzcwoGXmtleXMkCicABCIjAgRhZ3JwChteY29tXC5hcHBsZVwuc2VjdXJpdHlcLnNvcyQSGQAEIhUCBHZ3aHQKDV5CYWNrdXBCYWdWMCQSHAAEIhgCBHZ3aHQKEF5pQ2xvdWRJZGVudGl0eSQSEFNlY3VyZU9iamVjdFN5bmMyYwpbAAISEgAEIg4CBHZ3aHQKBl5XaUZpJBJDAAEKEwAEIg8CBWNsYXNzCgZeZ2VucCQKEwAEIg8CBGFncnAKB15hcHBsZSQKFQAEIhECBHN2Y2UKCV5BaXJQb3J0JBIEV2lGaTKdAwqDAwACEhgABCIUAgR2d2h0CgxeUENTLUJhY2t1cCQSGgAEIhYCBHZ3aHQKDl5QQ1MtQ2xvdWRLaXQkEhgABCIUAgR2d2h0CgxeUENTLUVzY3JvdyQSFQAEIhECBHZ3aHQKCV5QQ1MtRkRFJBIaAAQiFgIEdndodAoOXlBDUy1GZWxkc3BhciQSGgAEIhYCBHZ3aHQKDl5QQ1MtTWFpbERyb3AkEhoABCIWAgR2d2h0Cg5eUENTLU1haWxkcm9wJBIbAAQiFwIEdndodAoPXlBDUy1NYXN0ZXJLZXkkEhcABCITAgR2d2h0CgteUENTLU5vdGVzJBIYAAQiFAIEdndodAoMXlBDUy1QaG90b3MkEhkABCIVAgR2d2h0Cg1eUENTLVNoYXJpbmckEh4ABCIaAgR2d2h0ChJeUENTLWlDbG91ZEJhY2t1cCQSHQAEIhkCBHZ3aHQKEV5QQ1MtaUNsb3VkRHJpdmUkEhoABCIWAgR2d2h0Cg5eUENTLWlNZXNzYWdlJBIVUHJvdGVjdGVkQ2xvdWRTdG9yYWdlMj0KLgAEIioCBGFncnAKIl5jb21cLmFwcGxlXC5zYWZhcmlcLmNyZWRpdC1jYXJkcyQSC0NyZWRpdENhcmRzMjAKIwAEIh8CBGFncnAKF15jb21cLmFwcGxlXC5jZm5ldHdvcmskEglQYXNzd29yZHMybQpcAAISHgAEIhoCBHZ3aHQKEl5BY2Nlc3NvcnlQYWlyaW5nJBIaAAQiFgIEdndodAoOXk5hbm9SZWdpc3RyeSQSHAAEIhgCBHZ3aHQKEF5XYXRjaE1pZ3JhdGlvbiQSDURldmljZVBhaXJpbmcyDgoCAAYSCEJhY2tzdG9w", + plaintextPolicy: try! TPPolicyDocument(version: 7, + modelToCategory: [ + ["prefix": "iPhone", "category": "full"], + ["prefix": "iPad", "category": "full"], + ["prefix": "iPod", "category": "full"], + ["prefix": "Mac", "category": "full"], + ["prefix": "iMac", "category": "full"], + ["prefix": "AppleTV", "category": "tv"], + ["prefix": "Watch", "category": "watch"], + ["prefix": "AudioAccessory", "category": "audio"], + ], + categoriesByView: [ + "AutoUnlock": ["full", "watch"], + "ApplePay": ["full", "watch"], + "Backstop": ["full", "watch"], + "Engram": ["full", "watch"], + "Health": ["full", "watch"], + "Home": ["full", "watch", "tv", "audio"], + "LimitedPeersAllowed": ["full", "watch", "tv", "audio"], + "Manatee": ["full", "watch"], + "Applications": ["full", "watch"], + "SecureObjectSync": ["full", "watch"], + "WiFi": ["full", "watch", "tv", "audio"], + "ProtectedCloudStorage": ["full", "watch"], + "CreditCards": ["full", "watch"], + "Passwords": ["full", "watch"], + "DevicePairing": ["full", "watch"], + ], + introducersByCategory: [ + "full": ["full", "watch"], + "watch": ["full", "watch"], + "tv": ["full", "watch", "tv"], + "audio": ["full", "watch", "audio"], + ], + redactions: [:], + keyViewMapping: [ + TPPBPolicyKeyViewMapping(view: "ApplePay", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^ApplePay$")), + TPPBPolicyKeyViewMapping(view: "AutoUnlock", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AutoUnlock$")), + TPPBPolicyKeyViewMapping(view: "Engram", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Engram$")), + TPPBPolicyKeyViewMapping(view: "Health", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Health$")), + TPPBPolicyKeyViewMapping(view: "Home", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Home$")), + TPPBPolicyKeyViewMapping(view: "Manatee", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^Manatee$")), + TPPBPolicyKeyViewMapping(view: "LimitedPeersAllowed", matchingRule: TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^LimitedPeersAllowed$")), + + // These items will not be synced by Octagon + TPPBPolicyKeyViewMapping(view: "NotSynced", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^ContinuityUnlock$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^HomeKit$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AppleTV$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Applications", matchingRule: + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^[0-9A-Z]{10}\\.")), + + TPPBPolicyKeyViewMapping(view: "SecureObjectSync", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^genp$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.sbd$"), + ]), + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^keys$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.security\\.sos$"), + ]), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^BackupBagV0$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^iCloudIdentity$"), + ])), + + TPPBPolicyKeyViewMapping(view: "WiFi", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WiFi$"), + TPDictionaryMatchingRule.andMatch([ + TPDictionaryMatchingRule.fieldMatch("class", fieldRegex: "^genp$"), + TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^apple$"), + TPDictionaryMatchingRule.fieldMatch("svce", fieldRegex: "^AirPort$"), + ]), + ])), + + TPPBPolicyKeyViewMapping(view: "ProtectedCloudStorage", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Backup$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-CloudKit$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Escrow$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-FDE$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Feldspar$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-MailDrop$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Maildrop$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-MasterKey$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Notes$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Photos$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-Sharing$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iCloudBackup$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iCloudDrive$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^PCS-iMessage$"), + ])), + + TPPBPolicyKeyViewMapping(view: "CreditCards", + matchingRule: TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.safari\\.credit-cards$")), + + TPPBPolicyKeyViewMapping(view: "Passwords", + matchingRule: TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com\\.apple\\.cfnetwork$")), + + TPPBPolicyKeyViewMapping(view: "DevicePairing", matchingRule: + TPDictionaryMatchingRule.orMatch([ + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^AccessoryPairing$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^NanoRegistry$"), + TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WatchMigration$"), + ])), + + TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule: + TPDictionaryMatchingRule.trueMatch()), + ], + userControllableViewList: [], + piggybackViews: [], hashAlgo: .SHA256) ), + + // Note to you, the next person to add a policy: + // We added user_controllable_views to the policy proto after creating v7. Pushing a new policy just to fill + // in that section seemed unnecessary. When you create v8, please fill it in. See the hacky v7 patch in TPPolicy.m. + // We added views_to_piggyback to the policy proto after creating v7 as well. + ] // swiftlint:enable force_try @@ -563,7 +699,7 @@ func builtInPolicyDocuments() -> [TPPolicyDocument] { let data = Data(base64Encoded: raw.policyData)! let doc = TPPolicyDocument.policyDoc(withHash: raw.version.policyHash, data: data)! - if(!doc.isEqual(to: raw.plaintextPolicy)) { + if !doc.isEqual(to: raw.plaintextPolicy) { let bodyData = raw.plaintextPolicy.protobuf let bodyBase64 = bodyData.base64EncodedString() let hash = TPHashBuilder.hash(with: .SHA256, of: bodyData) diff --git a/keychain/TrustedPeersHelper/RecoveryKey/RecoverKeySet.swift b/keychain/TrustedPeersHelper/RecoveryKey/RecoverKeySet.swift index 5499b200..f300de19 100644 --- a/keychain/TrustedPeersHelper/RecoveryKey/RecoverKeySet.swift +++ b/keychain/TrustedPeersHelper/RecoveryKey/RecoverKeySet.swift @@ -33,13 +33,13 @@ enum RecoveryKeyType: Int { } class RecoveryKeySet: NSObject { - public var encryptionKey: _SFECKeyPair - public var signingKey: _SFECKeyPair + var encryptionKey: _SFECKeyPair + var signingKey: _SFECKeyPair - public var secret: Data - public var recoverySalt: String + var secret: Data + var recoverySalt: String - public init (secret: Data, recoverySalt: String) throws { + init (secret: Data, recoverySalt: String) throws { self.secret = secret self.recoverySalt = recoverySalt @@ -49,7 +49,9 @@ class RecoveryKeySet: NSObject { let signingKeyData = try RecoveryKeySet.generateRecoveryKey(keyType: RecoveryKeyType.kOTRecoveryKeySigning, masterSecret: secret, recoverySalt: recoverySalt) self.signingKey = _SFECKeyPair.init(secKey: try RecoveryKeySet.createSecKey(keyData: signingKeyData)) - let RecoverySigningPubKeyHash = try RecoveryKeySet.hashRecoveryedSigningPublicKey(keyData: self.signingKey.publicKey().spki()) + // Note: this uses the SPKI hash, and not the key data hash + // So, this will not match the RK's peer ID + let RecoverySigningPubKeyHash = RecoveryKeySet.hashRecoveryedSigningPublicKey(keyData: self.signingKey.publicKey().spki()) _ = try RecoveryKeySet.storeRecoveryedSigningKeyPair(keyData: self.signingKey.keyData, label: RecoverySigningPubKeyHash) _ = try RecoveryKeySet.storeRecoveryedEncryptionKeyPair(keyData: self.encryptionKey.keyData, label: RecoverySigningPubKeyHash) } @@ -76,7 +78,6 @@ class RecoveryKeySet: NSObject { let infoString = Array("Recovery Signing Private Key".utf8) info = Data(bytes: infoString, count: infoString.count) - } guard let cp = ccec_cp_384() else { @@ -109,7 +110,7 @@ class RecoveryKeySet: NSObject { if keyType == RecoveryKeyType.kOTRecoveryKeyEncryption || keyType == RecoveryKeyType.kOTRecoveryKeySigning { status = ccec_generate_key_deterministic(cp, derivedKeyBytes.count, derivedKeyBytes.bindMemory(to: UInt8.self).baseAddress!, - ccDRBGGetRngState(), + ccrng(nil), UInt32(CCEC_GENKEY_DETERMINISTIC_FIPS), fullKey) @@ -167,7 +168,7 @@ class RecoveryKeySet: NSObject { return result } - class func hashRecoveryedSigningPublicKey(keyData: Data) throws -> (String) { + class func hashRecoveryedSigningPublicKey(keyData: Data) -> (String) { let di = ccsha384_di() var result = Data(count: TPHObjectiveC.ccsha384_diSize()) @@ -183,7 +184,6 @@ class RecoveryKeySet: NSObject { } class func storeRecoveryedEncryptionKeyPair(keyData: Data, label: String) throws -> (Bool) { - let query: [CFString: Any] = [ kSecClass: kSecClassKey, kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, @@ -257,11 +257,11 @@ class RecoveryKeySet: NSObject { let keyTypeData = item[kSecAttrApplicationLabel as CFString] as! Data let keyType = String(data: keyTypeData, encoding: .utf8)! - if keyType.range(of: "Encryption") != nil { + if keyType.contains("Encryption") { let keyData = item[kSecValueData as CFString] as! Data let encryptionSecKey = try RecoveryKeySet.createSecKey(keyData: keyData) encryptionKey = _SFECKeyPair.init(secKey: encryptionSecKey) - } else if keyType.range(of: "Signing") != nil { + } else if keyType.contains("Signing") { let keyData = item[kSecValueData as CFString] as! Data let signingSecKey = try RecoveryKeySet.createSecKey(keyData: keyData) signingKey = _SFECKeyPair.init(secKey: signingSecKey) @@ -300,7 +300,6 @@ extension RecoveryKeySetError: LocalizedError { } extension RecoveryKeySetError: CustomNSError { - public static var errorDomain: String { return "com.apple.security.trustedpeers.RecoveryKeySetError" } diff --git a/keychain/TrustedPeersHelper/RecoveryKey/RecoveryKey.swift b/keychain/TrustedPeersHelper/RecoveryKey/RecoveryKey.swift index 35cd9b3f..373a256d 100644 --- a/keychain/TrustedPeersHelper/RecoveryKey/RecoveryKey.swift +++ b/keychain/TrustedPeersHelper/RecoveryKey/RecoveryKey.swift @@ -25,20 +25,38 @@ import Foundation import SecurityFoundation class RecoveryKey: NSObject { - public var recoveryKeys: RecoveryKeySet - public var secret: Data + internal var recoveryKeys: RecoveryKeySet + internal var secret: Data - public var peerKeys: OctagonSelfPeerKeys + internal var peerKeys: OctagonSelfPeerKeys - public init(recoveryKeyString: String, recoverySalt: String) throws { + internal init(recoveryKeyString: String, recoverySalt: String) throws { self.secret = Data(bytes: Array(recoveryKeyString.utf8), count: recoveryKeyString.utf8.count) self.recoveryKeys = try RecoveryKeySet(secret: self.secret, recoverySalt: recoverySalt) - let hash = try RecoveryKeySet.hashRecoveryedSigningPublicKey(keyData: self.recoveryKeys.signingKey.publicKey.keyData) - let peerID = "RK-" + hash + let peerID = RecoveryKey.PeerID(signingPublicKeyData: self.recoveryKeys.signingKey.publicKey.keyData) try self.peerKeys = OctagonSelfPeerKeys(peerID: peerID, signingKey: self.recoveryKeys.signingKey, encryptionKey: self.recoveryKeys.encryptionKey) } + + static func PeerID(signingPublicKeyData: Data) -> String { + let hash = RecoveryKeySet.hashRecoveryedSigningPublicKey(keyData: signingPublicKeyData) + let peerID = "RK-" + hash + + return peerID + } + + static func spki(publicKeyData: Data) throws -> Data { + let key = try _SFECPublicKey(data: publicKeyData, specifier: _SFECKeySpecifier(curve: SFEllipticCurve.nistp384)) + return key.encodeSubjectPublicKeyInfo() + } + + public static func asPeer(recoveryKeys: TPRecoveryKeyPair, viewList: Set) throws -> TrustedPeersHelperPeer { + return TrustedPeersHelperPeer(peerID: self.PeerID(signingPublicKeyData: recoveryKeys.signingKeyData), + signingSPKI: try self.spki(publicKeyData: recoveryKeys.signingKeyData), + encryptionSPKI: try self.spki(publicKeyData: recoveryKeys.encryptionKeyData), + viewList: viewList) + } } extension RecoveryKey { diff --git a/keychain/TrustedPeersHelper/TPHObjcTranslation.m b/keychain/TrustedPeersHelper/TPHObjcTranslation.m index 5254fe76..51128fa0 100644 --- a/keychain/TrustedPeersHelper/TPHObjcTranslation.m +++ b/keychain/TrustedPeersHelper/TPHObjcTranslation.m @@ -6,7 +6,7 @@ #import #import #import -#import +#import @implementation TPHObjectiveC : NSObject diff --git a/keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h b/keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h index a633cef5..38ec749f 100644 --- a/keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h +++ b/keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h @@ -29,6 +29,10 @@ #import "keychain/ot/OTConstants.h" #import "keychain/ot/OTDefines.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecord.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h" + #import "keychain/TrustedPeersHelper/TPHObjcTranslation.h" #import "keychain/TrustedPeersHelper/proto/generated_source/OTBottleContents.h" #import "keychain/TrustedPeersHelper/proto/generated_source/OTBottle.h" @@ -52,7 +56,11 @@ #import #import #import +#import -#import #import #include + +#if TARGET_OS_OSX +#include +#endif diff --git a/keychain/TrustedPeersHelper/TrustedPeersHelper-entitlements.plist b/keychain/TrustedPeersHelper/TrustedPeersHelper-entitlements.plist index 6947f3d5..539efa03 100644 --- a/keychain/TrustedPeersHelper/TrustedPeersHelper-entitlements.plist +++ b/keychain/TrustedPeersHelper/TrustedPeersHelper-entitlements.plist @@ -24,6 +24,8 @@ com.apple.private.cloudkit.systemService + com.apple.private.cloudkit.spi + com.apple.private.cloudkit.supportservice com.apple.private.cloudkit.prefix @@ -37,5 +39,24 @@ com.apple.symptom_diagnostics.report + seatbelt-profiles + + temporary-sandbox + + com.apple.security.ts.cloudkit-client + + com.apple.security.exception.files.absolute-path.read-write + + /private/var/Keychains/ + + com.apple.security.exception.mach-lookup.global-name + + com.apple.securityd + com.apple.security.sfkeychainserver + + com.apple.security.exception.shared-preference.read-write + + com.apple.TrustedPeersHelper + diff --git a/keychain/TrustedPeersHelper/TrustedPeersHelper.xcdatamodeld/TrustedPeersHelper_2.xcdatamodel/contents b/keychain/TrustedPeersHelper/TrustedPeersHelper.xcdatamodeld/TrustedPeersHelper_2.xcdatamodel/contents index 83d8766c..8160123b 100644 --- a/keychain/TrustedPeersHelper/TrustedPeersHelper.xcdatamodeld/TrustedPeersHelper_2.xcdatamodel/contents +++ b/keychain/TrustedPeersHelper/TrustedPeersHelper.xcdatamodeld/TrustedPeersHelper_2.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -18,16 +18,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -68,11 +110,14 @@ - + + + + - + \ No newline at end of file diff --git a/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h b/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h index 0f37bed2..145eee78 100644 --- a/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h +++ b/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h @@ -23,6 +23,7 @@ #import #import +#import #import "keychain/ckks/CKKSKeychainBackedKey.h" #import "keychain/ckks/CKKSTLKShare.h" @@ -158,11 +159,12 @@ NS_ASSUME_NONNULL_BEGIN bottleSalt:(NSString *)bottleSalt bottleID:(NSString *)bottleID modelID:(NSString *)modelID - deviceName:(nullable NSString*)deviceName - serialNumber:(NSString *)serialNumber + deviceName:(nullable NSString *)deviceName + serialNumber:(nullable NSString *)serialNumber osVersion:(NSString *)osVersion policyVersion:(nullable TPPolicyVersion *)policyVersion policySecrets:(nullable NSDictionary *)policySecrets + syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews signingPrivKeyPersistentRef:(nullable NSData *)spkPr encPrivKeyPersistentRef:(nullable NSData*)epkPr reply:(void (^)(NSString * _Nullable peerID, @@ -170,8 +172,7 @@ NS_ASSUME_NONNULL_BEGIN NSData * _Nullable permanentInfoSig, NSData * _Nullable stableInfo, NSData * _Nullable stableInfoSig, - NSSet* _Nullable syncingViewList, - TPPolicy* _Nullable syncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply; // If there already are existing CKKSViews, please pass in their key sets anyway. @@ -183,6 +184,7 @@ NS_ASSUME_NONNULL_BEGIN preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply; // Returns a voucher for the given peer ID using our own identity @@ -202,12 +204,13 @@ NS_ASSUME_NONNULL_BEGIN // Preflighting a vouch will return the peer ID associated with the bottle you will be recovering, as well as // the syncing policy used by that peer, and, // You can then use that peer ID to filter the tlkshares provided to vouchWithBottle. +// If TPH had to refetch anything from the network, it will report that fact as refetchNeeded. - (void)preflightVouchWithBottleWithContainer:(NSString *)container context:(NSString *)context bottleID:(NSString*)bottleID reply:(void (^)(NSString* _Nullable peerID, - NSSet* _Nullable peerSyncingViewList, - TPPolicy * _Nullable peerSyncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, + BOOL refetchWasNeeded, NSError * _Nullable error))reply; // Returns a voucher for our own identity, created by the identity inside this bottle @@ -230,8 +233,7 @@ NS_ASSUME_NONNULL_BEGIN recoveryKey:(NSString*)recoveryKey salt:(NSString*)salt reply:(void (^)(NSString* _Nullable recoveryKeyID, - NSSet* _Nullable peerSyncingViewList, - TPPolicy * _Nullable peerSyncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply; // Returns a voucher for our own identity, using recovery key @@ -253,20 +255,21 @@ NS_ASSUME_NONNULL_BEGIN voucherSig:(NSData *)voucherSig ckksKeys:(NSArray *)viewKeySets tlkShares:(NSArray *)tlkShares - preapprovedKeys:(NSArray *)preapprovedKeys + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, - NSSet* _Nullable syncingViewList, - TPPolicy* _Nullable syncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply; // Preflighting a preapproved join suggests whether or not you expect to succeed in an immediate preapprovedJoin() call // This only inspects the Octagon model, and ignores the trusted device list, so that you can preflight the preapprovedJoin() // before fetching that list. -// This will return YES if there are no existing peers, or if the existing peers preapprove your prepared identity. +// This will return YES if there are no existing peers, or if the existing peers preapprove your prepared identity, and +// you are intending to trust at least one preapproving peer (so that you don't stomp all over everyone else at join time). // This will return NO otherwise. - (void)preflightPreapprovedJoinWithContainer:(NSString *)container context:(NSString *)context + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(BOOL launchOkay, NSError * _Nullable error))reply; @@ -276,14 +279,14 @@ NS_ASSUME_NONNULL_BEGIN context:(NSString *)context ckksKeys:(NSArray *)ckksKeys tlkShares:(NSArray *)tlkShares - preapprovedKeys:(NSArray *)preapprovedKeys + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, - NSSet* _Nullable syncingViewList, - TPPolicy* _Nullable syncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply; // TODO: if the new policy causes someone to lose access to a view, how should this API work? +// syncUserControllableViews should contain the raw value of the TPPBPeerStableInfo_UserControllableViewStatus enum, or be nil - (void)updateWithContainer:(NSString *)container context:(NSString *)context deviceName:(nullable NSString *)deviceName @@ -291,7 +294,10 @@ NS_ASSUME_NONNULL_BEGIN osVersion:(nullable NSString *)osVersion policyVersion:(nullable NSNumber *)policyVersion policySecrets:(nullable NSDictionary *)policySecrets - reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, NSError * _Nullable error))reply; + syncUserControllableViews:(nullable NSNumber *)syncUserControllableViews + reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, + TPSyncingPolicy* _Nullable syncingPolicy, + NSError * _Nullable error))reply; - (void)setPreapprovedKeysWithContainer:(NSString *)container context:(NSString *)context @@ -309,6 +315,11 @@ NS_ASSUME_NONNULL_BEGIN context:(NSString *)context reply:(void (^)(NSArray* _Nullable sortedBottleIDs, NSArray* _Nullable sortedPartialBottleIDs, NSError* _Nullable error))reply; +- (void)fetchViableEscrowRecordsWithContainer:(NSString *)container + context:(NSString *)context + forceFetch:(BOOL)forceFetch + reply:(void (^)(NSArray* _Nullable records, NSError* _Nullable error))reply; + - (void)fetchEscrowContentsWithContainer:(NSString *)container context:(NSString *)context reply:(void (^)(NSData* _Nullable entropy, @@ -323,10 +334,14 @@ NS_ASSUME_NONNULL_BEGIN NSError * _Nullable error))reply; // Fetch the policy and view list for current peer. +// Note: userControllableViewStatusOfPeers is not our current peer's view of the world, but rather what +// our peers believe. +// If there is no prepared ego peer, the returned policy will be for a device with modelIDOverride - (void)fetchCurrentPolicyWithContainer:(NSString*)container context:(NSString*)context - reply:(void (^)(NSSet* _Nullable syncingViewList, - TPPolicy * _Nullable syncingPolicy, + modelIDOverride:(NSString* _Nullable)modelID + reply:(void (^)(TPSyncingPolicy* _Nullable syncingPolicy, + TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers, NSError * _Nullable error))reply; - (void)validatePeersWithContainer:(NSString *)container @@ -346,7 +361,8 @@ NS_ASSUME_NONNULL_BEGIN recoveryKey:(NSString *)recoveryKey salt:(NSString *)salt ckksKeys:(NSArray *)ckksKeys - reply:(void (^)(NSError* _Nullable error))reply; + reply:(void (^)(NSArray* _Nullable keyHierarchyRecords, + NSError* _Nullable error))reply; - (void)reportHealthWithContainer:(NSString *)container context:(NSString *)context @@ -367,6 +383,10 @@ NS_ASSUME_NONNULL_BEGIN context:(NSString *)context reply:(void (^)(NSData * _Nullable, NSError * _Nullable))reply; +- (void)removeEscrowCacheWithContainer:(NSString *)container + context:(NSString *)context + reply:(void (^)(NSError * _Nullable))reply; + @end /* diff --git a/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.m b/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.m index fb2f1557..fb31466c 100644 --- a/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.m +++ b/keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.m @@ -6,6 +6,7 @@ #import "utilities/debugging.h" #import #import +#import #endif NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) @@ -16,29 +17,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ errClasses = [NSMutableSet setWithSet:CKAcceptableValueClasses()]; - - char *classes[] = { - "CKPrettyError", - "CKRecordID", - "NSArray", - "NSData", - "NSDate", - "NSDictionary", - "NSError", - "NSNull", - "NSNumber", - "NSOrderedSet", - "NSSet", - "NSString", - "NSURL", - }; - - for (unsigned n = 0; n < sizeof(classes)/sizeof(classes[0]); n++) { - Class cls = objc_getClass(classes[n]); - if (cls) { - [errClasses addObject:cls]; - } - } + [errClasses unionSet:[SecXPCHelper safeErrorClasses]]; }); @try { @@ -50,6 +29,45 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) NSSet* arrayOfTrustedPeersHelperPeer = [NSSet setWithArray:@[[NSArray class], [TrustedPeersHelperPeer class]]]; + [interface setClasses:errClasses forSelector:@selector(dumpWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(departByDistrustingSelfWithContainer:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(distrustPeerIDsWithContainer:context:peerIDs:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(trustStatusWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(resetWithContainer:context:resetReason:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(localResetWithContainer:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(setAllowedMachineIDsWithContainer:context:allowedMachineIDs:honorIDMSListChanges:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(addAllowedMachineIDsWithContainer:context:machineIDs:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(removeAllowedMachineIDsWithContainer:context:machineIDs:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchAllowedMachineIDsWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchEgoEpochWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(prepareWithContainer:context:epoch:machineID:bottleSalt:bottleID:modelID:deviceName:serialNumber:osVersion:policyVersion:policySecrets:syncUserControllableViews:signingPrivKeyPersistentRef:encPrivKeyPersistentRef:reply:) argumentIndex:6 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(establishWithContainer:context:ckksKeys:tlkShares:preapprovedKeys:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(vouchWithContainer:context:peerID:permanentInfo:permanentInfoSig:stableInfo:stableInfoSig:ckksKeys:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(preflightVouchWithBottleWithContainer:context:bottleID:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(vouchWithBottleWithContainer:context:bottleID:entropy:bottleSalt:tlkShares:reply:) argumentIndex:4 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(preflightVouchWithRecoveryKeyWithContainer:context:recoveryKey:salt:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(vouchWithRecoveryKeyWithContainer:context:recoveryKey:salt:tlkShares:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(joinWithContainer:context:voucherData:voucherSig:ckksKeys:tlkShares:preapprovedKeys:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(preflightPreapprovedJoinWithContainer:context:preapprovedKeys:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(attemptPreapprovedJoinWithContainer:context:ckksKeys:tlkShares:preapprovedKeys:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(updateWithContainer:context:deviceName:serialNumber:osVersion:policyVersion:policySecrets:syncUserControllableViews:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(setPreapprovedKeysWithContainer:context:preapprovedKeys:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(updateTLKsWithContainer:context:ckksKeys:tlkShares:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchViableBottlesWithContainer:context:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchViableEscrowRecordsWithContainer:context:forceFetch:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchEscrowContentsWithContainer:context:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchPolicyDocumentsWithContainer:context:versions:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchCurrentPolicyWithContainer:context:modelIDOverride:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(validatePeersWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchTrustStateWithContainer:context:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(setRecoveryKeyWithContainer:context:recoveryKey:salt:ckksKeys:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(reportHealthWithContainer:context:stateMachineState:trustState:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(pushHealthInquiryWithContainer:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(requestHealthCheckWithContainer:context:requiresEscrowCheck:reply:) argumentIndex:4 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(getSupportAppInfoWithContainer:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(removeEscrowCacheWithContainer:context:reply:) argumentIndex:0 ofReply:YES]; + + [interface setClasses:arrayOfStrings forSelector:@selector(addAllowedMachineIDsWithContainer:context:machineIDs:reply:) argumentIndex:2 ofReply:NO]; [interface setClasses:arrayOfStrings forSelector:@selector(removeAllowedMachineIDsWithContainer:context:machineIDs:reply:) argumentIndex:2 ofReply:NO]; @@ -88,6 +106,12 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) salt: ckksKeys: reply:) argumentIndex:4 ofReply:NO]; + [interface setClasses:arrayOfCKRecords forSelector:@selector(setRecoveryKeyWithContainer: + context: + recoveryKey: + salt: + ckksKeys: + reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:arrayOfTLKShares forSelector:@selector(vouchWithRecoveryKeyWithContainer: context: recoveryKey: @@ -95,10 +119,6 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) tlkShares: reply:) argumentIndex:4 ofReply:NO]; - [interface setClasses:[NSSet setWithObject:[TPPolicy class]] forSelector:@selector(fetchCurrentPolicyWithContainer: - context: - reply:) argumentIndex:1 ofReply:YES]; - [interface setClasses:trustedPeersHelperPeerState forSelector:@selector(updateWithContainer: context: deviceName: @@ -106,6 +126,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) osVersion: policyVersion: policySecrets: + syncUserControllableViews: reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:trustedPeersHelperPeerState forSelector:@selector(fetchTrustStateWithContainer: @@ -133,9 +154,7 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) } @catch(NSException* e) { secerror("TrustedPeersHelperSetupProtocol failed, continuing, but you might crash later: %@", e); -#if DEBUG @throw e; -#endif } #endif @@ -164,10 +183,10 @@ NSXPCInterface* TrustedPeersHelperSetupProtocol(NSXPCInterface* interface) - (NSString*)description { - return [NSString stringWithFormat:@"", + return [NSString stringWithFormat:@"", self.peerID, self.identityIsPreapproved, - (int64_t)self.peerStatus, + TPPeerStatusToString(self.peerStatus), self.memberChanges ? @"YES" : @"NO", self.unknownMachineIDsPresent ? @"YES" : @"NO", self.osVersion?:@"unknown"]; diff --git a/keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb b/keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb new file mode 100644 index 00000000..a3d85d50 --- /dev/null +++ b/keychain/TrustedPeersHelper/com.apple.TrustedPeersHelper.sb @@ -0,0 +1,41 @@ +(version 1) + +(define (home-subpath home-relative-subpath) + (subpath (string-append (param "HOME") home-relative-subpath))) + +(deny default) +(deny file-map-executable iokit-get-properties process-info* nvram*) +(deny dynamic-code-generation) + +(deny mach-priv-host-port) +(import "system.sb") +(import "com.apple.corefoundation.sb") +(corefoundation) + +(allow distributed-notification-post) + +(allow process-info* (target self)) +(allow process-info-codesignature) + +(allow file-read-metadata) + +(allow file-read* file-write* + (home-subpath "/Library/Keychains/")) + +(allow mach-lookup + (global-name "com.apple.cloudd") + (global-name "com.apple.apsd") + (global-name "com.apple.securityd.xpc") + (global-name "com.apple.security.sfkeychainserver") + (global-name "com.apple.SecurityServer") + (global-name "com.apple.lsd.mapdb") +) + +(allow user-preference-read + (preference-domain "kCFPreferencesAnyApplication") +) + +(allow file-read* file-write* + (subpath "/private/var/db/mds/") + (subpath "/Library/Keychains/") +) diff --git a/keychain/TrustedPeersHelper/main.swift b/keychain/TrustedPeersHelper/main.swift index 9bfa5fb6..3f98b40d 100644 --- a/keychain/TrustedPeersHelper/main.swift +++ b/keychain/TrustedPeersHelper/main.swift @@ -59,11 +59,42 @@ class ServiceDelegate: NSObject, NSXPCListenerDelegate { } } +#if os(macOS) +public func withArrayOfCStrings( + _ args: [String], + _ body: ([UnsafePointer?]) -> R +) -> R { + var mutableCStrings = args.map { strdup($0) } + mutableCStrings.append(nil) + + let cStrings = mutableCStrings.map { UnsafePointer($0) } + + defer { + mutableCStrings.forEach { free($0) } + } + return body(cStrings) +} + +withArrayOfCStrings(["HOME", NSHomeDirectory()]) { parameters in + var sandboxErrors: UnsafeMutablePointer? + + let rc = sandbox_init_with_parameters("com.apple.TrustedPeersHelper", UInt64(SANDBOX_NAMED), parameters, &sandboxErrors) + guard rc == 0 else { + let printableMessage = sandboxErrors.map { String(cString: $0 ) } + os_log("Unable to enter sandbox. Error code:%d message: %@", log: tplogDebug, type: .default, rc, printableMessage ?? "no printable message") + sandbox_free_error(sandboxErrors) + abort() + } + os_log("Sandbox entered", log: tplogDebug, type: .default) +} +#endif + os_log("Starting up", log: tplogDebug, type: .default) ValueTransformer.setValueTransformer(SetValueTransformer(), forName: SetValueTransformer.name) let delegate = ServiceDelegate() let listener = NSXPCListener.service() + listener.delegate = delegate listener.resume() diff --git a/keychain/TrustedPeersHelper/proto/generated_source/OTBottleContents.h b/keychain/TrustedPeersHelper/proto/generated_source/OTBottleContents.h index 926ae2d0..0afee106 100644 --- a/keychain/TrustedPeersHelper/proto/generated_source/OTBottleContents.h +++ b/keychain/TrustedPeersHelper/proto/generated_source/OTBottleContents.h @@ -5,7 +5,6 @@ #import #import -@class OTPrivateKey; @class OTPrivateKey; #ifdef __cplusplus diff --git a/keychain/TrustedPeersHelperUnitTests/.swiftlint.yml b/keychain/TrustedPeersHelperUnitTests/.swiftlint.yml index 9ddd0d11..f8391d9b 100644 --- a/keychain/TrustedPeersHelperUnitTests/.swiftlint.yml +++ b/keychain/TrustedPeersHelperUnitTests/.swiftlint.yml @@ -1,3 +1,4 @@ disabled_rules: - force_cast - force_try + - implicitly_unwrapped_optional diff --git a/keychain/TrustedPeersHelperUnitTests/ContainerSync.swift b/keychain/TrustedPeersHelperUnitTests/ContainerSync.swift index 655bfdf8..1b325f35 100644 --- a/keychain/TrustedPeersHelperUnitTests/ContainerSync.swift +++ b/keychain/TrustedPeersHelperUnitTests/ContainerSync.swift @@ -8,7 +8,6 @@ import XCTest extension Container { - func dumpSync(test: XCTestCase) -> ([AnyHashable: Any]?, Error?) { let expectation = XCTestExpectation(description: "dump replied") var reta: [AnyHashable: Any]?, reterr: Error? @@ -54,13 +53,13 @@ extension Container { osVersion: String = "123", policyVersion: TPPolicyVersion? = nil, policySecrets: [String: Data]? = nil, + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus = .UNKNOWN, signingPrivateKeyPersistentRef: Data? = nil, encryptionPrivateKeyPersistentRef: Data? = nil - ) -> (String?, Data?, Data?, Data?, Data?, Set?, TPPolicy?, Error?) { + ) -> (String?, Data?, Data?, Data?, Data?, TPSyncingPolicy?, Error?) { let expectation = XCTestExpectation(description: "prepare replied") var reta: String?, retb: Data?, retc: Data?, retd: Data?, rete: Data?, reterr: Error? - var retviews: Set? - var retpolicy: TPPolicy? + var retpolicy: TPSyncingPolicy? self.prepare(epoch: epoch, machineID: machineID, bottleSalt: bottleSalt, @@ -71,39 +70,41 @@ extension Container { osVersion: osVersion, policyVersion: policyVersion, policySecrets: policySecrets, + syncUserControllableViews: syncUserControllableViews, signingPrivateKeyPersistentRef: signingPrivateKeyPersistentRef, encryptionPrivateKeyPersistentRef: encryptionPrivateKeyPersistentRef - ) { a, b, c, d, e, f, g, err in + ) { a, b, c, d, e, f, err in reta = a retb = b retc = c retd = d rete = e - retviews = f - retpolicy = g + retpolicy = f reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, retb, retc, retd, rete, retviews, retpolicy, reterr) + return (reta, retb, retc, retd, rete, retpolicy, reterr) } func establishSync(test: XCTestCase, ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data]?) -> (String?, [CKRecord], Error?) { + preapprovedKeys: [Data]?) -> (String?, [CKRecord], TPSyncingPolicy?, Error?) { let expectation = XCTestExpectation(description: "prepare replied") var reta: String?, retkhr: [CKRecord]?, reterr: Error? + var retpolicy: TPSyncingPolicy? self.establish(ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { a, khr, err in + preapprovedKeys: preapprovedKeys) { a, khr, policy, err in reta = a retkhr = khr + retpolicy = policy reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, retkhr!, reterr) + return (reta, retkhr!, retpolicy, reterr) } func vouchSync(test: XCTestCase, @@ -130,19 +131,20 @@ extension Container { return (reta, retb, reterr) } - func preflightVouchWithBottleSync(test: XCTestCase, bottleID: String) -> (String?, Set?, TPPolicy?, Error?) { + func preflightVouchWithBottleSync(test: XCTestCase, bottleID: String) -> (String?, TPSyncingPolicy?, Bool, Error?) { let expectation = XCTestExpectation(description: "preflightVouchWithBottle replied") var reta: String?, reterr: Error? - var retviews: Set?, retpolicy: TPPolicy? - self.preflightVouchWithBottle(bottleID: bottleID) { a, views, policy, err in + var retrefetched: Bool = false + var retpolicy: TPSyncingPolicy? + self.preflightVouchWithBottle(bottleID: bottleID) { a, policy, refetched, err in reta = a - retviews = views retpolicy = policy + retrefetched = refetched reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, retviews, retpolicy, reterr) + return (reta, retpolicy, retrefetched, reterr) } func vouchWithBottleSync(test: XCTestCase, b: String, entropy: Data, bottleSalt: String, tlkShares: [CKKSTLKShare]) -> (Data?, Data?, Int64, Int64, Error?) { @@ -165,70 +167,71 @@ extension Container { voucherSig: Data, ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, Set?, TPPolicy?, Error?) { + preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, TPSyncingPolicy?, Error?) { let expectation = XCTestExpectation(description: "join replied") var reta: String?, retkhr: [CKRecord]?, reterr: Error? - var retviews: Set?, retpolicy: TPPolicy? + var retpolicy: TPSyncingPolicy? self.join(voucherData: voucherData, voucherSig: voucherSig, ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { a, khr, views, policy, err in + preapprovedKeys: preapprovedKeys) { a, khr, policy, err in reta = a retkhr = khr - retviews = views retpolicy = policy reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, retkhr, retviews, retpolicy, reterr) + return (reta, retkhr, retpolicy, reterr) } func preapprovedJoinSync(test: XCTestCase, ckksKeys: [CKKSKeychainBackedKeySet], tlkShares: [CKKSTLKShare], - preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, Set?, TPPolicy?, Error?) { + preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, TPSyncingPolicy?, Error?) { let expectation = XCTestExpectation(description: "preapprovedjoin replied") var reta: String? var retkhr: [CKRecord]? - var retviews: Set? - var retpolicy: TPPolicy? + var retpolicy: TPSyncingPolicy? var reterr: Error? self.preapprovedJoin(ckksKeys: ckksKeys, tlkShares: tlkShares, - preapprovedKeys: preapprovedKeys) { a, khr, views, policy, err in + preapprovedKeys: preapprovedKeys) { a, khr, policy, err in reta = a retkhr = khr - retviews = views retpolicy = policy reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reta, retkhr, retviews, retpolicy, reterr) + return (reta, retkhr, retpolicy, reterr) } func updateSync(test: XCTestCase, deviceName: String? = nil, - serialNumner: String? = nil, + serialNumber: String? = nil, osVersion: String? = nil, policyVersion: UInt64? = nil, - policySecrets: [String: Data]? = nil) -> (TrustedPeersHelperPeerState?, Error?) { + policySecrets: [String: Data]? = nil, + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus? = nil) -> (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) { let expectation = XCTestExpectation(description: "update replied") var reterr: Error? var retstate: TrustedPeersHelperPeerState? + var retpolicy: TPSyncingPolicy? self.update(deviceName: deviceName, - serialNumber: serialNumner, + serialNumber: serialNumber, osVersion: osVersion, policyVersion: policyVersion, - policySecrets: policySecrets) { state, err in + policySecrets: policySecrets, + syncUserControllableViews: syncUserControllableViews) { state, policy, err in retstate = state + retpolicy = policy reterr = err expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (retstate, reterr) + return (retstate, retpolicy, reterr) } func setAllowedMachineIDsSync(test: XCTestCase, allowedMachineIDs: Set, accountIsDemo: Bool, listDifference: Bool = true) -> (Error?) { @@ -318,21 +321,22 @@ extension Container { do { secret = try loadSecret(label: label) } catch { - } return secret } - func setRecoveryKeySync(test: XCTestCase, recoveryKey: String, recoverySalt: String, ckksKeys: [CKKSKeychainBackedKeySet]) -> (Error?) { + func setRecoveryKeySync(test: XCTestCase, recoveryKey: String, recoverySalt: String, ckksKeys: [CKKSKeychainBackedKeySet]) -> ([CKRecord]?, Error?) { let expectation = XCTestExpectation(description: "setRecoveryKey replied") + var retrecords: [CKRecord]? var reterr: Error? - self.setRecoveryKey(recoveryKey: recoveryKey, salt: recoverySalt, ckksKeys: ckksKeys) { error in + self.setRecoveryKey(recoveryKey: recoveryKey, salt: recoverySalt, ckksKeys: ckksKeys) { records, error in + retrecords = records reterr = error expectation.fulfill() } test.wait(for: [expectation], timeout: 10.0) - return (reterr) + return (retrecords, reterr) } func fetchViableBottlesSync(test: XCTestCase) -> ([String]?, [String]?, Error?) { @@ -381,6 +385,20 @@ extension Container { return (reta, reterr) } + func fetchCurrentPolicySync(test: XCTestCase) -> (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) { + let expectation = XCTestExpectation(description: "fetchCurrentPolicy replied") + var reta: TPSyncingPolicy?, reterr: Error? + var retOp: TPPBPeerStableInfo_UserControllableViewStatus = .UNKNOWN + self.fetchCurrentPolicy(modelIDOverride: nil) { a, peerOpinion, err in + reta = a + retOp = peerOpinion + reterr = err + expectation.fulfill() + } + test.wait(for: [expectation], timeout: 10.0) + return (reta, retOp, reterr) + } + func fetchEscrowContentsSync(test: XCTestCase) -> (Data?, String?, Data?, Error?) { let expectation = XCTestExpectation(description: "fetchEscrowContents replied") var retentropy: Data? diff --git a/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift b/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift index 23267a01..4236b8c3 100644 --- a/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift +++ b/keychain/TrustedPeersHelperUnitTests/FakeCuttlefish.swift @@ -6,14 +6,9 @@ // import CloudKitCode +import CloudKitCodeProtobuf import Foundation -enum FakeCuttlefishError: Error { - case notEmpty - case unknownChangeToken - case unknownPeerID -} - enum FakeCuttlefishOpinion { case trusts case trustsByPreapproval @@ -70,6 +65,7 @@ struct FakeCuttlefishAssertion: CustomStringConvertible { class FakeCuttlefishNotify: NSObject { let pushes: (Data) -> Void let containerName: String + @objc init(_ containerName: String, pushes: @escaping (Data) -> Void) { self.containerName = containerName @@ -77,7 +73,7 @@ class FakeCuttlefishNotify: NSObject { } @objc - public func notify(_ function: String) throws { + func notify(_ function: String) throws { let notification: [String: [String: Any]] = [ "aps": ["content-available": 1], "cf": [ @@ -168,12 +164,12 @@ extension TLKShare { } class FakeCuttlefishServer: CuttlefishAPIAsync { - struct State { var peersByID: [String: Peer] = [:] var recoverySigningPubKey: Data? var recoveryEncryptionPubKey: Data? var bottles: [Bottle] = [] + var escrowRecords: [EscrowInformation] = [] var viewKeys: [CKRecordZone.ID: ViewKeys] = [:] var tlkShares: [CKRecordZone.ID: [TLKShare]] = [:] @@ -194,6 +190,9 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { // @property (nullable) NSMutableDictionary* keys; var ckksZoneKeys: NSMutableDictionary + var injectLegacyEscrowRecords: Bool = false + var includeEscrowRecords: Bool = true + var nextFetchErrors: [Error] = [] var fetchViableBottlesError: [Error] = [] var nextJoinErrors: [Error] = [] @@ -205,6 +204,9 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { var returnLeaveTrustResponse: Bool = false var returnRepairErrorResponse: Error? var fetchChangesCalledCount: Int = 0 + var fetchChangesReturnEmptyResponse: Bool = false + + var fetchViableBottlesEscrowRecordCacheTimeout: TimeInterval = 2.0 var nextEstablishReturnsMoreChanges: Bool = false @@ -282,7 +284,7 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } } snapshot.peersByID.forEach { (key: String, _: Peer) in - if nil == self.state.peersByID[key] { + if self.state.peersByID[key] == nil { changes.differences.append(PeerDifference.with { $0.remove = Peer.with { $0.peerID = key @@ -297,7 +299,6 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { if self.state.recoveryEncryptionPubKey != snapshot.recoveryEncryptionPubKey { changes.recoveryEncryptionPubKey = self.state.recoveryEncryptionPubKey ?? Data() } - } } @@ -410,7 +411,6 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { let record = share.fakeRecord(zoneID: rzid) fakeZone.add(toZone: record) allRecords.append(record) - } else { print("Received an unexpected zone id: \(rzid)") } @@ -422,7 +422,7 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { func establish(_ request: EstablishRequest, completion: @escaping (EstablishResponse?, Error?) -> Void) { print("FakeCuttlefish: establish called") if !self.state.peersByID.isEmpty { - completion(nil, FakeCuttlefishError.notEmpty) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .establishFailed)) } // Before performing write, check if we should error @@ -442,6 +442,38 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { self.state.peersByID[request.peer.peerID] = request.peer self.state.bottles.append(request.bottle) + let escrowInformation = EscrowInformation.with { + $0.label = "com.apple.icdp.record." + request.bottle.bottleID + $0.creationDate = Google_Protobuf_Timestamp(date: Date()) + $0.remainingAttempts = 10 + $0.silentAttemptAllowed = 1 + $0.recordStatus = .valid + let e = EscrowInformation.Metadata.with { + $0.backupKeybagDigest = Data() + $0.secureBackupUsesMultipleIcscs = 1 + $0.secureBackupTimestamp = Google_Protobuf_Timestamp(date: Date()) + $0.peerInfo = Data() + $0.bottleID = request.bottle.bottleID + $0.escrowedSpki = request.bottle.escrowedSigningSpki + let cm = EscrowInformation.Metadata.ClientMetadata.with { + $0.deviceColor = "#202020" + $0.deviceEnclosureColor = "#020202" + $0.deviceModel = "model" + $0.deviceModelClass = "modelClass" + $0.deviceModelVersion = "modelVersion" + $0.deviceMid = "mid" + $0.deviceName = "my device" + $0.devicePlatform = 1 + $0.secureBackupNumericPassphraseLength = 6 + $0.secureBackupMetadataTimestamp = Google_Protobuf_Timestamp(date: Date()) + $0.secureBackupUsesNumericPassphrase = 1 + $0.secureBackupUsesComplexPassphrase = 1 + } + $0.clientMetadata = cm + } + $0.escrowInformationMetadata = e + } + self.state.escrowRecords.append(escrowInformation) var keyRecords: [CKRecord] = [] keyRecords.append(contentsOf: store(viewKeys: request.viewKeys)) @@ -490,12 +522,43 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } guard let snapshot = self.snapshotsByChangeToken[request.changeToken] else { - completion(nil, FakeCuttlefishError.unknownChangeToken) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) return } self.state.peersByID[request.peer.peerID] = request.peer self.state.bottles.append(request.bottle) - + let escrowInformation = EscrowInformation.with { + $0.label = "com.apple.icdp.record." + request.bottle.bottleID + $0.creationDate = Google_Protobuf_Timestamp(date: Date()) + $0.remainingAttempts = 10 + $0.silentAttemptAllowed = 1 + $0.recordStatus = .valid + let e = EscrowInformation.Metadata.with { + $0.backupKeybagDigest = Data() + $0.secureBackupUsesMultipleIcscs = 1 + $0.secureBackupTimestamp = Google_Protobuf_Timestamp(date: Date()) + $0.peerInfo = Data() + $0.bottleID = request.bottle.bottleID + $0.escrowedSpki = request.bottle.escrowedSigningSpki + let cm = EscrowInformation.Metadata.ClientMetadata.with { + $0.deviceColor = "#202020" + $0.deviceEnclosureColor = "#020202" + $0.deviceModel = "model" + $0.deviceModelClass = "modelClass" + $0.deviceModelVersion = "modelVersion" + $0.deviceMid = "mid" + $0.deviceName = "my device" + $0.devicePlatform = 1 + $0.secureBackupNumericPassphraseLength = 6 + $0.secureBackupMetadataTimestamp = Google_Protobuf_Timestamp(date: Date()) + $0.secureBackupUsesNumericPassphrase = 1 + $0.secureBackupUsesComplexPassphrase = 1 + } + $0.clientMetadata = cm + } + $0.escrowInformationMetadata = e + } + self.state.escrowRecords.append(escrowInformation) var keyRecords: [CKRecord] = [] keyRecords.append(contentsOf: store(viewKeys: request.viewKeys)) keyRecords.append(contentsOf: store(tlkShares: request.tlkShares)) @@ -520,11 +583,11 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } guard let snapshot = self.snapshotsByChangeToken[request.changeToken] else { - completion(nil, FakeCuttlefishError.unknownChangeToken) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) return } guard var peer = self.state.peersByID[request.peerID] else { - completion(nil, FakeCuttlefishError.unknownPeerID) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .updateTrustPeerNotFound)) return } if request.hasStableInfoAndSig { @@ -580,15 +643,21 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } guard let snapshot = self.snapshotsByChangeToken[request.changeToken] else { - completion(nil, FakeCuttlefishError.unknownChangeToken) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) return } self.state.recoverySigningPubKey = request.recoverySigningPubKey self.state.recoveryEncryptionPubKey = request.recoveryEncryptionPubKey self.state.peersByID[request.peerID]?.stableInfoAndSig = request.stableInfoAndSig + + var keyRecords: [CKRecord] = [] + //keyRecords.append(contentsOf: store(viewKeys: request.viewKeys)) + keyRecords.append(contentsOf: store(tlkShares: request.tlkShares)) + self.makeSnapshot() completion(SetRecoveryKeyResponse.with { $0.changes = self.changesSince(snapshot: snapshot) + $0.zoneKeyHierarchyRecords = keyRecords.map { try! CloudKitCode.Ckcode_RecordTransport($0) } }, nil) self.pushNotify("setRecoveryKey") } @@ -604,6 +673,10 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { completion(nil, possibleError) return } + if fetchChangesReturnEmptyResponse == true { + completion(FetchChangesResponse(), nil) + return + } } if let injectedError = self.nextFetchErrors.first { @@ -614,11 +687,11 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { } let snapshot: State - if request.changeToken == "" { + if request.changeToken.isEmpty { snapshot = State() } else { guard let s = self.snapshotsByChangeToken[request.changeToken] else { - completion(nil, FakeCuttlefishError.unknownChangeToken) + completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) return } snapshot = s @@ -648,14 +721,29 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { return } + var legacy: [EscrowInformation] = [] + if self.injectLegacyEscrowRecords { + print("FakeCuttlefish: fetchViableBottles injecting legacy records") + let record = EscrowInformation.with { + $0.label = "fake-label" + } + legacy.append(record) + } let bottles = self.state.bottles.filter { $0.bottleID != fetchViableBottlesDontReturnBottleWithID } + completion(FetchViableBottlesResponse.with { $0.viableBottles = bottles.compactMap { bottle in EscrowPair.with { $0.escrowRecordID = bottle.bottleID $0.bottle = bottle + if self.includeEscrowRecords { + $0.record = self.state.escrowRecords.first { $0.escrowInformationMetadata.bottleID == bottle.bottleID } ?? EscrowInformation() + } } } + if self.injectLegacyEscrowRecords { + $0.legacyRecords = legacy + } }, nil) } @@ -754,6 +842,10 @@ class FakeCuttlefishServer: CuttlefishAPIAsync { func getSupportAppInfo(_: GetSupportAppInfoRequest, completion: @escaping (GetSupportAppInfoResponse?, Error?) -> Void) { completion(GetSupportAppInfoResponse(), nil) } + + func fetchSosiCloudIdentity(_: FetchSOSiCloudIdentityRequest, completion: @escaping (FetchSOSiCloudIdentityResponse?, Error?) -> Void) { + completion(FetchSOSiCloudIdentityResponse(), nil) + } } extension FakeCuttlefishServer: CloudKitCode.Invocable { diff --git a/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift b/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift index 8289a40e..083d98be 100644 --- a/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift +++ b/keychain/TrustedPeersHelperUnitTests/MockCuttlefish.swift @@ -21,7 +21,6 @@ enum Handler { } class MockCuttlefishAPIAsyncClient: CuttlefishAPIAsync { - var handlers: [Handler] = [] var index: Int = 0 @@ -164,7 +163,6 @@ class MockCuttlefishAPIAsyncClient: CuttlefishAPIAsync { } func getRepairAction(_: GetRepairActionRequest, completion: @escaping (GetRepairActionResponse?, Error?) -> Void) { completion(GetRepairActionResponse(), nil) - } func getSupportAppInfo(_: GetSupportAppInfoRequest, completion: @escaping (GetSupportAppInfoResponse?, Error?) -> Void) { completion(GetSupportAppInfoResponse(), nil) @@ -172,4 +170,7 @@ class MockCuttlefishAPIAsyncClient: CuttlefishAPIAsync { func getClubCertificates(_: GetClubCertificatesRequest, completion: @escaping (GetClubCertificatesResponse?, Error?) -> Void) { completion(GetClubCertificatesResponse(), nil) } + func fetchSosiCloudIdentity(_: FetchSOSiCloudIdentityRequest, completion: @escaping (FetchSOSiCloudIdentityResponse?, Error?) -> Void) { + completion(FetchSOSiCloudIdentityResponse(), nil) + } } diff --git a/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h b/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h index fc2d9223..9753ef8d 100644 --- a/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h +++ b/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests-BridgingHeader.h @@ -19,5 +19,6 @@ #import #import "keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h" +#import "keychain/securityd/SecItemDataSource.h" #import "keychain/ckks/tests/MockCloudKit.h" diff --git a/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests.swift b/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests.swift index c5f2b3f7..1ed9145c 100644 --- a/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests.swift +++ b/keychain/TrustedPeersHelperUnitTests/TrustedPeersHelperUnitTests.swift @@ -5,6 +5,7 @@ // Created by Ben Williamson on 5/1/18. // +import CloudKitCodeProtobuf import CoreData import XCTest @@ -21,7 +22,6 @@ let recovery_signingKey_384 = Data(base64Encoded: "BK5nrmP6oitJHtGV2Josk5cUKnG3p let recovery_encryptionKey_384 = Data(base64Encoded: "BKkZpYHTbMi2yrWFo+ErM3HbcYJCngPuWDYoVUD7egKkmiHFvv1Bsk0j/Dcj3xTR12vj5QOpZQV3GzE5estf75BV+EZz1cjUUSi/MysfpKsqEbwYrhIEkmeyMGr7CVWQWRLR2LnoihnQajvWi1LmO0AoDl3+LzVgTJBjjDQ5ANyw0Yv1EgOgBvZsLA9UTN4oAg==") class TrustedPeersHelperUnitTests: XCTestCase { - var tmpPath: String! var tmpURL: URL! var cuttlefish: FakeCuttlefishServer! @@ -46,7 +46,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { cuttlefish = FakeCuttlefishServer(nil, ckZones: [:], ckksZoneKeys: [:]) // Make a new fake keychain - tmpPath = String(format: "/tmp/%@-%X", testName, arc4random()) + tmpPath = String(format: "/tmp/%@-%X", testName, Int.random(in: 0..<1000000)) tmpURL = URL(fileURLWithPath: tmpPath, isDirectory: true) do { try FileManager.default.createDirectory(atPath: String(format: "%@/Library/Keychains", tmpPath), withIntermediateDirectories: true, attributes: nil) @@ -72,6 +72,23 @@ class TrustedPeersHelperUnitTests: XCTestCase { override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. cuttlefish = nil + + if let nskeychainDir : NSURL = SecCopyHomeURL(), let keychainDir : URL = nskeychainDir as URL? { + SecItemDataSourceFactoryReleaseAll() + SecKeychainDbForceClose() + SecKeychainDbReset(nil) + + // Only perform the destructive step if the url matches what we expect! + let testName = self.name.components(separatedBy: CharacterSet(charactersIn: " ]"))[1] + if keychainDir.path.hasPrefix("/tmp/" + testName) { + do { + try FileManager.default.removeItem(at: keychainDir) + } catch { + print("Failed to remove keychain directory: \(error)") + } + } + } + super.tearDown() } @@ -164,15 +181,24 @@ class TrustedPeersHelperUnitTests: XCTestCase { contextID: String, allowedMachineIDs: Set = Set(["aaa", "bbb", "ccc"]), accountIsDemo: Bool, + modelID: String = "iPhone1,1", + syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus = .UNKNOWN, store: NSPersistentStoreDescription) throws -> (Container, String) { var container = try Container(name: ContainerName(container: "test", context: contextID), persistentStoreDescription: store, cuttlefish: cuttlefish) XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: allowedMachineIDs, accountIsDemo: accountIsDemo, listDifference: !allowedMachineIDs.isEmpty), "should be able to set allowed machine IDs") - let (peerID, permanentInfo, permanentInfoSig, _, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, + epoch: 1, + machineID: "aaa", + bottleSalt: "123456789", + bottleID: UUID().uuidString, + modelID: modelID, + syncUserControllableViews: syncUserControllableViews) + do { let state = container.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == peerID }, "should have a bottle for peer") let secret = container.loadSecretSync(test: self, label: peerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -192,7 +218,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { } } - let (peerID2, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID2, _, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error2) XCTAssertNotNil(peerID2) @@ -203,24 +229,97 @@ class TrustedPeersHelperUnitTests: XCTestCase { func testEstablishWithReload() throws { let description = tmpStoreDescription(name: "container.db") - let (_, peerID) = try establish(reload: true, store: description) + let (container, peerID) = try establish(reload: true, store: description) assertTLKShareFor(peerID: peerID, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + // With no other input, the syncing policy should say to sync user views + let (policy, _, policyError) = container.fetchCurrentPolicySync(test: self) + XCTAssertNil(policyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(policy, "Should have a syncing policy") + XCTAssertEqual(policy?.syncUserControllableViews, .DISABLED, "Peer should not desire to sync user controllable views (as the client didn't have any input)") } func testEstablishNoReload() throws { let description = tmpStoreDescription(name: "container.db") - _ = try establish(reload: false, store: description) + let (container, peerID) = try establish(reload: false, store: description) + + assertTLKShareFor(peerID: peerID, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + // With no other input, the syncing policy should say to sync user views + let (policy, _, policyError) = container.fetchCurrentPolicySync(test: self) + XCTAssertNil(policyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(policy, "Should have a syncing policy") + XCTAssertEqual(policy?.syncUserControllableViews, .DISABLED, "Peer should not desire to sync user controllable views (as the client didn't have any input)") + } + + func testEstablishWithUserSyncableViews() throws { + let description = tmpStoreDescription(name: "container.db") + + let (container, peerID) = try self.establish(reload: false, + contextID: OTDefaultContext, + accountIsDemo: false, + syncUserControllableViews: .ENABLED, + store: description) + + assertTLKShareFor(peerID: peerID, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + //The syncing policy should say not to sync user views + let (policy, _, policyError) = container.fetchCurrentPolicySync(test: self) + XCTAssertNil(policyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(policy, "Should have a syncing policy") + + XCTAssertEqual(policy?.syncUserControllableViews, .ENABLED, "Peer should desire to sync user controllable views (per request)") + } + + func testEstablishWithoutUserSyncableViews() throws { + let description = tmpStoreDescription(name: "container.db") + + let (container, peerID) = try self.establish(reload: false, + contextID: OTDefaultContext, + accountIsDemo: false, + syncUserControllableViews: .DISABLED, + store: description) + + assertTLKShareFor(peerID: peerID, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + //The syncing policy should say not to sync user views + let (policy, _, policyError) = container.fetchCurrentPolicySync(test: self) + XCTAssertNil(policyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(policy, "Should have a syncing policy") + + XCTAssertEqual(policy?.syncUserControllableViews, .DISABLED, "Peer should not desire to sync user controllable views (per request)") + } + + func testEstablishWithoutUserSyncableViewsOnWatch() throws { + let description = tmpStoreDescription(name: "container.db") + + // Watches will listen to the input here. If we set FOLLOWING, it should remain FOLLOWING (as some watches don't have UI to change this value) + let (container, peerID) = try self.establish(reload: false, + contextID: OTDefaultContext, + accountIsDemo: false, + modelID: "Watch1,1", + syncUserControllableViews: .FOLLOWING, + store: description) + + assertTLKShareFor(peerID: peerID, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + //The syncing policy should say not to sync user views + let (policy, _, policyError) = container.fetchCurrentPolicySync(test: self) + XCTAssertNil(policyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(policy, "Should have a syncing policy") + + XCTAssertEqual(policy?.syncUserControllableViews, .FOLLOWING, "Peer should desire to sync user controllable views (ignoring the request)") } func testEstablishNotOnAllowListErrors() throws { let description = tmpStoreDescription(name: "container.db") let container = try Container(name: ContainerName(container: "test", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, _, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = container.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == peerID }, "should have a bottle for peer") let secret = container.loadSecretSync(test: self, label: peerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -235,7 +334,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { // Now set up a machine ID list that positively does not have our peer XCTAssertNil(container.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa"], accountIsDemo: false), "should be able to set allowed machine IDs") - let (peerID3, _, error3) = container.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID3, _, _, error3) = container.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNotNil(peerID3, "Should get a peer when you establish a now allow-listed peer") XCTAssertNil(error3, "Should not get an error when you establish a now allow-listed peer") } @@ -253,7 +352,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(c.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: accountIsDemo, listDifference: !machineIDs.isEmpty), "Should be able to set machine IDs") print("preparing \(containerID)") - let (peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error) = + let (peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error) = c.prepareSync(test: self, epoch: 1, machineID: machineID, bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(peerID) @@ -282,11 +381,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertTLKShareFor(peerID: peerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("\(containerID) joins") - let (joinedPeerID, _, _, _, joinError) = c.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [], - tlkShares: []) + let (joinedPeerID, _, _, joinError) = c.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) XCTAssertNil(joinError) XCTAssertEqual(joinedPeerID, peerID!) } @@ -306,15 +405,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerC.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aViewList, aPolicy, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") - XCTAssertNotNil(aViewList, "Should have a view list coming back from a successful prepare") - XCTAssertNotNil(aPolicy, "Should have a policy coming back from a successful prepare") + XCTAssertNotNil(aPolicy, "Should have a syncing policy coming back from a successful prepare") XCTAssertEqual(aPolicy?.version, prevailingPolicyVersion, "Policy coming back from prepare() should be prevailing policy version") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .UNKNOWN, "Policy coming back from prepare() should not have an opinion on views") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -326,17 +425,25 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } + do { + // With no other input, the syncing policy should say to sync user views + let (aPolicy, _, aPolicyError) = containerA.fetchCurrentPolicySync(test: self) + XCTAssertNil(aPolicyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(aPolicy, "Should have a syncing policy") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .DISABLED, "Peer should desire to not sync user controllable views (as the client didn't have any input)") + } + print("preparing B") - let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, _, error2) = + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -392,13 +499,16 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, _, _, error) = containerB.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [], - tlkShares: []) + let (peerID, _, bPolicy, error) = containerB.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) XCTAssertNil(error) XCTAssertEqual(peerID, bPeerID!) + + XCTAssertNotNil(bPolicy, "Should have a syncing policy") + XCTAssertEqual(bPolicy?.syncUserControllableViews, .DISABLED, "Peer should desire to not sync user controllable views (following A's lead)") } _ = containerA.dumpSync(test: self) @@ -406,11 +516,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerC.dumpSync(test: self) print("preparing C") - let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, _, _, error4) = + let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, _, error4) = containerC.prepareSync(test: self, epoch: 1, machineID: "ccc", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerC.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == cPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == cPeerID }, "should have a bottle for peer") let secret = containerC.loadSecretSync(test: self, label: cPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -444,14 +554,17 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertTLKShareFor(peerID: cPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("C joins") - let (peerID, _, _, _, error2) = containerC.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [self.manateeKeySet, provisionalEngramKeySet], - tlkShares: []) + let (peerID, _, cPolicy, error2) = containerC.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [self.manateeKeySet, provisionalEngramKeySet], + tlkShares: []) XCTAssertNil(error2) XCTAssertEqual(peerID, cPeerID!) + XCTAssertNotNil(cPolicy, "Should have a syncing policy") + XCTAssertEqual(cPolicy?.syncUserControllableViews, .DISABLED, "Peer should desire to not sync user controllable views (following A and B's lead)") + assertTLKShareFor(peerID: cPeerID!, keyUUID: provisionalEngramKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Engram")) assertTLKShareFor(peerID: aPeerID!, keyUUID: provisionalEngramKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Engram")) assertTLKShareFor(peerID: bPeerID!, keyUUID: provisionalEngramKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Engram")) @@ -459,7 +572,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("A updates") do { - let (_, error) = containerA.updateSync(test: self) + let (_, _, error) = containerA.updateSync(test: self) XCTAssertNil(error) } @@ -474,15 +587,130 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerC.dumpSync(test: self) } + func testJoinWithEnabledUserControllableViews() throws { + let description = tmpStoreDescription(name: "container.db") + let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + + let machineIDs = Set(["aaa", "bbb", "ccc"]) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + + print("preparing A") + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) = + containerA.prepareSync(test: self, + epoch: 1, + machineID: "aaa", + bottleSalt: "123456789", + bottleID: UUID().uuidString, + modelID: "iPhone1,1", + syncUserControllableViews: .ENABLED) + XCTAssertNotNil(aPolicy, "Should have a syncing policy coming back from a successful prepare") + XCTAssertEqual(aPolicy?.version, prevailingPolicyVersion, "Policy coming back from prepare() should be prevailing policy version") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .ENABLED, "Policy coming back from prepare() should already have an opinion of user view syncing") + + XCTAssertNil(error) + XCTAssertNotNil(aPeerID) + XCTAssertNotNil(aPermanentInfo) + XCTAssertNotNil(aPermanentInfoSig) + + print("establishing A") + do { + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + XCTAssertNil(error) + XCTAssertNotNil(peerID) + } + + do { + let (aPolicy, _, aPolicyError) = containerA.fetchCurrentPolicySync(test: self) + XCTAssertNil(aPolicyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(aPolicy, "Should have a syncing policy") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .ENABLED, "Peer should desire to sync user controllable views (as per request)") + } + + print("preparing B") + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, error2) = + containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + let state = containerB.getStateSync(test: self) + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") + let secret = containerB.loadSecretSync(test: self, label: bPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNil(error2) + XCTAssertNotNil(bPeerID) + XCTAssertNotNil(bPermanentInfo) + XCTAssertNotNil(bPermanentInfoSig) + + do { + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + print("A vouches for B, but doesn't provide any TLKShares") + let (_, _, errorVouchingWithoutTLKs) = + containerA.vouchSync(test: self, + peerID: bPeerID!, + permanentInfo: bPermanentInfo!, + permanentInfoSig: bPermanentInfoSig!, + stableInfo: bStableInfo!, + stableInfoSig: bStableInfoSig!, + ckksKeys: []) + XCTAssertNil(errorVouchingWithoutTLKs, "Should be no error vouching without uploading TLKShares") + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("A vouches for B, but doesn't only has provisional TLKs at the time") + let provisionalManateeKeySet = try self.makeFakeKeyHierarchy(zoneID: CKRecordZone.ID(zoneName: "Manatee")) + provisionalManateeKeySet.newUpload = true + + let (_, _, errorVouchingWithProvisionalTLKs) = + containerA.vouchSync(test: self, + peerID: bPeerID!, + permanentInfo: bPermanentInfo!, + permanentInfoSig: bPermanentInfoSig!, + stableInfo: bStableInfo!, + stableInfoSig: bStableInfoSig!, + ckksKeys: [provisionalManateeKeySet]) + XCTAssertNil(errorVouchingWithProvisionalTLKs, "Should be no error vouching without uploading TLKShares for a non-existent key") + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("A vouches for B") + let (voucherData, voucherSig, error3) = + containerA.vouchSync(test: self, + peerID: bPeerID!, + permanentInfo: bPermanentInfo!, + permanentInfoSig: bPermanentInfoSig!, + stableInfo: bStableInfo!, + stableInfoSig: bStableInfoSig!, + ckksKeys: [self.manateeKeySet]) + XCTAssertNil(error3) + XCTAssertNotNil(voucherData) + XCTAssertNotNil(voucherSig) + + // As part of the vouch, A should have uploaded a tlkshare for B + assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("B joins") + let (peerID, _, bPolicy, error) = containerB.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) + XCTAssertNil(error) + XCTAssertEqual(peerID, bPeerID!) + + XCTAssertNotNil(bPolicy, "Should have a syncing policy") + XCTAssertEqual(bPolicy?.syncUserControllableViews, .ENABLED, "Peer should desire to sync user controllable views (following A's lead)") + } + } + func testJoinWithoutAllowListErrors() throws { let description = tmpStoreDescription(name: "container.db") let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, _, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == peerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: peerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -494,16 +722,16 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: ["aaa"], accountIsDemo: false), "should be able to set allowed machine IDs") - let (peerID2, _, error2) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID2, _, _, error2) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNotNil(peerID2, "Should get a peer when you establish a now allow-listed peer") XCTAssertNil(error2, "Should not get an error when you establish a now allow-listed peer") print("preparing B") - let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, _, errorPrepareB) = + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, errorPrepareB) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == peerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: peerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -530,11 +758,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNotNil(voucherSig, "Should have a signature from A") print("B joins") - let (peerID, _, _, _, error) = containerB.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [], - tlkShares: []) + let (peerID, _, _, error) = containerB.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) XCTAssertNotNil(error, "Should have an error joining with an unapproved machine ID") XCTAssertNil(peerID, "Should not receive a peer ID joining with an unapproved machine ID") } @@ -548,10 +776,10 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -564,7 +792,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { assertNoTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) assertTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) @@ -591,10 +819,10 @@ class TrustedPeersHelperUnitTests: XCTestCase { let machineIDs = Set(["aaa"]) XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -619,6 +847,8 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { let error = containerA.localResetSync(test: self) XCTAssertNil(error, "local-reset shouldn't error") + let peers = containerA.containerMO.peers as! Set + XCTAssertEqual(peers.count, 0, "peers should be empty ") } do { let (dict, error) = containerA.dumpSync(test: self) @@ -645,24 +875,24 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerC.setAllowedMachineIDsSync(test: self, allowedMachineIDs: Set(["aaa", "bbb", "ccc"]), accountIsDemo: false)) print("preparing") - let (peerID, _, _, _, _, _, _, _) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, _, _, _, _, _, _) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == peerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: peerID!) XCTAssertNotNil(secret, "secret should not be nil") } - let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, _, _) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, _) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") } - let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, _, _, _) = containerC.prepareSync(test: self, epoch: 1, machineID: "ccc", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, _, _) = containerC.prepareSync(test: self, epoch: 1, machineID: "ccc", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerC.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == cPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == cPeerID }, "should have a bottle for peer") let secret = containerC.loadSecretSync(test: self, label: cPeerID!) XCTAssertNotNil(secret, "secret should not be nil") } @@ -747,7 +977,6 @@ class TrustedPeersHelperUnitTests: XCTestCase { // TODO: need a real configurable mock cuttlefish func testFetchPolicyDocuments() throws { - // 1 is known locally via builtin, 3 is not but is known to cuttlefish let missingTuple = TPPolicyVersion(version: 900, hash: "not a hash") @@ -808,7 +1037,6 @@ class TrustedPeersHelperUnitTests: XCTestCase { } func testEscrowKeys() throws { - XCTAssertThrowsError(try EscrowKeys.retrieveEscrowKeysFromKeychain(label: "hash"), "retrieveEscrowKeysFromKeychain should throw error") XCTAssertThrowsError(try EscrowKeys.findEscrowKeysForLabel(label: "hash"), "findEscrowKeysForLabel should throw error") @@ -843,7 +1071,6 @@ class TrustedPeersHelperUnitTests: XCTestCase { } func testEscrowKeyTestVectors() { - let secretString = "I'm a secretI'm a secretI'm a secretI'm a secretI'm a secretI'm a secret" let secret = secretString.data(using: .utf8) @@ -911,11 +1138,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") bottleA = state.bottles.removeFirst() @@ -930,14 +1157,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { assertNoTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) assertTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -947,11 +1174,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -961,10 +1188,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B prepares to join via bottle") - let (bottlePeerID, views, policy, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") - XCTAssertNotNil(views, "Should have a set of views to restore") XCTAssertNotNil(policy, "Should have a policy") let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) @@ -977,7 +1203,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) + let (peerID, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) XCTAssertNil(error) XCTAssertEqual(peerID, bPeerID!) @@ -998,11 +1224,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") bottleA = state.bottles.removeFirst() @@ -1017,14 +1243,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { assertNoTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) assertTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -1034,11 +1260,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1048,10 +1274,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B prepares to join via bottle") - let (bottlePeerID, views, policy, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") - XCTAssertNotNil(views, "Should have a set of views to restore") XCTAssertNotNil(policy, "Should have a policy") let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) @@ -1064,7 +1289,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) + let (peerID, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) XCTAssertNil(error) XCTAssertEqual(peerID, bPeerID!) @@ -1084,11 +1309,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1100,13 +1325,13 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -1116,11 +1341,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1130,10 +1355,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B joins via bottle") - let (bottlePeerID, views, policy, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: "wrong escrow record") + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: "wrong escrow record") XCTAssertNotNil(errorPreflight, "Should be an error preflighting bottle that doesn't exist") XCTAssertNil(bottlePeerID, "peerID should be nil for no bottle") - XCTAssertNil(views, "Should not have a set of views to restore") XCTAssertNil(policy, "Should not have a policy") let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: "wrong escrow record", entropy: entropy, bottleSalt: "123456789", tlkShares: []) @@ -1156,11 +1380,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1172,13 +1396,13 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -1186,11 +1410,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { } print("preparing B") - let (bPeerID, _, _, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") bottleB = state.bottles.removeFirst() let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") @@ -1201,10 +1425,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B joins via bottle") - let (bottlePeerID, views, policy, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleB.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleB.bottleID!) XCTAssertNotNil(errorPreflight, "Should be an error preflighting bottle that doesn't correspond to a peer") XCTAssertNil(bottlePeerID, "Should have no peer for invalid bottle") - XCTAssertNil(views, "Should not have a set of views to restore") XCTAssertNil(policy, "Should not have a policy") let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleB.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) @@ -1227,11 +1450,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) bottleA = state.bottles.removeFirst() XCTAssertNotNil(secret, "secret should not be nil") @@ -1244,13 +1467,13 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -1260,11 +1483,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1274,10 +1497,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B joins via bottle") - let (bottlePeerID, views, policy, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") - XCTAssertNotNil(views, "Should have a set of views to restore") XCTAssertNotNil(policy, "Should have a policy") let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "987654321", tlkShares: []) @@ -1299,11 +1521,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) bottleA = state.bottles.removeFirst() XCTAssertNotNil(secret, "secret should not be nil") @@ -1316,13 +1538,13 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1331,11 +1553,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1345,10 +1567,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B joins via bottle") - let (bottlePeerID, views, policy, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") - XCTAssertNotNil(views, "Should have a set of views to restore") XCTAssertNotNil(policy, "Should have a policy") let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: Data(count: Int(OTMasterSecretLength)), bottleSalt: "123456789", tlkShares: []) @@ -1371,11 +1592,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! bottleA = state.bottles.removeFirst() @@ -1389,24 +1610,24 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") } print("preparing B") - let (bPeerID, _, _, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1418,10 +1639,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { self.cuttlefish.fetchViableBottlesError.append(FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) - let (bottlePeerID, views, policy, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNotNil(errorPreflight, "Should be an error preflighting a vouch with bottle with a fetch error") XCTAssertNil(bottlePeerID, "peerID should be nil") - XCTAssertNil(views, "Should not have a set of views to restore") XCTAssertNil(policy, "Should not have a policy") self.cuttlefish.fetchViableBottlesError.append(FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) @@ -1438,29 +1658,37 @@ class TrustedPeersHelperUnitTests: XCTestCase { let description = tmpStoreDescription(name: "container.db") let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + let containerC = try Container(name: ContainerName(container: "c", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) - let machineIDs = Set(["aaa", "bbb"]) + let machineIDs = Set(["aaa", "bbb", "ccc"]) XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerC.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aViewList, aPolicy, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(aPeerID) XCTAssertNotNil(aPermanentInfo) XCTAssertNotNil(aPermanentInfoSig) - XCTAssertNotNil(aViewList, "Should have a view list coming back from a successful prepare") XCTAssertNotNil(aPolicy, "Should have a policy coming back from a successful prepare") XCTAssertEqual(aPolicy?.version, prevailingPolicyVersion, "Policy coming back from prepare() should be prevailing policy version") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .UNKNOWN, "Policy shouldn't yet know whether we want to sync user views") print("preparing B") - let (bPeerID, bPermanentInfo, bPermanentInfoSig, _, _, _, _, error2) = - containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (bPeerID, bPermanentInfo, bPermanentInfoSig, _, _, _, error2) = + containerB.prepareSync(test: self, + epoch: 1, + machineID: "bbb", + bottleSalt: "123456789", + bottleID: UUID().uuidString, + modelID: "iPhone1,1", + syncUserControllableViews: .DISABLED) do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1470,34 +1698,96 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNotNil(bPermanentInfo) XCTAssertNotNil(bPermanentInfoSig) - // Now, A establishes preapproving B + print("preparing C") + let (cPeerID, cPermanentInfo, cPermanentInfoSig, _, _, _, cPrepareError) = + containerC.prepareSync(test: self, + epoch: 1, + machineID: "ccc", + bottleSalt: "123456789", + bottleID: UUID().uuidString, + modelID: "iPhone1,1", + syncUserControllableViews: .ENABLED) + do { + let state = containerC.getStateSync(test: self) + XCTAssertTrue(state.bottles.contains { $0.peerID == cPeerID }, "should have a bottle for peer") + let secret = containerC.loadSecretSync(test: self, label: cPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNil(cPrepareError) + XCTAssertNotNil(cPeerID) + XCTAssertNotNil(cPermanentInfo) + XCTAssertNotNil(cPermanentInfoSig) + + // Now, A establishes preapproving B & C // Note: secd is responsible for passing in TLKShares to these preapproved keys in sosTLKShares + let aPermanentInfoParsed = TPPeerPermanentInfo(peerID: aPeerID!, data: aPermanentInfo!, sig: aPermanentInfoSig!, keyFactory: TPECPublicKeyFactory()) + XCTAssertNotNil(aPermanentInfoParsed, "Should have parsed A's permanent info") + let bPermanentInfoParsed = TPPeerPermanentInfo(peerID: bPeerID!, data: bPermanentInfo!, sig: bPermanentInfoSig!, keyFactory: TPECPublicKeyFactory()) XCTAssertNotNil(bPermanentInfoParsed, "Should have parsed B's permanent info") + let cPermanentInfoParsed = TPPeerPermanentInfo(peerID: cPeerID!, data: cPermanentInfo!, sig: cPermanentInfoSig!, keyFactory: TPECPublicKeyFactory()) + XCTAssertNotNil(cPermanentInfoParsed, "Should have parsed C's permanent info") + + print(bPermanentInfoParsed!.signingPubKey.spki().base64EncodedString()) + print(cPermanentInfoParsed!.signingPubKey.spki().base64EncodedString()) + print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: [bPermanentInfoParsed!.signingPubKey.spki()]) + let (peerID, _, _, error) = containerA.establishSync(test: self, + ckksKeys: [self.manateeKeySet], + tlkShares: [], + preapprovedKeys: [bPermanentInfoParsed!.signingPubKey.spki(), + cPermanentInfoParsed!.signingPubKey.spki(), ]) XCTAssertNil(error) XCTAssertNotNil(peerID) + + let (aPolicy, _, aPolicyError) = containerA.fetchCurrentPolicySync(test: self) + XCTAssertNil(aPolicyError, "Should be no error fetching aPolicy") + XCTAssertNotNil(aPolicy, "Should have a syncing policy") + XCTAssertEqual(aPolicy?.syncUserControllableViews, .DISABLED, "A should desire to not ync user controllable views (as the client didn't have any input)") } do { assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins by preapproval, and uploads all TLKShares that it has") - let (bJoinedPeerID, _, views, policy, bJoinedError) = containerB.preapprovedJoinSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: []) + let (bJoinedPeerID, _, bPolicy, bJoinedError) = containerB.preapprovedJoinSync(test: self, + ckksKeys: [self.manateeKeySet], + tlkShares: [], + preapprovedKeys: [aPermanentInfoParsed!.signingPubKey.spki(), + cPermanentInfoParsed!.signingPubKey.spki(), ]) XCTAssertNil(bJoinedError, "Should be no error joining by preapproval") XCTAssertNotNil(bJoinedPeerID, "Should have a peer ID out of join") - XCTAssertNotNil(views, "should have a list of views to use") - XCTAssertNotNil(policy, "Should have a policy back from preapprovedjoin") + XCTAssertNotNil(bPolicy, "Should have a policy back from preapprovedjoin") + XCTAssertEqual(bPolicy?.syncUserControllableViews, .DISABLED, "Policy should say not to sync user controllable views") assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) } + do { + assertNoTLKShareFor(peerID: cPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("B joins by preapproval, and uploads all TLKShares that it has") + let (cJoinedPeerID, _, cPolicy, cJoinedError) = containerC.preapprovedJoinSync(test: self, + ckksKeys: [self.manateeKeySet], + tlkShares: [], + preapprovedKeys: [aPermanentInfoParsed!.signingPubKey.spki(), + bPermanentInfoParsed!.signingPubKey.spki(), ]) + XCTAssertNil(cJoinedError, "Should be no error joining by preapproval") + XCTAssertNotNil(cJoinedPeerID, "Should have a peer ID out of join") + XCTAssertEqual(cPeerID, cJoinedPeerID, "PeerID after joining should match") + XCTAssertNotNil(cPolicy, "Should have a policy back from preapprovedjoin") + XCTAssertEqual(cPolicy?.syncUserControllableViews, .ENABLED, "Policy should say to sync user controllable views") + + assertTLKShareFor(peerID: cPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + } + _ = containerA.dumpSync(test: self) _ = containerB.dumpSync(test: self) + _ = containerC.dumpSync(test: self) } func testDepart() throws { @@ -1524,7 +1814,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { machineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, store: store) - let (_, cUpdateError) = c.updateSync(test: self) + let (_, _, cUpdateError) = c.updateSync(test: self) XCTAssertNil(cUpdateError, "Should be able to update first container") assertTrusts(context: c, peerIDs: [peerID1, peerID2, peerID3]) @@ -1540,11 +1830,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertDistrusts(context: c, peerIDs: [peerID2, peerID3]) // peers should accept their fates - let (_, c2UpdateError) = c2.updateSync(test: self) + let (_, _, c2UpdateError) = c2.updateSync(test: self) XCTAssertNil(c2UpdateError, "Should be able to update second container") assertDistrusts(context: c2, peerIDs: [peerID2]) - let (_, c3UpdateError) = c3.updateSync(test: self) + let (_, _, c3UpdateError) = c3.updateSync(test: self) XCTAssertNil(c3UpdateError, "Should be able to update third container") assertDistrusts(context: c3, peerIDs: [peerID3]) } @@ -1558,7 +1848,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { // And the first container fetches again, which should succeed self.cuttlefish.nextFetchErrors.append(FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired)) - let (_, updateError) = c.updateSync(test: self) + let (_, _, updateError) = c.updateSync(test: self) XCTAssertNil(updateError, "Update should have succeeded") // and c's model should only include peerID2 @@ -1618,7 +1908,6 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNotNil(deserializedBottle, "deserializedBottle should not be nil") XCTAssertEqual(deserializedBottle.contents, bottle.contents, "bottle data should be equal") - } catch { XCTFail("error testing bottles \(error)") } @@ -1636,12 +1925,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { let state = c.getStateSync(test: self) XCTAssertEqual(state.bottles.count, 1, "first container should have a bottle for peer") + XCTAssertEqual(state.escrowRecords.count, 1, "first container should have an escrow record for peer") } let c2 = try Container(name: ContainerName(container: "test", context: "newcomer"), persistentStoreDescription: store, cuttlefish: self.cuttlefish) do { let state = c2.getStateSync(test: self) XCTAssertEqual(state.bottles.count, 0, "before fetch, second container should not have any stored bottles") + XCTAssertEqual(state.escrowRecords.count, 0, "before fetch, second container should not have any escrow records") } let (c2bottles, _, c2FetchError) = c2.fetchViableBottlesSync(test: self) @@ -1652,6 +1943,128 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { let state = c2.getStateSync(test: self) XCTAssertEqual(state.bottles.count, 1, "after fetch, second container should have one stored bottles") + XCTAssertEqual(state.escrowRecords.count, 1, "after fetch, second container should have one escrow record") + } + } + + func testFetchBottlesAfterCacheExpires() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + var bottleA: BottleMO + var entropy: Data + let description = tmpStoreDescription(name: "container.db") + let containerA = try Container(name: ContainerName(container: "a", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + let containerB = try Container(name: ContainerName(container: "b", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) + + let machineIDs = Set(["aaa", "bbb"]) + XCTAssertNil(containerA.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) + + print("preparing A") + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = + containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + var state = containerA.getStateSync(test: self) + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") + + bottleA = state.bottles.removeFirst() + + let secret = containerA.loadSecretSync(test: self, label: aPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNotNil(aPeerID) + XCTAssertNotNil(aPermanentInfo) + XCTAssertNotNil(aPermanentInfoSig) + + print("establishing A") + do { + assertNoTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + XCTAssertNil(error) + XCTAssertNotNil(peerID) + assertTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + } + do { + let state = containerA.getStateSync(test: self) + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") + let secret = containerA.loadSecretSync(test: self, label: aPeerID!) + entropy = secret! + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + + let (bottles, _, fetchError) = containerA.fetchViableBottlesSync(test: self) + XCTAssertNil(fetchError, "should be no error fetching viable bottles") + XCTAssertNotNil(bottles, "should have fetched some bottles") + XCTAssertEqual(bottles!.count, 1, "should have fetched one bottle") + + do { + let state = containerA.getStateSync(test: self) + XCTAssertEqual(state.bottles.count, 1, "first container should have a bottle for peer") + XCTAssertEqual(state.escrowRecords.count, 1, "first container should have an escrow record for peer") + } + + //have another peer join + _ = containerB.updateSync(test: self) + + print("preparing B") + let (bPeerID, _, _, _, _, _, error2) = + containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + do { + let state = containerB.getStateSync(test: self) + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") + let secret = containerB.loadSecretSync(test: self, label: bPeerID!) + XCTAssertNotNil(secret, "secret should not be nil") + XCTAssertNil(error, "error should be nil") + } + XCTAssertNil(error2) + + do { + print("B prepares to join via bottle") + + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") + XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") + XCTAssertNotNil(policy, "Should have a policy") + + let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) + + XCTAssertNil(error3) + XCTAssertNotNil(voucherData) + XCTAssertNotNil(voucherSig) + + // Before B joins, there should be no TLKShares for B + assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + + print("B joins") + let (peerID, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) + XCTAssertNil(error) + XCTAssertEqual(peerID, bPeerID!) + + // But afterward, it has one! + assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) + } + + //now fetch bottles and we should get the cached version + let (_, _, _) = containerA.fetchViableBottlesSync(test: self) + do { + let state = containerA.getStateSync(test: self) + XCTAssertEqual(state.bottles.count, 1, "first container should have a bottle for peer") + XCTAssertEqual(state.escrowRecords.count, 1, "first container should have an escrow record for peer") + } + + sleep(2) + + //now fetch bottles again after the cache expired + containerA.escrowCacheTimeout = 2.0 + + let (_, _, _) = containerA.fetchViableBottlesSync(test: self) + do { + let state = containerA.getStateSync(test: self) + XCTAssertEqual(state.bottles.count, 2, "container A should have 2 bottles") + XCTAssertEqual(state.escrowRecords.count, 2, "container A should have 2 escrow records") } } @@ -1711,18 +2124,18 @@ class TrustedPeersHelperUnitTests: XCTestCase { let store = tmpStoreDescription(name: "container.db") let c = try Container(name: ContainerName(container: "c", context: "context"), - persistentStoreDescription: store, - cuttlefish: self.cuttlefish) + persistentStoreDescription: store, + cuttlefish: self.cuttlefish) let machineIDs = Set(["aaa", "bbb", "ccc"]) XCTAssertNil(c.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing peer A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = c.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = c.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = c.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1734,14 +2147,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = c.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) + let (peerID, _, _, error) = c.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) XCTAssertNil(error) XCTAssertNotNil(peerID) } let recoveryKey = SecRKCreateRecoveryKeyString(nil) XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") - let (setRecoveryError) = c.setRecoveryKeySync(test: self, recoveryKey: recoveryKey!, recoverySalt: "altDSID", ckksKeys: []) + let (_, setRecoveryError) = c.setRecoveryKeySync(test: self, recoveryKey: recoveryKey!, recoverySalt: "altDSID", ckksKeys: []) XCTAssertNil(setRecoveryError, "error should be nil") } @@ -1774,11 +2187,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(c.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing peer A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = c.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = c.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = c.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1790,15 +2203,15 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = c.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) + let (peerID, _, _, error) = c.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) XCTAssertNil(error) XCTAssertNotNil(peerID) } let (repairAccount, repairEscrow, resetOctagon, leaveTrust, healthError) = c.requestHealthCheckSync(requiresEscrowCheck: true, test: self) - XCTAssertEqual(repairAccount, false, "") - XCTAssertEqual(repairEscrow, false, "") - XCTAssertEqual(resetOctagon, false, "") - XCTAssertEqual(leaveTrust, false, "") + XCTAssertFalse(repairAccount, "") + XCTAssertFalse(repairEscrow, "") + XCTAssertFalse(resetOctagon, "") + XCTAssertFalse(leaveTrust, "") XCTAssertNil(healthError) } @@ -1814,11 +2227,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { var state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") bottleA = state.bottles.removeFirst() @@ -1833,14 +2246,14 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { assertNoTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) assertTLKShareFor(peerID: aPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) } do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) entropy = secret! XCTAssertNotNil(secret, "secret should not be nil") @@ -1850,11 +2263,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerB.updateSync(test: self) print("preparing B") - let (bPeerID, _, _, _, _, _, _, error2) = + let (bPeerID, _, _, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1864,10 +2277,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { print("B prepares to join via bottle") - let (bottlePeerID, views, policy, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) + let (bottlePeerID, policy, _, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleA.bottleID!) XCTAssertNil(errorPreflight, "Should be no error preflighting a vouch with bottle") XCTAssertEqual(bottlePeerID, aPeerID, "Bottle should be for peer A") - XCTAssertNotNil(views, "Should have a set of views to restore") XCTAssertNotNil(policy, "Should have a policy") let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: []) @@ -1882,9 +2294,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) - XCTAssertNotNil(error) - XCTAssertNil(peerID) + let (peerID, _, _, error) = containerB.joinSync(test: self, voucherData: voucherData!, voucherSig: voucherSig!, ckksKeys: [self.manateeKeySet], tlkShares: []) + XCTAssertNil(error, "Should be no error joining with a fetch error") + XCTAssertNotNil(peerID, "Should have a peer ID") } } @@ -1898,11 +2310,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertNil(containerB.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false)) print("preparing peer A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, aStableInfo, aStableInfoSig, _, _, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, aStableInfo, aStableInfoSig, _, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerA.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == aPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == aPeerID }, "should have a bottle for peer") let secret = containerA.loadSecretSync(test: self, label: aPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1916,17 +2328,17 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: nil) XCTAssertNil(error) XCTAssertNotNil(peerID) } print("preparing B") - let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, _, error2) = + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) - XCTAssertFalse( state.bottles.filter { $0.peerID == bPeerID } .isEmpty, "should have a bottle for peer") + XCTAssertTrue(state.bottles.contains { $0.peerID == bPeerID }, "should have a bottle for peer") let secret = containerB.loadSecretSync(test: self, label: bPeerID!) XCTAssertNotNil(secret, "secret should not be nil") XCTAssertNil(error, "error should be nil") @@ -1982,23 +2394,23 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, _, _, error) = containerB.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [], - tlkShares: []) + let (peerID, _, _, error) = containerB.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) XCTAssertNil(error) XCTAssertEqual(peerID, bPeerID!) } print("A updates") do { - let (_, error) = containerA.updateSync(test: self) + let (_, _, error) = containerA.updateSync(test: self) XCTAssertNil(error) } print("B updates") do { - let (_, error) = containerB.updateSync(test: self) + let (_, _, error) = containerB.updateSync(test: self) XCTAssertNil(error) } @@ -2009,17 +2421,17 @@ class TrustedPeersHelperUnitTests: XCTestCase { let recoveryKey = SecRKCreateRecoveryKeyString(nil) XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") - let (setRecoveryError) = containerB.setRecoveryKeySync(test: self, recoveryKey: recoveryKey!, recoverySalt: "altDSID", ckksKeys: []) + let (_, setRecoveryError) = containerB.setRecoveryKeySync(test: self, recoveryKey: recoveryKey!, recoverySalt: "altDSID", ckksKeys: []) XCTAssertNil(setRecoveryError, "error should be nil") print("A updates") do { - let (_, error) = containerA.updateSync(test: self) + let (_, _, error) = containerA.updateSync(test: self) XCTAssertNil(error) } print("B updates") do { - let (_, error) = containerB.updateSync(test: self) + let (_, _, error) = containerB.updateSync(test: self) XCTAssertNil(error) } @@ -2040,7 +2452,6 @@ class TrustedPeersHelperUnitTests: XCTestCase { let recoveryEncryptionPublicKey: Data? = stableInfo!["recovery_encryption_public_key"] as! Data? XCTAssertNil(recoveryEncryptionPublicKey, "recoveryEncryptionPublicKey should be nil") - } } @@ -2050,7 +2461,6 @@ class TrustedPeersHelperUnitTests: XCTestCase { unknownMachineIDs: Set = Set(), persistentStore: NSPersistentStoreDescription, cuttlefish: FakeCuttlefishServer) throws { - let midList = container.onqueueCurrentMIDList() XCTAssertEqual(midList.machineIDs(in: .allowed), allowedMachineIDs, "List of allowed machine IDs should match") XCTAssertEqual(midList.machineIDs(in: .disallowed), disallowedMachineIDs, "List of disallowed machine IDs should match") @@ -2073,7 +2483,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { let description = tmpStoreDescription(name: "container.db") let container = try Container(name: ContainerName(container: "test", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, _, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(peerID) @@ -2120,17 +2530,17 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // A update() before establish() doesn't change the list, since it isn't actually changing anything - let (_, updateError) = container.updateSync(test: self) + let (_, _, updateError) = container.updateSync(test: self) XCTAssertNil(updateError, "Should not be an error updating the container without first establishing") try self.assert(container: container, allowedMachineIDs: Set(["xxx", "mmm", "aaa"]), disallowedMachineIDs: Set(["zzz", "kkk", "bbb", "ccc", "fff"]), persistentStore: description, cuttlefish: self.cuttlefish) - let (_, _, establishError) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (_, _, _, establishError) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(establishError, "Should be able to establish() with no error") try self.assert(container: container, allowedMachineIDs: Set(["xxx", "mmm", "aaa"]), disallowedMachineIDs: Set(["zzz", "kkk", "bbb", "ccc", "fff"]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") // But a successful update() does remove all disallowed machine IDs, as they're no longer relevant - let (_, updateError2) = container.updateSync(test: self) + let (_, _, updateError2) = container.updateSync(test: self) XCTAssertNil(updateError2, "Should not be an error updating the container after establishing") try self.assert(container: container, allowedMachineIDs: Set(["xxx", "mmm", "aaa"]), disallowedMachineIDs: Set([]), persistentStore: description, cuttlefish: self.cuttlefish) XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") @@ -2225,7 +2635,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { // Now TPH boots up with a preexisting model let container = try Container(name: containerName, persistentStoreDescription: description, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, _, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(peerID) @@ -2346,6 +2756,109 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertFalse(container.onqueueFullIDMSListWouldBeHelpful(), "Container shouldn't think it could use an IDMS list set") } + func testDuplicateVouchersWhenRegisteringOnModel() throws { + let store = tmpStoreDescription(name: "container.db") + let (c, peerID1) = try establish(reload: false, store: store) + + let (c2, peerID2) = try joinByVoucher(sponsor: c, + containerID: "second", + machineID: "bbb", + machineIDs: ["aaa", "bbb"], accountIsDemo: false, + store: store) + + let (_, _, cUpdateError) = c.updateSync(test: self) + XCTAssertNil(cUpdateError, "Should be able to update first container") + assertTrusts(context: c, peerIDs: [peerID1, peerID2]) + + let (_, _, c2UpdateError) = c2.updateSync(test: self) + XCTAssertNil(c2UpdateError, "Should be able to update second container") + assertTrusts(context: c2, peerIDs: [peerID1, peerID2]) + + //attempt to register a bunch of vouchers it likely already has + for voucher in c2.model.allVouchers() { + c.model.register(voucher) + } + XCTAssertEqual(c.model.allVouchers().count, 1, "voucher count should be 1") + XCTAssertEqual(c2.model.allVouchers().count, 1, "voucher count should be 1") + } + + func testDuplicateVouchersOnload() throws { + let description = tmpStoreDescription(name: "container.db") + + let store = tmpStoreDescription(name: "container.db") + let (c, peerID1) = try establish(reload: false, store: store) + + let (c2, peerID2) = try joinByVoucher(sponsor: c, + containerID: "second", + machineID: "bbb", + machineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, + store: store) + + let (c3, peerID3) = try joinByVoucher(sponsor: c, + containerID: "third", + machineID: "ccc", + machineIDs: ["aaa", "bbb", "ccc"], accountIsDemo: false, + store: store) + + let (_, _, cUpdateError) = c.updateSync(test: self) + XCTAssertNil(cUpdateError, "Should be able to update first container") + + let (_, _, cUpdateError2) = c2.updateSync(test: self) + XCTAssertNil(cUpdateError2, "Should be able to update first container") + let (_, _, cUpdateError3) = c3.updateSync(test: self) + XCTAssertNil(cUpdateError3, "Should be able to update first container") + let (_, _, _) = c.updateSync(test: self) + + assertTrusts(context: c, peerIDs: [peerID1, peerID2, peerID3]) + + var vouchers: [VoucherMO] = Array() + + let c1Peers = c.containerMO.peers as! Set + for peer in c1Peers { + for voucher in peer.vouchers! { + let vouch = voucher as! VoucherMO + vouchers.append(vouch) + } + } + for peer in c1Peers { + for voucher in peer.vouchers! { + let vouch = voucher as! VoucherMO + vouchers.append(vouch) + } + } + + for peer in c1Peers { + for voucher in peer.vouchers! { + let vouch = voucher as! VoucherMO + vouchers.append(vouch) + } + } + + //reload container + XCTAssertEqual(vouchers.count, 6, "should have 6 vouchers") + + c.moc.performAndWait { + let containerMO = ContainerMO(context: c.moc) + do { + + for peer in containerMO.peers as! Set { + for vouch in vouchers { + peer.addToVouchers(vouch) + } + } + } + XCTAssertNoThrow(try! c.moc.save()) + } + + //reload container + do { + let container = try Container(name: c.name, persistentStoreDescription: description, cuttlefish: cuttlefish) + XCTAssertEqual(container.model.allVouchers().count, 2, "voucher count should be 2") + } catch { + XCTFail("Creating container errored: \(error)") + } + } + func testMachineIDListSetDisallowedOldUnknownMachineIDs() throws { let description = tmpStoreDescription(name: "container.db") var (container, peerID1) = try establish(reload: false, contextID: OTDefaultContext, allowedMachineIDs: Set(["aaa"]), accountIsDemo: false, store: description) @@ -2364,7 +2877,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { store: description) // And the first container accepts the join... - let (_, cUpdateError) = container.updateSync(test: self) + let (_, _, cUpdateError) = container.updateSync(test: self) XCTAssertNil(cUpdateError, "Should be able to update first container") assertTrusts(context: container, peerIDs: [peerID1, peerID3]) @@ -2393,7 +2906,6 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { container = try Container(name: ContainerName(container: "test", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) XCTAssertEqual(container.containerMO.honorIDMSListChanges, "YES", "honorIDMSListChanges should be YES") - } catch { XCTFail("Creating container errored: \(error)") } @@ -2431,7 +2943,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { store: description) // And the first container accepts the join... - let (_, cUpdateError) = container.updateSync(test: self) + let (_, _, cUpdateError) = container.updateSync(test: self) XCTAssertNil(cUpdateError, "Should be able to update first container") assertTrusts(context: container, peerIDs: [peerID1, peerID2]) @@ -2459,7 +2971,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { c2.containerMO.honorIDMSListChanges = "NO" // And the first container accepts the join... - let (_, cUpdateError) = container.updateSync(test: self) + let (_, _, cUpdateError) = container.updateSync(test: self) XCTAssertNil(cUpdateError, "Should be able to update first container") assertTrusts(context: container, peerIDs: [peerID1, peerID2]) @@ -2470,7 +2982,6 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { container = try Container(name: ContainerName(container: "test", context: OTDefaultContext), persistentStoreDescription: description, cuttlefish: cuttlefish) XCTAssertEqual(container.containerMO.honorIDMSListChanges, "NO", "honorIDMSListChanges should be NO") - } catch { XCTFail("Creating container errored: \(error)") } @@ -2484,11 +2995,10 @@ class TrustedPeersHelperUnitTests: XCTestCase { } func testContainerAndModelConsistency() throws { - let preTestContainerName = ContainerName(container: "testToCreatePrepareData", context: "context") let description = tmpStoreDescription(name: "container.db") let containerTest = try Container(name: preTestContainerName, persistentStoreDescription: description, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error) = containerTest.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error) = containerTest.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(peerID) XCTAssertNotNil(permanentInfo) @@ -2519,17 +3029,18 @@ class TrustedPeersHelperUnitTests: XCTestCase { let containerEgoStableInfo = TPPeerStableInfo(data: stableInfo!, sig: stableInfoSig!) do { let peerKeys: OctagonSelfPeerKeys = try loadEgoKeysSync(peerID: containerMO.egoPeerID!) - let info3 = TPPeerStableInfo(clock: containerEgoStableInfo!.clock + 2, - frozenPolicyVersion: containerEgoStableInfo!.frozenPolicyVersion, - flexiblePolicyVersion: containerEgoStableInfo!.flexiblePolicyVersion!, - policySecrets: containerEgoStableInfo!.policySecrets, - deviceName: containerEgoStableInfo!.deviceName, - serialNumber: containerEgoStableInfo!.serialNumber, - osVersion: containerEgoStableInfo!.osVersion, - signing: peerKeys.signingKey, - recoverySigningPubKey: containerEgoStableInfo!.recoverySigningPublicKey, - recoveryEncryptionPubKey: containerEgoStableInfo!.recoveryEncryptionPublicKey, - error: nil) + let newClock = containerEgoStableInfo!.clock + 2 + let info3 = try TPPeerStableInfo(clock: newClock, + frozenPolicyVersion: containerEgoStableInfo!.frozenPolicyVersion, + flexiblePolicyVersion: containerEgoStableInfo!.flexiblePolicyVersion!, + policySecrets: containerEgoStableInfo!.policySecrets, + syncUserControllableViews: containerEgoStableInfo!.syncUserControllableViews, + deviceName: containerEgoStableInfo!.deviceName, + serialNumber: containerEgoStableInfo!.serialNumber, + osVersion: containerEgoStableInfo!.osVersion, + signing: peerKeys.signingKey, + recoverySigningPubKey: containerEgoStableInfo!.recoverySigningPublicKey, + recoveryEncryptionPubKey: containerEgoStableInfo!.recoveryEncryptionPublicKey) //setting the containerMO's ego stable info to an old clock containerMO.egoPeerStableInfo = containerEgoStableInfo!.data @@ -2603,7 +3114,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { var container = try Container(name: ContainerName(container: "test", context: contextID), persistentStoreDescription: description, cuttlefish: cuttlefish) XCTAssertEqual(container.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") - let (peerID, permanentInfo, permanentInfoSig, _, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = container.getStateSync(test: self) XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") @@ -2624,7 +3135,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTFail("Creating container errored: \(error)") } - let (peerID2, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID2, _, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error2) XCTAssertNotNil(peerID2) @@ -2643,9 +3154,8 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertEqual(containerC.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aViewList, aPolicy, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") - XCTAssertNotNil(aViewList, "Should have a view list coming back from a successful prepare") XCTAssertNotNil(aPolicy, "Should have a policy coming back from a successful prepare") XCTAssertEqual(aPolicy?.version, prevailingPolicyVersion, "Policy coming back from prepare() should be prevailing policy version") @@ -2663,13 +3173,13 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error) XCTAssertNotNil(peerID) } print("preparing B") - let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, _, error2) = + let (bPeerID, bPermanentInfo, bPermanentInfoSig, bStableInfo, bStableInfoSig, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) @@ -2729,11 +3239,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins") - let (peerID, _, _, _, error) = containerB.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [], - tlkShares: []) + let (peerID, _, _, error) = containerB.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [], + tlkShares: []) XCTAssertNil(error) XCTAssertEqual(peerID, bPeerID!) } @@ -2743,7 +3253,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { _ = containerC.dumpSync(test: self) print("preparing C") - let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, _, _, error4) = + let (cPeerID, cPermanentInfo, cPermanentInfoSig, cStableInfo, cStableInfoSig, _, error4) = containerC.prepareSync(test: self, epoch: 1, machineID: "ccc", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerC.getStateSync(test: self) @@ -2781,11 +3291,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertTLKShareFor(peerID: cPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("C joins") - let (peerID, _, _, _, error2) = containerC.joinSync(test: self, - voucherData: voucherData!, - voucherSig: voucherSig!, - ckksKeys: [self.manateeKeySet, provisionalEngramKeySet], - tlkShares: []) + let (peerID, _, _, error2) = containerC.joinSync(test: self, + voucherData: voucherData!, + voucherSig: voucherSig!, + ckksKeys: [self.manateeKeySet, provisionalEngramKeySet], + tlkShares: []) XCTAssertNil(error2) XCTAssertEqual(peerID, cPeerID!) @@ -2796,7 +3306,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("A updates") do { - let (_, error) = containerA.updateSync(test: self) + let (_, _, error) = containerA.updateSync(test: self) XCTAssertNil(error) } @@ -2824,19 +3334,18 @@ class TrustedPeersHelperUnitTests: XCTestCase { XCTAssertEqual(containerB.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") print("preparing A") - let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aViewList, aPolicy, error) = + let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) = containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") XCTAssertNil(error) XCTAssertNotNil(aPeerID) XCTAssertNotNil(aPermanentInfo) XCTAssertNotNil(aPermanentInfoSig) - XCTAssertNotNil(aViewList, "Should have a view list coming back from a successful prepare") XCTAssertNotNil(aPolicy, "Should have a policy coming back from a successful prepare") XCTAssertEqual(aPolicy?.version, prevailingPolicyVersion, "Policy coming back from prepare() should be prevailing policy version") print("preparing B") - let (bPeerID, bPermanentInfo, bPermanentInfoSig, _, _, _, _, error2) = + let (bPeerID, bPermanentInfo, bPermanentInfoSig, _, _, _, error2) = containerB.prepareSync(test: self, epoch: 1, machineID: "bbb", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = containerB.getStateSync(test: self) @@ -2858,7 +3367,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { print("establishing A") do { - let (peerID, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: [bPermanentInfoParsed!.signingPubKey.spki()]) + let (peerID, _, _, error) = containerA.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: [bPermanentInfoParsed!.signingPubKey.spki()]) XCTAssertNil(error) XCTAssertNotNil(peerID) } @@ -2867,10 +3376,9 @@ class TrustedPeersHelperUnitTests: XCTestCase { assertNoTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) print("B joins by preapproval, and uploads all TLKShares that it has") - let (bJoinedPeerID, _, views, policy, bJoinedError) = containerB.preapprovedJoinSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: []) + let (bJoinedPeerID, _, policy, bJoinedError) = containerB.preapprovedJoinSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: []) XCTAssertNil(bJoinedError, "Should be no error joining by preapproval") XCTAssertNotNil(bJoinedPeerID, "Should have a peer ID out of join") - XCTAssertNotNil(views, "should have a list of views to use") XCTAssertNotNil(policy, "Should have a policy back from preapprovedjoin") assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee")) @@ -2888,7 +3396,7 @@ class TrustedPeersHelperUnitTests: XCTestCase { let contextID = "contextID" var container = try Container(name: ContainerName(container: "test", context: contextID), persistentStoreDescription: store, cuttlefish: cuttlefish) - let (peerID, permanentInfo, permanentInfoSig, _, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") + let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1") do { let state = container.getStateSync(test: self) XCTAssertFalse( state.bottles.filter { $0.peerID == peerID } .isEmpty, "should have a bottle for peer") @@ -2908,12 +3416,11 @@ class TrustedPeersHelperUnitTests: XCTestCase { do { container = try Container(name: ContainerName(container: "test", context: contextID), persistentStoreDescription: store, cuttlefish: cuttlefish) XCTAssertEqual(container.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown") - } catch { XCTFail("Creating container errored: \(error)") } - let (peerID2, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) + let (peerID2, _, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: []) XCTAssertNil(error2) XCTAssertNotNil(peerID2) diff --git a/keychain/analytics/SecEventMetric.m b/keychain/analytics/SecEventMetric.m index f40e458d..7f1493b1 100644 --- a/keychain/analytics/SecEventMetric.m +++ b/keychain/analytics/SecEventMetric.m @@ -54,8 +54,7 @@ } - (instancetype)initWithCoder:(NSCoder *)coder { - self = [super init]; - if (self) { + if ((self = [super init])) { NSMutableSet *attributeClasses = [[[self class] supportedAttributeClasses] mutableCopy]; [attributeClasses addObject:[NSDictionary class]]; diff --git a/keychain/analytics/SecMetrics.m b/keychain/analytics/SecMetrics.m index 5aa7ef4c..cabdc1c7 100644 --- a/keychain/analytics/SecMetrics.m +++ b/keychain/analytics/SecMetrics.m @@ -23,7 +23,7 @@ #import #import -#import +#import #import #import #import @@ -42,6 +42,8 @@ #import "keychain/analytics/C2Metric/SECC2MPDeviceInfo.h" #import +#import + @interface SecMetrics () diff --git a/keychain/behavior/SFBehavior.h b/keychain/behavior/SFBehavior.h deleted file mode 100644 index 69fc256a..00000000 --- a/keychain/behavior/SFBehavior.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2017 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@ - */ - -#if __OBJC2__ - -#import - -typedef NS_ENUM(uint32_t, SFBehaviorRamping) { - SFBehaviorRampingDisabled = 0, /* must not be enabled */ - SFBehaviorRampingEnabled = 1, /* unconditionally enabled */ - SFBehaviorRampingPromoted = 2, /* should be promoted by application */ - SFBehaviorRampingVisible = 3, /* allowed to enabled */ -}; - -@interface SFBehavior : NSObject - -+ (SFBehavior *)behaviorFamily:(NSString *)family; -- (instancetype)init NS_UNAVAILABLE; - -/* - * Ramping control controlled by CloudKit and configuration - * - * Return the current ramping state, can be called as often as clients want, state is cached - * and fetched in background (returning SFBehaviorRampingDisabled) until server changes the value. - * - * Ramping always go from Disable -> Visiable -> Promoted -> Enabled, can can skip over steps in-between. - * - * The feature can also go from { Visiable, Promoted, Enabled } -> Disabled if the feature is disabled - * - * Passing in force will for fetching the value from the server and bypass all caching, this will - * take its sweet time, so don't block UI on this operation, using force is not recommended. - */ -- (SFBehaviorRamping)ramping:(NSString *)feature force:(bool)force; - -/* - * This feature is assumed to be enabled unless disabled by configuration. - */ -- (bool)featureEnabled:(NSString *)feature; -/* - * This feature is assumed to be disabled unless enabled by configuration. - */ -- (bool)featureDisabled:(NSString *)feature; - -/* - * Fetch configuration values that might be changed from server configuration - */ -- (NSNumber *)configurationNumber:(NSString *)configuration defaultValue:(NSNumber *)defaultValue; -- (NSString *)configurationString:(NSString *)configuration defaultValue:(NSString *)defaultValue; - -@end - -#endif diff --git a/keychain/behavior/SFBehavior.m b/keychain/behavior/SFBehavior.m deleted file mode 100644 index cd46021f..00000000 --- a/keychain/behavior/SFBehavior.m +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2017 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@ - */ - -#import "SFBehavior.h" -#import - -#if __OBJC2__ - -@interface SFBehavior () -@property NSString *family; -@property NSXPCConnection *connection; -- (instancetype)initBehaviorFamily:(NSString *)family connection:(NSXPCConnection *)connection; -@end - -@protocol SFBehaviorProtocol -- (void)ramping:(NSString *)feature family:(NSString*)family complete:(void (^)(SFBehaviorRamping))complete; -- (void)feature:(NSString *)feature family:(NSString*)family defaultValue:(bool)defaultValue complete:(void (^)(bool))complete; - -- (void)configNumber:(NSString *)configuration family:(NSString*)family complete:(void (^)(NSNumber *))complete; -- (void)configString:(NSString *)configuration family:(NSString*)family complete:(void (^)(NSString *))complete; -@end - - -@implementation SFBehavior - -+ (SFBehavior *)behaviorFamily:(NSString *)family -{ - static dispatch_once_t onceToken = 0; - static NSMutableDictionary *behaviors; - static NSXPCConnection *connection = NULL; - dispatch_once(&onceToken, ^{ - behaviors = [NSMutableDictionary dictionary]; - connection = [[NSXPCConnection alloc] initWithMachServiceName:@"com.apple.security.behavior" options:NSXPCConnectionPrivileged]; - - connection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(SFBehaviorProtocol)]; - [connection resume]; - }); - - SFBehavior *behavior = nil; - @synchronized (behaviors) { - behavior = behaviors[family]; - if (behavior == NULL) { - behavior = [[SFBehavior alloc] initBehaviorFamily:family connection:connection]; - behaviors[family] = behavior; - } - } - - return behavior; -} - -- (instancetype)initBehaviorFamily:(NSString *)family connection:(NSXPCConnection *)connection -{ - self = [super init]; - if (self) { - _family = family; - _connection = connection; - } - return self; -} - -- (SFBehaviorRamping)ramping:(NSString *)feature force:(bool)force -{ - __block SFBehaviorRamping _ramping = SFBehaviorRampingDisabled; - [[_connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - }] ramping:feature family:_family complete:^(SFBehaviorRamping ramping) { - _ramping = ramping; - }]; - return _ramping; -} - -- (bool)feature:(NSString *)feature defaultValue:(bool)defaultValue -{ - __block bool enabled = defaultValue; - - [[_connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - }] feature:feature family:_family defaultValue:defaultValue complete:^(bool returnFeature) { - enabled = returnFeature; - }]; - return enabled; - -} - -- (bool)featureEnabled:(NSString *)feature -{ - return [self feature:feature defaultValue:true]; -} - -- (bool)featureDisabled:(NSString *)feature -{ - return ![self feature:feature defaultValue:false]; -} - -- (NSNumber *)configurationNumber:(NSString *)configuration defaultValue:(NSNumber *)defaultValue -{ - __block NSNumber *_number = defaultValue; - - [[_connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - }] configNumber:configuration family:_family complete:^(NSNumber *number) { - if (number) - _number = number; - }]; - return _number; -} - -- (NSString *)configurationString:(NSString *)configuration defaultValue:(NSString *)defaultValue -{ - __block NSString *_string = defaultValue; - - [[_connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - }] configString:configuration family:_family complete:^(NSString *string) { - if (string) - _string = string; - }]; - return _string; -} - -@end - -#endif /* __OBJC2__ */ - diff --git a/keychain/ckks/CKKS.h b/keychain/ckks/CKKS.h index 50070ebc..8cf27239 100644 --- a/keychain/ckks/CKKS.h +++ b/keychain/ckks/CKKS.h @@ -32,10 +32,10 @@ #ifdef __OBJC__ #import -NS_ASSUME_NONNULL_BEGIN -#else +#import "keychain/ot/OctagonStateMachine.h" +#endif /* __OBJC__ */ + CF_ASSUME_NONNULL_BEGIN -#endif #ifdef __OBJC__ @@ -62,6 +62,7 @@ extern CKKSItemState* const SecCKKSStateInFlight; extern CKKSItemState* const SecCKKSStateReencrypt; extern CKKSItemState* const SecCKKSStateError; extern CKKSItemState* const SecCKKSStateDeleted; // meta-state: please delete this item! +extern CKKSItemState* const SecCKKSStateMismatchedView; // This item was for a different view at processing time. Held pending a policy refresh. /* Processed States */ @protocol SecCKKSProcessedState @@ -157,9 +158,16 @@ extern NSString* const SecCKRecordManifestLeafDERKey; extern NSString* const SecCKRecordManifestLeafDigestKey; /* Zone Key Hierarchy States */ +#if OCTAGON +typedef OctagonState CKKSZoneKeyState; +#else +// This is here to allow for building with Octagon off @protocol SecCKKSZoneKeyState @end typedef NSString CKKSZoneKeyState; +#endif + +extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForCloudKitAccountStatus; // CKKS is currently logged out extern CKKSZoneKeyState* const SecCKKSZoneKeyStateLoggedOut; @@ -170,17 +178,28 @@ extern CKKSZoneKeyState* const SecCKKSZoneKeyStateInitializing; extern CKKSZoneKeyState* const SecCKKSZoneKeyStateInitialized; // CKKSZone has informed us that zone setup did not work. Try again soon! extern CKKSZoneKeyState* const SecCKKSZoneKeyStateZoneCreationFailed; + +// Everything is likely ready. Double-check. +extern CKKSZoneKeyState* const SecCKKSZoneKeyStateBecomeReady; // Everything is ready and waiting for input. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateReady; + // We're presumably ready, but we'd like to do one or two more checks after we unlock. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateReadyPendingUnlock; +// A key hierarchy fetch will now begin +extern CKKSZoneKeyState* const SecCKKSZoneKeyStateBeginFetch; + // We're currently refetching the zone extern CKKSZoneKeyState* const SecCKKSZoneKeyStateFetch; // A Fetch has just been completed which includes some new keys to process extern CKKSZoneKeyState* const SecCKKSZoneKeyStateFetchComplete; // We'd really like a full refetch. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateNeedFullRefetch; + +// The TLK doesn't appear to be present. Determine what to to next! +extern CKKSZoneKeyState* const SecCKKSZoneKeyStateTLKMissing; + // We've received a wrapped TLK, but we don't have its contents yet. Wait until they arrive. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLK; @@ -191,8 +210,11 @@ extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLKUpload; // We've received a wrapped TLK, but we can't process it until the keybag unlocks. Wait until then. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForUnlock; +// Some operation has noticed that trust is lost. Will enter WaitForTrust. +extern CKKSZoneKeyState* const SecCKKSZoneKeyStateLoseTrust; // We've done some CK ops, but are waiting for the trust system to tell us to continue extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTrust; + // Things are unhealthy, but we're not sure entirely why. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateUnhealthy; // Something has gone horribly wrong with the current key pointers. @@ -215,8 +237,6 @@ extern CKKSZoneKeyState* const SecCKKSZoneKeyStateResettingLocalData; // Fatal error. Will not proceed unless fixed from outside class. extern CKKSZoneKeyState* const SecCKKSZoneKeyStateError; -// This CKKS instance has been cancelled. -extern CKKSZoneKeyState* const SecCKKSZoneKeyStateCancelled; // If you absolutely need to numberify one of the above constants, here's your maps. NSDictionary* CKKSZoneKeyStateMap(void); @@ -226,7 +246,7 @@ CKKSZoneKeyState* CKKSZoneKeyRecover(NSNumber* stateNumber); // Use this to determine if CKKS believes the current state is "transient": that is, should resolve itself with further local processing // or 'nontransient': further local processing won't progress. Either we're ready, or waiting for the user to unlock, or a remote device to do something. -bool CKKSKeyStateTransient(CKKSZoneKeyState* state); +NSSet* CKKSKeyStateNonTransientStates(void); /* Hide Item Length */ extern const NSUInteger SecCKKSItemPaddingBlockSize; @@ -298,6 +318,9 @@ void SecCKKSTestSetDisableSOS(bool set); bool SecCKKSTestDisableKeyNotifications(void); void SecCKKSTestSetDisableKeyNotifications(bool set); +bool SecCKKSTestSkipScan(void); +bool SecCKKSSetTestSkipScan(bool value); + // TODO: handle errors better typedef CF_ENUM(CFIndex, CKKSErrorCode) { CKKSNotInitialized = 9, @@ -337,6 +360,11 @@ typedef CF_ENUM(CFIndex, CKKSErrorCode) { CKKSKeysMissing = 53, CKKSCircularKeyReference = 54, + + CKKSErrorViewIsPaused = 55, + CKKSErrorPolicyNotLoaded = 56, + + CKKSErrorUnexpectedNil = 57, }; typedef CF_ENUM(CFIndex, CKKSResultDescriptionErrorCode) { @@ -384,6 +412,8 @@ typedef CF_ENUM(CFIndex, CKKSServerExtensionErrorCode) { //CKKSServerInvalidCurrentItem = 17, }; +#if __OBJC__ + #define SecTranslateError(nserrorptr, cferror) \ if(nserrorptr) { \ *nserrorptr = (__bridge_transfer NSError*)cferror; \ @@ -391,62 +421,38 @@ typedef CF_ENUM(CFIndex, CKKSServerExtensionErrorCode) { CFReleaseNull(cferror); \ } +extern os_log_t CKKSLogObject(NSString* scope, NSString* _Nullable zoneName); + // Very similar to the secerror, secnotice, and secinfo macros in debugging.h, but add zoneNames -#define ckkserrorwithzonename(scope, zoneName, format, ...) \ - { \ - os_log(secLogObjForScope("SecError"), scope "-%@: " format, (zoneName ? zoneName : @"unknown"), ##__VA_ARGS__); \ - } -#define ckksnoticewithzonename(scope, zoneName, format, ...) \ - { \ - os_log(secLogObjForCFScope((__bridge CFStringRef)[@(scope "-") stringByAppendingString:(zoneName ? zoneName : @"unknown")]), \ - format, \ - ##__VA_ARGS__); \ - } -#define ckksinfowithzonename(scope, zoneName, format, ...) \ - { \ - os_log_debug(secLogObjForCFScope((__bridge CFStringRef)[@(scope "-") stringByAppendingString:(zoneName ? zoneName : @"unknown")]), \ - format, \ - ##__VA_ARGS__); \ - } +#define ckkserrorwithzonename(scope, zoneName, format, ...) \ +{ \ + os_log_with_type(CKKSLogObject(@scope, zoneName), \ + OS_LOG_TYPE_ERROR, \ + format, \ + ##__VA_ARGS__); \ +} -#define ckkserror(scope, zoneNameHaver, format, ...) \ - { \ - NSString* znh = zoneNameHaver.zoneName; \ - ckkserrorwithzonename(scope, znh, format, ##__VA_ARGS__) \ - } -#define ckksnotice(scope, zoneNameHaver, format, ...) \ - { \ - NSString* znh = zoneNameHaver.zoneName; \ - ckksnoticewithzonename(scope, znh, format, ##__VA_ARGS__) \ - } -#define ckksinfo(scope, zoneNameHaver, format, ...) \ - { \ - NSString* znh = zoneNameHaver.zoneName; \ - ckksinfowithzonename(scope, znh, format, ##__VA_ARGS__) \ - } +#define ckkserror(scope, zoneNameBearer, format, ...) \ + ckkserrorwithzonename(scope, zoneNameBearer.zoneName, format, ##__VA_ARGS__) -#undef ckksdebug -#if !defined(NDEBUG) -#define ckksdebugwithzonename(scope, zoneName, format, ...) \ - { \ - os_log_debug(secLogObjForCFScope((__bridge CFStringRef)[@(scope "-") stringByAppendingString:(zoneName ? zoneName : @"unknown")]), \ - format, \ - ##__VA_ARGS__); \ - } -#define ckksdebug(scope, zoneNameHaver, format, ...) \ - { \ - NSString* znh = zoneNameHaver.zoneName; \ - ckksdebugwithzonename(scope, znh, format, ##__VA_ARGS__) \ - } -#else -#define ckksdebug(scope, ...) /* nothing */ -#endif +#define ckkserror_global(scope, format, ...) \ + ckkserrorwithzonename(scope, nil, format, ##__VA_ARGS__) + +#define ckksnotice(scope, zoneNameBearer, format, ...) \ + os_log(CKKSLogObject(@scope, zoneNameBearer.zoneName), format, ##__VA_ARGS__) + +#define ckksnotice_global(scope, format, ...) \ + os_log(CKKSLogObject(@scope, nil), format, ##__VA_ARGS__) + +#define ckksinfo(scope, zoneNameBearer, format, ...) \ + os_log_debug(CKKSLogObject(@scope, zoneNameBearer.zoneName), format, ##__VA_ARGS__) + +#define ckksinfo_global(scope, format, ...) \ + os_log_debug(CKKSLogObject(@scope, nil), format, ##__VA_ARGS__) + +#endif // __OBJC__ -#ifdef __OBJC__ -NS_ASSUME_NONNULL_END -#else CF_ASSUME_NONNULL_END -#endif #endif /* CKKS_h */ diff --git a/keychain/ckks/CKKS.m b/keychain/ckks/CKKS.m index 3b35e838..31ce6d7a 100644 --- a/keychain/ckks/CKKS.m +++ b/keychain/ckks/CKKS.m @@ -27,7 +27,6 @@ #import #endif -#include #include "keychain/securityd/SecItemServer.h" #include @@ -38,6 +37,7 @@ #import "keychain/ckks/CKKSKey.h" #import "keychain/ot/OTManager.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" NSDictionary* CKKSZoneKeyStateMap(void) { static NSDictionary* map = nil; @@ -46,7 +46,7 @@ NSDictionary* CKKSZoneKeyStateMap(void) { map = @{ SecCKKSZoneKeyStateReady: @0U, SecCKKSZoneKeyStateError: @1U, - SecCKKSZoneKeyStateCancelled: @2U, + //SecCKKSZoneKeyStateCancelled: @2U, SecCKKSZoneKeyStateInitializing: @3U, SecCKKSZoneKeyStateInitialized: @4U, @@ -70,6 +70,11 @@ NSDictionary* CKKSZoneKeyStateMap(void) { SecCKKSZoneKeyStateWaitForTLKUpload: @22U, SecCKKSZoneKeyStateWaitForTLKCreation: @23U, SecCKKSZoneKeyStateProcess: @24U, + SecCKKSZoneKeyStateBecomeReady: @25U, + SecCKKSZoneKeyStateLoseTrust: @26U, + SecCKKSZoneKeyStateTLKMissing: @27U, + SecCKKSZoneKeyStateWaitForCloudKitAccountStatus:@28U, + SecCKKSZoneKeyStateBeginFetch: @29U, }; }); return map; @@ -106,18 +111,27 @@ CKKSZoneKeyState* CKKSZoneKeyRecover(NSNumber* stateNumber) { return SecCKKSZoneKeyStateError; } -bool CKKSKeyStateTransient(CKKSZoneKeyState* state) { - // Easier to compare against a blacklist of end states - bool nontransient = [state isEqualToString:SecCKKSZoneKeyStateReady] || - [state isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock] || - [state isEqualToString:SecCKKSZoneKeyStateWaitForTrust] || - [state isEqualToString:SecCKKSZoneKeyStateWaitForTLK] || - [state isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation] || - [state isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload] || - [state isEqualToString:SecCKKSZoneKeyStateWaitForUnlock] || - [state isEqualToString:SecCKKSZoneKeyStateError] || - [state isEqualToString:SecCKKSZoneKeyStateCancelled]; - return !nontransient; +NSSet* CKKSKeyStateNonTransientStates() +{ + static NSSet* states = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + states = [NSSet setWithArray:@[ + SecCKKSZoneKeyStateReady, + SecCKKSZoneKeyStateReadyPendingUnlock, + SecCKKSZoneKeyStateWaitForTrust, + SecCKKSZoneKeyStateWaitForTLK, + SecCKKSZoneKeyStateWaitForTLKCreation, + SecCKKSZoneKeyStateWaitForTLKUpload, + SecCKKSZoneKeyStateWaitForUnlock, + SecCKKSZoneKeyStateError, + SecCKKSZoneKeyStateLoggedOut, +#if OCTAGON + OctagonStateMachineHalted, +#endif + ]]; + }); + return states; } #if OCTAGON @@ -128,7 +142,7 @@ static bool testCKKS = false; bool SecCKKSIsEnabled(void) { if([CKDatabase class] == nil) { // CloudKit is not linked. We cannot bring CKKS up; disable it with prejudice. - secerror("CKKS: CloudKit.framework appears to not be linked. Cannot enable CKKS (on pain of crash)."); + ckkserror_global("ckks", "CloudKit.framework appears to not be linked. Cannot enable CKKS (on pain of crash)."); return false; } @@ -158,7 +172,7 @@ bool SecCKKSTestsEnabled(void) { bool SecCKKSTestsEnable(void) { if([CKDatabase class] == nil) { // CloudKit is not linked. We cannot bring CKKS up; disable it with prejudice. - secerror("CKKS: CloudKit.framework appears to not be linked. Cannot enable CKKS testing."); + ckkserror_global("ckks", "CloudKit.framework appears to not be linked. Cannot enable CKKS testing."); testCKKS = false; return false; } @@ -210,7 +224,7 @@ bool SecCKKSReduceRateLimiting(void) { [defaults registerDefaults: @{key: CKKSReduceRateLimiting ? @YES : @NO}]; CKKSReduceRateLimiting = !![defaults boolForKey:@"reduce-rate-limiting"]; - secnotice("ckks", "reduce-rate-limiting is %@", CKKSReduceRateLimiting ? @"on" : @"off"); + ckksnotice_global("ratelimit", "reduce-rate-limiting is %@", CKKSReduceRateLimiting ? @"on" : @"off"); }); return CKKSReduceRateLimiting; @@ -219,7 +233,7 @@ bool SecCKKSReduceRateLimiting(void) { bool SecCKKSSetReduceRateLimiting(bool value) { (void) SecCKKSReduceRateLimiting(); // Call this once to read the defaults write CKKSReduceRateLimiting = value; - secnotice("ckks", "reduce-rate-limiting is now %@", CKKSReduceRateLimiting ? @"on" : @"off"); + ckksnotice_global("ratelimit", "reduce-rate-limiting is now %@", CKKSReduceRateLimiting ? @"on" : @"off"); return CKKSReduceRateLimiting; } @@ -234,7 +248,7 @@ bool SecCKKSShareTLKs(void) { [defaults registerDefaults: @{@"tlksharing": CKKSShareTLKs ? @YES : @NO}]; CKKSShareTLKs = !![defaults boolForKey:@"tlksharing"]; - secnotice("ckksshare", "TLK sharing is %@", CKKSShareTLKs ? @"on" : @"off"); + ckksnotice_global("ckksshare", "TLK sharing is %@", CKKSShareTLKs ? @"on" : @"off"); }); return CKKSShareTLKs; @@ -278,16 +292,26 @@ void SecCKKSTestSetDisableKeyNotifications(bool set) { CKKSDisableKeyNotifications = set; } +static bool CKKSSkipScan = false; +bool SecCKKSTestSkipScan(void) { + return CKKSSkipScan; +} +bool SecCKKSSetTestSkipScan(bool value) { + CKKSSkipScan = value; + return CKKSSkipScan; +} + void SecCKKSTestResetFlags(void) { SecCKKSTestSetDisableAutomaticUUID(false); SecCKKSTestSetDisableSOS(false); SecCKKSTestSetDisableKeyNotifications(false); + SecCKKSSetTestSkipScan(false); } #else /* NO OCTAGON */ bool SecCKKSIsEnabled(void) { - secerror("CKKS was disabled at compile time."); + ckkserror_global("ckks", "CKKS was disabled at compile time."); return false; } @@ -323,7 +347,7 @@ void SecCKKSInitialize(SecDbRef db) { if(!SecCKKSTestsEnabled()) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - [OctagonAPSReceiver receiverForEnvironment:APSEnvironmentProduction namedDelegatePort:SecCKKSAPSNamedPort apsConnectionClass:[APSConnection class]]; + [[OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort apsConnectionClass:[APSConnection class]] registerForEnvironment:APSEnvironmentProduction]; }); } } @@ -338,7 +362,7 @@ void SecCKKSNotifyBlock(SecDbConnectionRef dbconn, SecDbTransactionPhase phase, // Ignore our own changes, otherwise we'd infinite-loop. if(source == kSecDbCKKSTransaction) { - secinfo("ckks", "Ignoring kSecDbCKKSTransaction notification"); + ckksinfo_global("ckks", "Ignoring kSecDbCKKSTransaction notification"); return; } @@ -349,7 +373,7 @@ void SecCKKSNotifyBlock(SecDbConnectionRef dbconn, SecDbTransactionPhase phase, SecDbEventTranslateComponents(r, (CFTypeRef*) &deleted, (CFTypeRef*) &added); if(!added && !deleted) { - secerror("CKKS: SecDbEvent gave us garbage: %@", r); + ckkserror_global("ckks", "SecDbEvent gave us garbage: %@", r); return; } @@ -380,12 +404,12 @@ void CKKSRegisterSyncStatusCallback(CFStringRef cfuuid, SecBoolCFErrorCallback c void SecCKKSPerformLocalResync() { #if OCTAGON if(SecCKKSIsEnabled()) { - secnotice("ckks", "Local keychain was reset; performing local resync"); + ckksnotice_global("reset", "Local keychain was reset; performing local resync"); [[CKKSViewManager manager] rpcResyncLocal:nil reply:^(NSError *result) { if(result) { - secnotice("ckks", "Local keychain reset resync finished with an error: %@", result); + ckksnotice_global("reset", "Local keychain reset resync finished with an error: %@", result); } else { - secnotice("ckks", "Local keychain reset resync finished successfully"); + ckksnotice_global("reset", "Local keychain reset resync finished successfully"); } }]; } diff --git a/keychain/ckks/CKKSAccountStateTracker.h b/keychain/ckks/CKKSAccountStateTracker.h index e83a8a24..ef217967 100644 --- a/keychain/ckks/CKKSAccountStateTracker.h +++ b/keychain/ckks/CKKSAccountStateTracker.h @@ -83,6 +83,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status); @end @protocol CKKSCloudKitAccountStateTrackingProvider - (dispatch_semaphore_t)registerForNotificationsOfCloudKitAccountStatusChange:(id)listener; +- (BOOL)notifyCKAccountStatusChangeAndWait:(dispatch_time_t)timeout; @end #pragma mark -- Tracker diff --git a/keychain/ckks/CKKSAccountStateTracker.m b/keychain/ckks/CKKSAccountStateTracker.m index 05900dc0..8db458f7 100644 --- a/keychain/ckks/CKKSAccountStateTracker.m +++ b/keychain/ckks/CKKSAccountStateTracker.m @@ -24,7 +24,6 @@ #if OCTAGON #include -#include #include #include #include "keychain/SecureObjectSync/SOSInternal.h" @@ -100,7 +99,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) _hsa2iCloudAccountInitialized = [[CKKSCondition alloc] init]; id notificationCenter = [self.nsnotificationCenterClass defaultCenter]; - secinfo("ckksaccount", "Registering with notification center %@", notificationCenter); + ckksinfo_global("ckksaccount", "Registering with notification center %@", notificationCenter); [notificationCenter addObserver:self selector:@selector(notifyCKAccountStatusChange:) name:CKAccountChangedNotification object:NULL]; WEAKIFY(self); @@ -178,15 +177,15 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) dispatch_queue_t objQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); [self.ckChangeListeners setObject:listener forKey: objQueue]; - secinfo("ckksaccount-ck", "adding a new listener: %@", listener); + ckksinfo_global("ckksaccount-ck", "adding a new listener: %@", listener); // If we know the current account status, let this listener know if(self.firstCKAccountFetch) { - secinfo("ckksaccount-ck", "notifying new listener %@ of current state %@", listener, self.currentCKAccountInfo); + ckksinfo_global("ckksaccount-ck", "notifying new listener %@ of current state %@", listener, self.currentCKAccountInfo); dispatch_group_t g = dispatch_group_create(); if(!g) { - secnotice("ckksaccount-ck", "Unable to get dispatch group."); + ckkserror_global("ckksaccount-ck", "Unable to get dispatch group."); dispatch_semaphore_signal(finishedSema); return; } @@ -217,14 +216,14 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) STRONGIFY(self); if(error) { - secerror("ckksaccount: error getting account info: %@", error); + ckkserror_global("ckksaccount", "error getting account info: %@", error); dispatch_semaphore_signal(finishedSema); return; } dispatch_sync(self.queue, ^{ self.firstCKAccountFetch = true; - secnotice("ckksaccount", "received CK Account info: %@", ckAccountInfo); + ckksnotice_global("ckksaccount", "received CK Account info: %@", ckAccountInfo); [self _onqueueUpdateAccountState:ckAccountInfo deliveredSemaphore:finishedSema]; }); }]; @@ -242,7 +241,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) [self.container fetchCurrentDeviceIDWithCompletionHandler:^(NSString* deviceID, NSError* ckerror) { STRONGIFY(self); if(!self) { - secerror("ckksaccount: Received fetchCurrentDeviceIDWithCompletionHandler callback with null AccountStateTracker"); + ckkserror_global("ckksaccount", "Received fetchCurrentDeviceIDWithCompletionHandler callback with null AccountStateTracker"); return; } @@ -250,14 +249,14 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) dispatch_async(self.queue, ^{ STRONGIFY(self); if(self.currentCKAccountInfo.accountStatus == CKAccountStatusAvailable) { - secnotice("ckksaccount", "CloudKit deviceID is: %@ %@", deviceID, ckerror); + ckksnotice_global("ckksaccount", "CloudKit deviceID is: %@ %@", deviceID, ckerror); self.ckdeviceID = deviceID; self.ckdeviceIDError = ckerror; [self.ckdeviceIDInitialized fulfill]; } else { // Logged out! No ckdeviceid. - secerror("ckksaccount: Logged back out but still received a fetchCurrentDeviceIDWithCompletionHandler callback"); + ckkserror_global("ckksaccount", "Logged back out but still received a fetchCurrentDeviceIDWithCompletionHandler callback"); self.ckdeviceID = nil; self.ckdeviceIDError = nil; @@ -279,7 +278,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) SOSAccountStatus* sosstatus = [CKKSAccountStateTracker getCircleStatus]; dispatch_sync(self.queue, ^{ if(self.currentCircleStatus == nil || ![self.currentCircleStatus isEqual:sosstatus]) { - secnotice("ckksaccount", "moving to circle status: %@", sosstatus); + ckksnotice_global("ckksaccount", "moving to circle status: %@", sosstatus); self.currentCircleStatus = sosstatus; if (sosstatus.status == kSOSCCInCircle) { @@ -315,7 +314,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) [CKKSAccountStateTracker fetchCirclePeerID:^(NSString* peerID, NSError* error) { STRONGIFY(self); if(!self) { - secerror("ckksaccount: Received fetchCirclePeerID callback with null AccountStateTracker"); + ckkserror_global("ckksaccount", "Received fetchCirclePeerID callback with null AccountStateTracker"); return; } @@ -323,13 +322,13 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) STRONGIFY(self); if(self.currentCircleStatus && self.currentCircleStatus.status == kSOSCCInCircle) { - secnotice("ckksaccount", "Circle peerID is: %@ %@", peerID, error); + ckksnotice_global("ckksaccount", "Circle peerID is: %@ %@", peerID, error); // Still in circle. Proceed. self.accountCirclePeerID = peerID; self.accountCirclePeerIDError = error; [self.accountCirclePeerIDInitialized fulfill]; } else { - secerror("ckksaccount: Out of circle but still received a fetchCirclePeerID callback"); + ckkserror_global("ckksaccount", "Out of circle but still received a fetchCirclePeerID callback"); // Not in-circle. Throw away circle id. self.accountCirclePeerID = nil; self.accountCirclePeerIDError = nil; @@ -339,7 +338,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) }]; } else { // Not in-circle, reset circle ID - secnotice("ckksaccount", "out of circle(%@): resetting peer ID", sosstatus); + ckksnotice_global("ckksaccount", "out of circle(%@): resetting peer ID", sosstatus); self.accountCirclePeerID = nil; self.accountCirclePeerIDError = nil; self.accountCirclePeerIDInitialized = [[CKKSCondition alloc] init]; @@ -356,7 +355,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) dispatch_group_t g = dispatch_group_create(); if(!g) { - secnotice("ckksaccount", "Unable to get dispatch group."); + ckksnotice_global("ckksaccount", "Unable to get dispatch group."); dispatch_semaphore_signal(finishedSema); return; } @@ -376,13 +375,13 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) if([self.currentCKAccountInfo isEqual: ckAccountInfo]) { // no-op. - secinfo("ckksaccount", "received another notification of CK Account State %@", ckAccountInfo); + ckksinfo_global("ckksaccount", "received another notification of CK Account State %@", ckAccountInfo); return; } if((self.currentCKAccountInfo == nil && ckAccountInfo != nil) || !(self.currentCKAccountInfo == ckAccountInfo || [self.currentCKAccountInfo isEqual: ckAccountInfo])) { - secnotice("ckksaccount", "moving to CK Account info: %@", ckAccountInfo); + ckksnotice_global("ckksaccount", "moving to CK Account info: %@", ckAccountInfo); CKAccountInfo* oldAccountInfo = self.currentCKAccountInfo; self.currentCKAccountInfo = ckAccountInfo; [self.ckAccountInfoInitialized fulfill]; @@ -424,8 +423,13 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) } } +- (BOOL)notifyCKAccountStatusChangeAndWait:(dispatch_time_t)timeout +{ + return dispatch_semaphore_wait([self notifyCKAccountStatusChange:nil], dispatch_time(DISPATCH_TIME_NOW, timeout)) == 0; +} + -(void)notifyCKAccountStatusChangeAndWaitForSignal { - dispatch_semaphore_wait([self notifyCKAccountStatusChange: nil], DISPATCH_TIME_FOREVER); + [self notifyCKAccountStatusChangeAndWait:DISPATCH_TIME_FOREVER]; } -(void)notifyCircleStatusChangeAndWaitForSignal { @@ -436,7 +440,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) dispatch_group_t g = dispatch_group_create(); if(!g) { - secnotice("ckksaccount", "Unable to get dispatch group."); + ckksnotice_global("ckksaccount", "Unable to get dispatch group."); return nil; } @@ -448,12 +452,12 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) while ((dq = [enumerator nextObject])) { id listener = [self.ckChangeListeners objectForKey: dq]; - secinfo("ckksaccountblock", "Starting blocking for listener %@", listener); + ckksinfo_global("ckksaccountblock", "Starting blocking for listener %@", listener); WEAKIFY(listener); dispatch_group_async(g, dq, ^{ STRONGIFY(listener); // Do nothing in particular. It's just important that this block runs. - secinfo("ckksaccountblock", "Done blocking for listener %@", listener); + ckksinfo_global("ckksaccountblock", "Done blocking for listener %@", listener); }); } }); @@ -467,7 +471,7 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) SOSCCStatus status = SOSCCThisDeviceIsInCircle(&cferror); if(cferror) { - secerror("ckksaccount: error getting circle status: %@", cferror); + ckkserror_global("ckksaccount", "error getting circle status: %@", cferror); return [[SOSAccountStatus alloc] init:kSOSCCError error:CFBridgingRelease(cferror)]; } @@ -503,10 +507,10 @@ NSString* CKKSAccountStatusToString(CKKSAccountStatus status) dispatch_sync(self.queue, ^{ if(error) { - secerror("ckksaccount: error getting octagon status: %@", error); + ckkserror_global("ckksaccount", "error getting octagon status: %@", error); self.octagonStatus = [[OTCliqueStatusWrapper alloc] initWithStatus:CliqueStatusError]; } else { - secnotice("ckksaccount", "Caching octagon status as (%@, %@)", OTCliqueStatusToString(status), peerID); + ckksnotice_global("ckksaccount", "Caching octagon status as (%@, %@)", OTCliqueStatusToString(status), peerID); self.octagonStatus = [[OTCliqueStatusWrapper alloc] initWithStatus:status]; } diff --git a/keychain/ckks/CKKSAnalytics.h b/keychain/ckks/CKKSAnalytics.h index b90f4252..357a032c 100644 --- a/keychain/ckks/CKKSAnalytics.h +++ b/keychain/ckks/CKKSAnalytics.h @@ -43,6 +43,7 @@ extern NSString* const OctagonAnalyticIcloudAccountState; extern NSString* const OctagonAnalyticCDPBitStatus; extern NSString* const OctagonAnalyticsTrustState; extern NSString* const OctagonAnalyticsAttemptedJoin; +extern NSString* const OctagonAnalyticsUserControllableViewsSyncing; extern NSString* const OctagonAnalyticsLastHealthCheck; extern NSString* const OctagonAnalyticsSOSStatus; extern NSString* const OctagonAnalyticsDateOfLastPreflightPreapprovedJoin; @@ -73,8 +74,6 @@ extern NSString* const OctagonAnalyticsBottledTotalTLKSharesRecovered; extern NSString* const OctagonAnalyticsBottledUniqueTLKsWithSharesCount; extern NSString* const OctagonAnalyticsBottledTLKUniqueViewCount; -@class CKKSKeychainView; - @protocol CKKSAnalyticsFailableEvent @end typedef NSString CKKSAnalyticsFailableEvent; @@ -211,17 +210,12 @@ extern CKKSAnalyticsActivity* const OctagonSOSAdapterUpdateKeys; + (instancetype)logger; -- (void)logSuccessForEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view; +- (void)logSuccessForEvent:(CKKSAnalyticsFailableEvent*)event zoneName:(NSString*)viewName; - (void)logRecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event - inView:(CKKSKeychainView*)view + zoneName:(NSString*)viewName withAttributes:(NSDictionary*)attributes; -- (void)logRecoverableError:(NSError*)error - forEvent:(CKKSAnalyticsFailableEvent*)event - zoneName:(NSString*)zoneName - withAttributes:(NSDictionary *)attributes; - - (void)logRecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event withAttributes:(NSDictionary *)attributes; @@ -232,21 +226,21 @@ extern CKKSAnalyticsActivity* const OctagonSOSAdapterUpdateKeys; - (void)logUnrecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event - inView:(CKKSKeychainView*)view + zoneName:(NSString*)viewName withAttributes:(NSDictionary*)attributes; - (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event; -- (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event inView:(CKKSKeychainView*)view; +- (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event zoneName:(NSString*)zoneName; -- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key inView:(CKKSKeychainView *)view; -- (NSDate *)datePropertyForKey:(NSString *)key inView:(CKKSKeychainView *)view; +- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key zoneName:(NSString*)zoneName; +- (NSDate *)datePropertyForKey:(NSString *)key zoneName:(NSString*)zoneName; @end @interface CKKSAnalytics (UnitTesting) - (NSDate*)dateOfLastSuccessForEvent:(CKKSAnalyticsFailableEvent*)event - inView:(CKKSKeychainView*)view; + zoneName:(NSString*)zoneName; - (NSDictionary *)errorChain:(NSError *)error depth:(NSUInteger)depth; - (NSDictionary *)createErrorAttributes:(NSError *)error diff --git a/keychain/ckks/CKKSAnalytics.m b/keychain/ckks/CKKSAnalytics.m index 6547366d..dcc6b61c 100644 --- a/keychain/ckks/CKKSAnalytics.m +++ b/keychain/ckks/CKKSAnalytics.m @@ -53,6 +53,7 @@ NSString* const OctagonAnalyticCDPBitStatus = @"OACDPStatus"; NSString* const OctagonAnalyticsTrustState = @"OATrust"; NSString* const OctagonAnalyticsAttemptedJoin = @"OAAttemptedJoin"; +NSString* const OctagonAnalyticsUserControllableViewsSyncing = @"OAUserViewsSyncing"; NSString* const OctagonAnalyticsLastHealthCheck = @"OAHealthCheck"; NSString* const OctagonAnalyticsSOSStatus = @"OASOSStatus"; NSString* const OctagonAnalyticsDateOfLastPreflightPreapprovedJoin = @"OALastPPJ"; @@ -221,10 +222,10 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti return [super logger]; } -- (void)logSuccessForEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view +- (void)logSuccessForEvent:(CKKSAnalyticsFailableEvent*)event zoneName:(NSString*)zoneName { - [self logSuccessForEventNamed:[NSString stringWithFormat:@"%@-%@", view.zoneName, event]]; - [self setDateProperty:[NSDate date] forKey:[NSString stringWithFormat:@"last_success_%@-%@", view.zoneName, event]]; + [self logSuccessForEventNamed:[NSString stringWithFormat:@"%@-%@", zoneName, event]]; + [self setDateProperty:[NSDate date] forKey:[NSString stringWithFormat:@"last_success_%@-%@", zoneName, event]]; } - (bool)isCKPartialError:(NSError *)error @@ -297,7 +298,10 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti return eventAttributes; } -- (void)logRecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event zoneName:(NSString*)zoneName withAttributes:(NSDictionary *)attributes +- (void)logRecoverableError:(NSError*)error + forEvent:(CKKSAnalyticsFailableEvent*)event + zoneName:(NSString*)zoneName + withAttributes:(NSDictionary *)attributes { if (error == nil){ return; @@ -346,32 +350,10 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti [super logSoftFailureForEventNamed:event withAttributes:eventAttributes]; } -- (void)logRecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view withAttributes:(NSDictionary *)attributes -{ - if (error == nil){ - return; - } - NSMutableDictionary* eventAttributes = [NSMutableDictionary dictionary]; - - /* Don't allow caller to overwrite our attributes, lets merge them first */ - if (attributes) { - [eventAttributes setValuesForKeysWithDictionary:attributes]; - } - - [eventAttributes setValuesForKeysWithDictionary:@{ - CKKSAnalyticsAttributeRecoverableError : @(YES), - CKKSAnalyticsAttributeZoneName : view.zoneName, - CKKSAnalyticsAttributeErrorDomain : error.domain, - CKKSAnalyticsAttributeErrorCode : @(error.code) - }]; - - eventAttributes[CKKSAnalyticsAttributeErrorChain] = [self errorChain:error.userInfo[NSUnderlyingErrorKey] depth:0]; - [self addCKPartialError:eventAttributes error:error depth:0]; - - [super logSoftFailureForEventNamed:event withAttributes:eventAttributes]; -} - -- (void)logUnrecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view withAttributes:(NSDictionary *)attributes +- (void)logUnrecoverableError:(NSError*)error + forEvent:(CKKSAnalyticsFailableEvent*)event + zoneName:(NSString*)zoneName + withAttributes:(NSDictionary *)attributes { if (error == nil){ return; @@ -386,7 +368,7 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti [eventAttributes setValuesForKeysWithDictionary:@{ CKKSAnalyticsAttributeRecoverableError : @(NO), - CKKSAnalyticsAttributeZoneName : view.zoneName, + CKKSAnalyticsAttributeZoneName : zoneName, CKKSAnalyticsAttributeErrorDomain : error.domain, CKKSAnalyticsAttributeErrorCode : @(error.code) }]; @@ -394,7 +376,9 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti [self logHardFailureForEventNamed:event withAttributes:eventAttributes]; } -- (void)logUnrecoverableError:(NSError*)error forEvent:(CKKSAnalyticsFailableEvent*)event withAttributes:(NSDictionary *)attributes +- (void)logUnrecoverableError:(NSError*)error + forEvent:(CKKSAnalyticsFailableEvent*)event + withAttributes:(NSDictionary *)attributes { if (error == nil){ return; @@ -423,23 +407,23 @@ CKKSAnalyticsActivity* const OctagonActivityRemoveFriendsInClique = (CKKSAnalyti { [self noteEventNamed:event]; } -- (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event inView:(CKKSKeychainView*)view +- (void)noteEvent:(CKKSAnalyticsSignpostEvent*)event zoneName:(NSString*)zoneName { - [self noteEventNamed:[NSString stringWithFormat:@"%@-%@", view.zoneName, event]]; + [self noteEventNamed:[NSString stringWithFormat:@"%@-%@", zoneName, event]]; } -- (NSDate*)dateOfLastSuccessForEvent:(CKKSAnalyticsFailableEvent*)event inView:(CKKSKeychainView*)view +- (NSDate*)dateOfLastSuccessForEvent:(CKKSAnalyticsFailableEvent*)event zoneName:(NSString*)zoneName { - return [self datePropertyForKey:[NSString stringWithFormat:@"last_success_%@-%@", view.zoneName, event]]; + return [self datePropertyForKey:[NSString stringWithFormat:@"last_success_%@-%@", zoneName, event]]; } -- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key inView:(CKKSKeychainView *)view +- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key zoneName:(NSString*)zoneName { - [self setDateProperty:date forKey:[NSString stringWithFormat:@"%@-%@", key, view.zoneName]]; + [self setDateProperty:date forKey:[NSString stringWithFormat:@"%@-%@", key, zoneName]]; } -- (NSDate *)datePropertyForKey:(NSString *)key inView:(CKKSKeychainView *)view +- (NSDate *)datePropertyForKey:(NSString *)key zoneName:(NSString*)zoneName { - return [self datePropertyForKey:[NSString stringWithFormat:@"%@-%@", key, view.zoneName]]; + return [self datePropertyForKey:[NSString stringWithFormat:@"%@-%@", key, zoneName]]; } @end diff --git a/keychain/ckks/CKKSCheckKeyHierarchyOperation.h b/keychain/ckks/CKKSCheckKeyHierarchyOperation.h new file mode 100644 index 00000000..0ed27699 --- /dev/null +++ b/keychain/ckks/CKKSCheckKeyHierarchyOperation.h @@ -0,0 +1,23 @@ + +#import + +#if OCTAGON + +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CKKSCheckKeyHierarchyOperation : CKKSResultOperation +@property CKKSOperationDependencies* deps; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSCheckKeyHierarchyOperation.m b/keychain/ckks/CKKSCheckKeyHierarchyOperation.m new file mode 100644 index 00000000..874969c0 --- /dev/null +++ b/keychain/ckks/CKKSCheckKeyHierarchyOperation.m @@ -0,0 +1,198 @@ + +#if OCTAGON + +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKSCheckKeyHierarchyOperation.h" +#import "keychain/ckks/CKKSMirrorEntry.h" +#import "keychain/ot/OTDefines.h" +#import "utilities/SecTrace.h" + +@implementation CKKSCheckKeyHierarchyOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if(self = [super init]) { + _deps = dependencies; + + _intendedState = intendedState; + _nextState = errorState; + } + return self; +} + +- (void)main { + NSArray* currentTrustStates = [self.deps currentTrustStates]; + + __block CKKSCurrentKeySet* set = nil; + + [self.deps.databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{ + set = [CKKSCurrentKeySet loadForZone:self.deps.zoneID]; + }]; + + // Drop off the sql queue: we can do the rest of this function with what we've already loaded + + if(set.error && !([set.error.domain isEqual: @"securityd"] && set.error.code == errSecItemNotFound)) { + ckkserror("ckkskey", self.deps.zoneID, "Error examining existing key hierarchy: %@", set.error); + } + + if(!set.currentTLKPointer && !set.currentClassAPointer && !set.currentClassCPointer) { + ckkserror("ckkskey", self.deps.zoneID, "Error examining existing key hierarchy (missing all CKPs, likely no hierarchy exists): %@", set); + self.nextState = SecCKKSZoneKeyStateWaitForTLKCreation; + return; + } + + // Check keyset + if(!set.tlk || !set.classA || !set.classC) { + ckkserror("ckkskey", self.deps.zoneID, "Error examining existing key hierarchy (missing at least one key): %@", set); + self.error = set.error; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } + + NSError* localerror = nil; + bool probablyOkIfUnlocked = false; + + // keychain being locked is not a fatal error here + [set.tlk loadKeyMaterialFromKeychain:&localerror]; + if(localerror && ![self.deps.lockStateTracker isLockedError:localerror]) { + ckkserror("ckkskey", self.deps.zoneID, "Error loading TLK(%@): %@", set.tlk, localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } else if(localerror) { + ckkserror("ckkskey", self.deps.zoneID, "Soft error loading TLK(%@), maybe locked: %@", set.tlk, localerror); + probablyOkIfUnlocked = true; + } + localerror = nil; + + // keychain being locked is not a fatal error here + [set.classA loadKeyMaterialFromKeychain:&localerror]; + if(localerror && ![self.deps.lockStateTracker isLockedError:localerror]) { + ckkserror("ckkskey", self.deps.zoneID, "Error loading classA key(%@): %@", set.classA, localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } else if(localerror) { + ckkserror("ckkskey", self.deps.zoneID, "Soft error loading classA key(%@), maybe locked: %@", set.classA, localerror); + probablyOkIfUnlocked = true; + } + localerror = nil; + + // keychain being locked is a fatal error here, since this is class C + [set.classC loadKeyMaterialFromKeychain:&localerror]; + if(localerror) { + ckkserror("ckkskey", self.deps.zoneID, "Error loading classC(%@): %@", set.classC, localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } + + // Check that the classA and classC keys point to the current TLK + if(![set.classA.parentKeyUUID isEqualToString: set.tlk.uuid]) { + localerror = [NSError errorWithDomain:CKKSServerExtensionErrorDomain + code:CKKSServerUnexpectedSyncKeyInChain + userInfo:@{ + NSLocalizedDescriptionKey: @"Current class A key does not wrap to current TLK", + }]; + ckkserror("ckkskey", self.deps.zoneID, "Key hierarchy unhealthy: %@", localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } + if(![set.classC.parentKeyUUID isEqualToString: set.tlk.uuid]) { + localerror = [NSError errorWithDomain:CKKSServerExtensionErrorDomain + code:CKKSServerUnexpectedSyncKeyInChain + userInfo:@{ + NSLocalizedDescriptionKey: @"Current class C key does not wrap to current TLK", + }]; + ckkserror("ckkskey", self.deps.zoneID, "Key hierarchy unhealthy: %@", localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } + + // Now that we're pretty sure we have the keys, are they shared appropriately? + // We need trust in order to proceed here + if(currentTrustStates.count == 0u) { + ckkserror("ckkskey", self.deps.zoneID, "Can't check TLKShares due to missing trust states"); + [self.deps provideKeySet:set]; + self.nextState = SecCKKSZoneKeyStateLoseTrust; + return; + } + + // If we've reached this point, we have a workable keyset. Let's provide it to all waiters. + [self.deps provideKeySet:set]; + + if(probablyOkIfUnlocked) { + ckkserror("ckkskey", self.deps.zoneID, "Can't check TLKShares due to lock state"); + [self.deps provideKeySet:set]; + self.nextState = SecCKKSZoneKeyStateReadyPendingUnlock; + return; + } + + // Check that every trusted peer has at least one TLK share + // If any trust state check works, don't error out + bool anyTrustStateSucceeded = false; + for(CKKSPeerProviderState* trustState in currentTrustStates) { + NSSet>* missingShares = [trustState findPeersMissingTLKSharesFor:set + error:&localerror]; + + if(localerror && [self.deps.lockStateTracker isLockedError:localerror]) { + ckkserror("ckkskey", self.deps.zoneID, "Couldn't find missing TLK shares due to lock state: %@", localerror); + continue; + + } else if(([localerror.domain isEqualToString:TrustedPeersHelperErrorDomain] && localerror.code == TrustedPeersHelperErrorNoPreparedIdentity) || + ([localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSLackingTrust) || + ([localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSNoPeersAvailable)) { + ckkserror("ckkskey", self.deps.zoneID, "Couldn't find missing TLK shares due some trust issue: %@", localerror); + + if(trustState.essential) { + ckkserror("ckkskey", self.deps.zoneID, "Trust state is considered essential; entering waitfortrust: %@", trustState); + + // Octagon can reinform us when it thinks we should start again + self.nextState = SecCKKSZoneKeyStateLoseTrust; + + return; + } else { + ckkserror("ckkskey", self.deps.zoneID, "Peer provider is considered nonessential; ignoring error: %@", trustState); + continue; + } + + } else if(localerror) { + ckkserror("ckkskey", self.deps.zoneID, "Error finding missing TLK shares: %@", localerror); + continue; + } + + if(!missingShares || missingShares.count != 0u) { + ckksnotice("ckksshare", self.deps.zoneID, "TLK (%@) is not shared correctly for trust state %@, but we believe AKS is locked", set.tlk, trustState.peerProviderID); + + self.error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSMissingTLKShare + description:[NSString stringWithFormat:@"Missing shares for %lu peers", (unsigned long)missingShares.count]]; + self.nextState = SecCKKSZoneKeyStateHealTLKShares; + return; + } else { + ckksnotice("ckksshare", self.deps.zoneID, "TLK (%@) is shared correctly for trust state %@", set.tlk, trustState.peerProviderID); + } + + anyTrustStateSucceeded |= true; + } + + if(!anyTrustStateSucceeded) { + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateError; + + return; + } + + // Got to the bottom? Cool! All keys are present and accounted for. + self.nextState = SecCKKSZoneKeyStateReady; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSConstants.m b/keychain/ckks/CKKSConstants.m index f680d81b..60c3ce96 100644 --- a/keychain/ckks/CKKSConstants.m +++ b/keychain/ckks/CKKSConstants.m @@ -16,6 +16,7 @@ CKKSItemState* const SecCKKSStateInFlight = (CKKSItemState*) @"inflight"; CKKSItemState* const SecCKKSStateReencrypt = (CKKSItemState*) @"reencrypt"; CKKSItemState* const SecCKKSStateError = (CKKSItemState*) @"error"; CKKSItemState* const SecCKKSStateDeleted = (CKKSItemState*) @"deleted"; +CKKSItemState* const SecCKKSStateMismatchedView = (CKKSItemState*) @"mismatched_view"; CKKSProcessedState* const SecCKKSProcessedStateLocal = (CKKSProcessedState*) @"local"; CKKSProcessedState* const SecCKKSProcessedStateRemote = (CKKSProcessedState*) @"remote"; @@ -87,21 +88,27 @@ NSString* const SecCKRecordManifestLeafType = @"manifest_leaf"; NSString* const SecCKRecordManifestLeafDERKey = @"der"; NSString* const SecCKRecordManifestLeafDigestKey = @"digest"; +CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForCloudKitAccountStatus = (CKKSZoneKeyState*)@"wait_for_ck_account_status"; + CKKSZoneKeyState* const SecCKKSZoneKeyStateReady = (CKKSZoneKeyState*) @"ready"; +CKKSZoneKeyState* const SecCKKSZoneKeyStateBecomeReady = (CKKSZoneKeyState*) @"become_ready"; CKKSZoneKeyState* const SecCKKSZoneKeyStateReadyPendingUnlock = (CKKSZoneKeyState*) @"readypendingunlock"; CKKSZoneKeyState* const SecCKKSZoneKeyStateError = (CKKSZoneKeyState*) @"error"; -CKKSZoneKeyState* const SecCKKSZoneKeyStateCancelled = (CKKSZoneKeyState*) @"cancelled"; CKKSZoneKeyState* const SecCKKSZoneKeyStateInitializing = (CKKSZoneKeyState*) @"initializing"; CKKSZoneKeyState* const SecCKKSZoneKeyStateInitialized = (CKKSZoneKeyState*) @"initialized"; +CKKSZoneKeyState* const SecCKKSZoneKeyStateBeginFetch = (CKKSZoneKeyState*) @"begin_fetch"; CKKSZoneKeyState* const SecCKKSZoneKeyStateFetch = (CKKSZoneKeyState*) @"fetching"; CKKSZoneKeyState* const SecCKKSZoneKeyStateFetchComplete = (CKKSZoneKeyState*) @"fetchcomplete"; CKKSZoneKeyState* const SecCKKSZoneKeyStateNeedFullRefetch = (CKKSZoneKeyState*) @"needrefetch"; + +CKKSZoneKeyState* const SecCKKSZoneKeyStateTLKMissing = (CKKSZoneKeyState*) @"tlkmissing"; CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLK = (CKKSZoneKeyState*) @"waitfortlk"; CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLKCreation = (CKKSZoneKeyState*) @"waitfortlkcreation"; CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTLKUpload = (CKKSZoneKeyState*) @"waitfortlkupload"; CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForUnlock = (CKKSZoneKeyState*) @"waitforunlock"; +CKKSZoneKeyState* const SecCKKSZoneKeyStateLoseTrust = (CKKSZoneKeyState*) @"lose_trust"; CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForTrust = (CKKSZoneKeyState*) @"waitfortrust"; CKKSZoneKeyState* const SecCKKSZoneKeyStateUnhealthy = (CKKSZoneKeyState*) @"unhealthy"; CKKSZoneKeyState* const SecCKKSZoneKeyStateBadCurrentPointers = (CKKSZoneKeyState*) @"badcurrentpointers"; @@ -113,7 +120,7 @@ CKKSZoneKeyState* const SecCKKSZoneKeyStateResettingZone = (CKKSZoneKeyState*) @ CKKSZoneKeyState* const SecCKKSZoneKeyStateResettingLocalData = (CKKSZoneKeyState*) @"resetlocal"; CKKSZoneKeyState* const SecCKKSZoneKeyStateLoggedOut = (CKKSZoneKeyState*) @"loggedout"; CKKSZoneKeyState* const SecCKKSZoneKeyStateZoneCreationFailed = (CKKSZoneKeyState*) @"zonecreationfailed"; -CKKSZoneKeyState* const SecCKKSZoneKeyStateProcess = (CKKSZoneKeyState*) @"process"; +CKKSZoneKeyState* const SecCKKSZoneKeyStateProcess = (CKKSZoneKeyState*) @"process_key_hierarchy"; NSString* const CKKSErrorDomain = @"CKKSErrorDomain"; NSString* const CKKSServerExtensionErrorDomain = @"CKKSServerExtensionErrorDomain"; diff --git a/keychain/ckks/CKKSControl.h b/keychain/ckks/CKKSControl.h index 7a071d0a..92ddf330 100644 --- a/keychain/ckks/CKKSControl.h +++ b/keychain/ckks/CKKSControl.h @@ -34,6 +34,7 @@ typedef NS_ENUM(NSUInteger, CKKSKnownBadState) { CKKSKnownStateTLKsMissing = 1, // CKKS doesn't have the TLKs: your operation will likely not succeed CKKSKnownStateWaitForUnlock = 2, // CKKS has some important things to do, but the device is locked. Your operation will likely not succeed CKKSKnownStateWaitForOctagon = 3, // CKKS has important things to do, but Octagon hasn't done them yet. Your operation will likely not succeed + CKKSKnownStateNoCloudKitAccount = 4, // The device isn't signed into CloudKit. Your operation will likely not succeed }; @interface CKKSControl : NSObject @@ -49,6 +50,7 @@ typedef NS_ENUM(NSUInteger, CKKSKnownBadState) { reply:(void (^)(NSArray* _Nullable result, NSError* _Nullable error))reply; - (void)rpcResetLocal:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply; - (void)rpcResetCloudKit:(NSString* _Nullable)viewName reason:(NSString *)reason reply:(void (^)(NSError* _Nullable error))reply; +- (void)rpcResyncLocal:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply; - (void)rpcResync:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply; - (void)rpcFetchAndProcessChanges:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply; - (void)rpcFetchAndProcessClassAChanges:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply; diff --git a/keychain/ckks/CKKSControl.m b/keychain/ckks/CKKSControl.m index f4d75de7..fc09adc7 100644 --- a/keychain/ckks/CKKSControl.m +++ b/keychain/ckks/CKKSControl.m @@ -31,8 +31,7 @@ #import "keychain/ckks/CKKSControl.h" #import "keychain/ckks/CKKSControlProtocol.h" #import "keychain/ckks/CKKSControlServer.h" - -#include +#import "utilities/debugging.h" @interface CKKSControl () @property (readwrite,assign) BOOL synchronous; @@ -49,6 +48,10 @@ return self; } +- (void)dealloc { + [self.connection invalidate]; +} + - (id)objectProxyWithErrorHandler:(void(^)(NSError * _Nonnull error))failureHandler { if (self.synchronous) { @@ -78,6 +81,7 @@ - (void)rpcResetLocal:(NSString*)viewName reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a local reset for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcResetLocal:viewName reply:^(NSError* error){ @@ -86,6 +90,7 @@ } - (void)rpcResetCloudKit:(NSString*)viewName reason:(NSString *)reason reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a CloudKit reset for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcResetCloudKit:viewName reason:reason reply:^(NSError* error){ @@ -93,8 +98,17 @@ }]; } - +- (void)rpcResyncLocal:(NSString* _Nullable)viewName reply:(void (^)(NSError* _Nullable error))reply +{ + secnotice("ckkscontrol", "Requesting a local resync for view %@", viewName); + [[self objectProxyWithErrorHandler:^(NSError* error) { + reply(error); + }] rpcResyncLocal:viewName reply:^(NSError* error){ + reply(error); + }]; +} - (void)rpcResync:(NSString*)viewName reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a resync for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcResync:viewName reply:^(NSError* error){ @@ -102,6 +116,7 @@ }]; } - (void)rpcFetchAndProcessChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a fetch for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcFetchAndProcessChanges:viewName reply:^(NSError* error){ @@ -109,6 +124,7 @@ }]; } - (void)rpcFetchAndProcessClassAChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a fetch(classA) for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcFetchAndProcessClassAChanges:viewName reply:^(NSError* error){ @@ -116,6 +132,7 @@ }]; } - (void)rpcPushOutgoingChanges:(NSString*)viewName reply:(void(^)(NSError* error))reply { + secnotice("ckkscontrol", "Requesting a push for view %@", viewName); [[self objectProxyWithErrorHandler:^(NSError* error) { reply(error); }] rpcPushOutgoingChanges:viewName reply:^(NSError* error){ @@ -174,6 +191,7 @@ bool tlkMissing = false; bool waitForUnlock = false; bool waitForOctagon = false; + bool noAccount = false; CKKSKnownBadState response = CKKSKnownStatePossiblyGood; @@ -194,15 +212,21 @@ } if([keystate isEqualToString:@"waitfortlkcreation"] || - [keystate isEqualToString:@"waitfortlkupload"]) { + [keystate isEqualToString:@"waitfortlkupload"] || + [keystate isEqualToString:@"waitfortrust"]) { waitForOctagon = true; } + + if([keystate isEqualToString:@"loggedout"]) { + noAccount = true; + } } - response = (tlkMissing ? CKKSKnownStateTLKsMissing : - (waitForUnlock ? CKKSKnownStateWaitForUnlock : - (waitForOctagon ? CKKSKnownStateWaitForOctagon : - CKKSKnownStatePossiblyGood))); + response = (noAccount ? CKKSKnownStateNoCloudKitAccount : + (tlkMissing ? CKKSKnownStateTLKsMissing : + (waitForUnlock ? CKKSKnownStateWaitForUnlock : + (waitForOctagon ? CKKSKnownStateWaitForOctagon : + CKKSKnownStatePossiblyGood)))); reply(response); }]; diff --git a/keychain/ckks/CKKSControlProtocol.h b/keychain/ckks/CKKSControlProtocol.h index d96fae7b..1775d890 100644 --- a/keychain/ckks/CKKSControlProtocol.h +++ b/keychain/ckks/CKKSControlProtocol.h @@ -25,7 +25,7 @@ @protocol CKKSControlProtocol - (void)performanceCounters:(void(^)(NSDictionary *))reply; -- (void)rpcResetLocal: (NSString*)viewName reply: (void(^)(NSError* result)) reply; +- (void)rpcResetLocal: (NSString*)viewName reply: (void(^)(NSError* result)) reply; /** * Reset CloudKit zone with a caller provided reason, the reason will be logged in the operation group diff --git a/keychain/ckks/CKKSControlProtocol.m b/keychain/ckks/CKKSControlProtocol.m index 648b8253..4109183b 100644 --- a/keychain/ckks/CKKSControlProtocol.m +++ b/keychain/ckks/CKKSControlProtocol.m @@ -28,8 +28,10 @@ #if OCTAGON #import #import -#import +#import +#import "utilities/debugging.h" #include +#import // Weak-link CloudKit, until we can get ckksctl out of base system static void *cloudKit = NULL; @@ -67,48 +69,26 @@ NSXPCInterface* CKKSSetupControlProtocol(NSXPCInterface* interface) { __typeof(CKAcceptableValueClasses) *soft_CKAcceptableValueClasses = NULL; getCloudKitSymbol((void **)&soft_CKAcceptableValueClasses, "CKAcceptableValueClasses"); errClasses = [NSMutableSet setWithSet:soft_CKAcceptableValueClasses()]; - - char *classes[] = { - "CKPrettyError", - "CKRecordID", - "NSArray", - "NSData", - "NSDate", - "NSDictionary", - "NSError", - "NSNull", - "NSNumber", - "NSOrderedSet", - "NSSet", - "NSString", - "NSURL", - }; - - for (unsigned n = 0; n < sizeof(classes)/sizeof(classes[0]); n++) { - Class cls = objc_getClass(classes[n]); - if (cls) { - [errClasses addObject:cls]; - } - } + [errClasses unionSet:[SecXPCHelper safeErrorClasses]]; }); @try { - [interface setClasses:errClasses forSelector:@selector(rpcResetCloudKit:reason:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcResetLocal:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcResetCloudKit:reason:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcResync:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errClasses forSelector:@selector(rpcStatus:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcResyncLocal:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcStatus:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcFastStatus:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcFetchAndProcessChanges:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcFetchAndProcessClassAChanges:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcPushOutgoingChanges:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(rpcGetCKDeviceIDWithReply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(rpcCKMetric:attributes:reply:) argumentIndex:0 ofReply:YES]; } @catch(NSException* e) { secerror("CKKSSetupControlProtocol failed, continuing, but you might crash later: %@", e); -#if DEBUG @throw e; -#endif } #endif diff --git a/keychain/ckks/CKKSControlServer.m b/keychain/ckks/CKKSControlServer.m index fecffc4c..a76d72ee 100644 --- a/keychain/ckks/CKKSControlServer.m +++ b/keychain/ckks/CKKSControlServer.m @@ -16,14 +16,14 @@ #if OCTAGON NSNumber *num = [newConnection valueForEntitlement:(__bridge NSString *)kSecEntitlementPrivateCKKS]; if (![num isKindOfClass:[NSNumber class]] || ![num boolValue]) { - secerror("ckks: Client pid: %d doesn't have entitlement: %@", + ckkserror_global("ckks", "Client pid: %d doesn't have entitlement: %@", [newConnection processIdentifier], kSecEntitlementPrivateCKKS); return NO; } // In the future, we should consider vending a proxy object that can return a nicer error. if (!SecCKKSIsEnabled()) { - secerror("ckks: Client pid: %d attempted to use CKKS, but CKKS is not enabled.", + ckkserror_global("ckks", "Client pid: %d attempted to use CKKS, but CKKS is not enabled.", newConnection.processIdentifier); return NO; } diff --git a/keychain/ckks/CKKSCreateCKZoneOperation.h b/keychain/ckks/CKKSCreateCKZoneOperation.h new file mode 100644 index 00000000..8e9473f2 --- /dev/null +++ b/keychain/ckks/CKKSCreateCKZoneOperation.h @@ -0,0 +1,23 @@ + +#import + +#if OCTAGON + +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CKKSCreateCKZoneOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSCreateCKZoneOperation.m b/keychain/ckks/CKKSCreateCKZoneOperation.m new file mode 100644 index 00000000..3edc2c31 --- /dev/null +++ b/keychain/ckks/CKKSCreateCKZoneOperation.m @@ -0,0 +1,121 @@ +#if OCTAGON + +#import +#import + +#import "keychain/ckks/CKKSCreateCKZoneOperation.h" +#import "keychain/ckks/CKKSZoneStateEntry.h" +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ot/ObjCImprovements.h" +#import "keychain/ot/OTDefines.h" + +@implementation CKKSCreateCKZoneOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if(self = [super init]) { + _deps = dependencies; + + _intendedState = intendedState; + _nextState = errorState; + } + return self; +} + +- (void)groupStart +{ + __block CKKSZoneStateEntry* ckseOriginal = nil; + [self.deps.databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{ + ckseOriginal = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName]; + }]; + + if(ckseOriginal.ckzonecreated && ckseOriginal.ckzonesubscribed) { + ckksinfo("ckkskey", self.deps.zoneID, "Zone is already created and subscribed"); + self.nextState = self.intendedState; + return; + } + + ckksnotice("ckkszone", self.deps.zoneID, "Asking to create and subscribe to CloudKit zone '%@'", self.deps.zoneID.zoneName); + CKRecordZone* zone = [[CKRecordZone alloc] initWithZoneID:self.deps.zoneID]; + CKKSZoneModifyOperations* zoneOps = [self.deps.zoneModifier createZone:zone]; + + WEAKIFY(self); + + CKKSResultOperation* handleModificationsOperation = [CKKSResultOperation named:@"handle-modification" withBlock:^{ + STRONGIFY(self); + BOOL zoneCreated = NO; + BOOL zoneSubscribed = NO; + if([zoneOps.savedRecordZones containsObject:zone]) { + ckksinfo("ckkszone", self.deps.zoneID, "Successfully created '%@'", self.deps.zoneID); + zoneCreated = YES; + } else { + ckkserror("ckkszone", self.deps.zoneID, "Failed to create '%@'", self.deps.zoneID); + } + + bool createdSubscription = false; + for(CKSubscription* subscription in zoneOps.savedSubscriptions) { + if([subscription.subscriptionID isEqual:[@"zone:" stringByAppendingString: self.deps.zoneID.zoneName]]) { + zoneSubscribed = true; + break; + } + } + + if(createdSubscription) { + ckksinfo("ckkszone", self.deps.zoneID, "Successfully subscribed '%@'", self.deps.zoneID); + zoneSubscribed = YES; + } else { + ckkserror("ckkszone", self.deps.zoneID, "Failed to subscribe to '%@'", self.deps.zoneID); + } + + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + ckksnotice("ckkszone", self.deps.zoneID, "Zone setup progress: created:%d %@ subscribed:%d %@", + zoneCreated, + zoneOps.zoneModificationOperation.error, + zoneSubscribed, + zoneOps.zoneSubscriptionOperation.error); + + NSError* error = nil; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName]; + ckse.ckzonecreated = zoneCreated; + ckse.ckzonesubscribed = zoneSubscribed; + + // Although, if the zone subscribed error says there's no zone, mark down that there's no zone + if(zoneOps.zoneSubscriptionOperation.error && + [zoneOps.zoneSubscriptionOperation.error.domain isEqualToString:CKErrorDomain] && zoneOps.zoneSubscriptionOperation.error.code == CKErrorPartialFailure) { + NSError* subscriptionError = zoneOps.zoneSubscriptionOperation.error.userInfo[CKPartialErrorsByItemIDKey][self.deps.zoneID]; + if(subscriptionError && [subscriptionError.domain isEqualToString:CKErrorDomain] && subscriptionError.code == CKErrorZoneNotFound) { + + ckkserror("ckks", self.deps.zoneID, "zone subscription error appears to say the zone doesn't exist, fixing status: %@", zoneOps.zoneSubscriptionOperation.error); + ckse.ckzonecreated = false; + } + } + + [ckse saveToDatabase:&error]; + if(error) { + ckkserror("ckks", self.deps.zoneID, "couldn't save zone creation status for %@: %@", self.deps.zoneID, error); + } + + if(!zoneCreated || !zoneSubscribed) { + // Go into 'zonecreationfailed' + self.nextState = SecCKKSZoneKeyStateZoneCreationFailed; + self.error = zoneOps.zoneModificationOperation.error ?: zoneOps.zoneSubscriptionOperation.error; + } else { + self.nextState = self.intendedState; + } + + return CKKSDatabaseTransactionCommit; + }]; + }]; + + [handleModificationsOperation addNullableDependency:zoneOps.zoneModificationOperation]; + [handleModificationsOperation addNullableDependency:zoneOps.zoneSubscriptionOperation]; + [self runBeforeGroupFinished:handleModificationsOperation]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSCurrentKeyPointer.m b/keychain/ckks/CKKSCurrentKeyPointer.m index 78a935ad..d0c74c12 100644 --- a/keychain/ckks/CKKSCurrentKeyPointer.m +++ b/keychain/ckks/CKKSCurrentKeyPointer.m @@ -39,7 +39,7 @@ _currentKeyUUID = currentKeyUUID; if(self.currentKeyUUID == nil) { - secerror("ckkscurrentkey: created a CKKSCurrentKey with a nil currentKeyUUID. Why?"); + ckkserror_global("currentkey", "created a CKKSCurrentKey with a nil currentKeyUUID. Why?"); } } return self; @@ -126,7 +126,7 @@ self.currentKeyUUID = [record[SecCKRecordParentKeyRefKey] recordID].recordName; if(self.currentKeyUUID == nil) { - secerror("ckkscurrentkey: No current key UUID in record! How/why? %@", record); + ckkserror_global("currentkey", "No current key UUID in record! How/why? %@", record); } } diff --git a/keychain/ckks/CKKSDeleteCKZoneOperation.h b/keychain/ckks/CKKSDeleteCKZoneOperation.h new file mode 100644 index 00000000..bb7a5402 --- /dev/null +++ b/keychain/ckks/CKKSDeleteCKZoneOperation.h @@ -0,0 +1,22 @@ +#import + +#if OCTAGON + +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CKKSDeleteCKZoneOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSDeleteCKZoneOperation.m b/keychain/ckks/CKKSDeleteCKZoneOperation.m new file mode 100644 index 00000000..e2b5aa79 --- /dev/null +++ b/keychain/ckks/CKKSDeleteCKZoneOperation.m @@ -0,0 +1,101 @@ + + +#if OCTAGON + +#import +#import + +#import "keychain/ckks/CKKSDeleteCKZoneOperation.h" +#import "keychain/ckks/CKKSZoneStateEntry.h" +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ot/ObjCImprovements.h" +#import "keychain/ot/OTDefines.h" + +@implementation CKKSDeleteCKZoneOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if(self = [super init]) { + _deps = dependencies; + + _intendedState = intendedState; + _nextState = errorState; + } + return self; +} + +- (void)groupStart +{ + + ckksnotice("ckkszone", self.deps.zoneID, "Deleting CloudKit zone '%@'", self.deps.zoneID); + CKKSZoneModifyOperations* zoneOps = [self.deps.zoneModifier deleteZone:self.deps.zoneID]; + + + WEAKIFY(self); + + CKKSResultOperation* handleModificationsOperation = [CKKSResultOperation named:@"handle-modification" withBlock:^{ + STRONGIFY(self); + + bool fatalError = false; + + NSError* operationError = zoneOps.zoneModificationOperation.error; + bool removed = [zoneOps.deletedRecordZoneIDs containsObject:self.deps.zoneID]; + + if(!removed && operationError) { + // Okay, but if this error is either 'ZoneNotFound' or 'UserDeletedZone', that's fine by us: the zone is deleted. + NSDictionary* partialErrors = operationError.userInfo[CKPartialErrorsByItemIDKey]; + if([operationError.domain isEqualToString:CKErrorDomain] && operationError.code == CKErrorPartialFailure && partialErrors) { + for(CKRecordZoneID* errorZoneID in partialErrors.allKeys) { + NSError* errorZone = partialErrors[errorZoneID]; + + if(errorZone && [errorZone.domain isEqualToString:CKErrorDomain] && + (errorZone.code == CKErrorZoneNotFound || errorZone.code == CKErrorUserDeletedZone)) { + ckksnotice("ckkszone", self.deps.zoneID, "Attempted to delete zone %@, but it's already missing. This is okay: %@", errorZoneID, errorZone); + } else { + fatalError = true; + } + } + + } else { + fatalError = true; + } + + ckksnotice("ckkszone", self.deps.zoneID, "deletion of record zone %@ completed with error: %@", self.deps.zoneID, operationError); + + if(fatalError) { + // Early-exit + self.error = operationError; + return; + } + } + + ckksnotice("ckkszone", self.deps.zoneID, "deletion of record zone %@ completed successfully", self.deps.zoneID); + + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName]; + ckse.ckzonecreated = NO; + ckse.ckzonesubscribed = NO; + + [ckse saveToDatabase:&error]; + if(error) { + ckkserror("ckks", self.deps.zoneID, "couldn't save zone creation status for %@: %@", self.deps.zoneID, error); + } + + self.nextState = self.intendedState; + return CKKSDatabaseTransactionCommit; + }]; + }]; + + [handleModificationsOperation addNullableDependency:zoneOps.zoneModificationOperation]; + [handleModificationsOperation addNullableDependency:zoneOps.zoneSubscriptionOperation]; + [self runBeforeGroupFinished:handleModificationsOperation]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSDeviceStateEntry.m b/keychain/ckks/CKKSDeviceStateEntry.m index 557de53c..b19013e6 100644 --- a/keychain/ckks/CKKSDeviceStateEntry.m +++ b/keychain/ckks/CKKSDeviceStateEntry.m @@ -104,7 +104,7 @@ case (uint32_t)kSOSCCError: // And, if by some miracle, you end up with -1 as a uint32_t, accept that too return kSOSCCError; default: - secerror("ckks: %d is not an SOSCCStatus?", n); + ckkserror_global("ckks", "%d is not an SOSCCStatus?", n); return kSOSCCError; } } @@ -146,7 +146,7 @@ case (uint32_t)kSOSCCErrorPositive: // Use the magic number return [[OTCliqueStatusWrapper alloc] initWithStatus:CliqueStatusError]; default: - secerror("ckks: %d is not an OTCliqueStatus?", n); + ckkserror_global("ckks", "%d is not an OTCliqueStatus?", n); return [[OTCliqueStatusWrapper alloc] initWithStatus:CliqueStatusError];; } } diff --git a/keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.m b/keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.m index 9a03e976..7212cf97 100644 --- a/keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.m +++ b/keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.m @@ -144,7 +144,7 @@ if(!self.forceResync) { if (self.changeTokens[clientZoneID]) { options.previousServerChangeToken = self.changeTokens[clientZoneID]; - secnotice("ckksfetch", "Using cached change token for %@: %@", clientZoneID, self.changeTokens[clientZoneID]); + ckksnotice_global("ckksfetch", "Using cached change token for %@: %@", clientZoneID, self.changeTokens[clientZoneID]); } else { options.previousServerChangeToken = clientPreference.changeToken; } @@ -168,7 +168,7 @@ if(self.fetchedZoneIDs.count == 0) { // No clients actually want to fetch right now, so quit self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSNoFetchesRequested description:@"No clients want a fetch right now"]; - secnotice("ckksfetch", "Cancelling fetch: %@", self.error); + ckksnotice_global("ckksfetch", "Cancelling fetch: %@", self.error); return; } @@ -196,7 +196,7 @@ // networkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; //} - secnotice("ckksfetch", "Beginning fetch with discretionary network (%d): %@", (int)networkBehavior, self.allClientOptions); + ckksnotice_global("ckksfetch", "Beginning fetch with discretionary network (%d): %@", (int)networkBehavior, self.allClientOptions); self.fetchRecordZoneChangesOperation = [[self.fetchRecordZoneChangesOperationClass alloc] initWithRecordZoneIDs:self.fetchedZoneIDs configurationsByRecordZoneID:self.allClientOptions]; @@ -204,11 +204,11 @@ self.fetchRecordZoneChangesOperation.configuration.discretionaryNetworkBehavior = networkBehavior; self.fetchRecordZoneChangesOperation.configuration.isCloudKitSupportOperation = YES; self.fetchRecordZoneChangesOperation.group = self.ckoperationGroup; - secnotice("ckksfetch", "Operation group is %@", self.ckoperationGroup); + ckksnotice_global("ckksfetch", "Operation group is %@", self.ckoperationGroup); self.fetchRecordZoneChangesOperation.recordChangedBlock = ^(CKRecord *record) { STRONGIFY(self); - secinfo("ckksfetch", "CloudKit notification: record changed(%@): %@", [record recordType], record); + ckksinfo_global("ckksfetch", "CloudKit notification: record changed(%@): %@", [record recordType], record); // Add this to the modifications, and remove it from the deletions self.modifications[record.recordID] = record; @@ -218,7 +218,7 @@ self.fetchRecordZoneChangesOperation.recordWithIDWasDeletedBlock = ^(CKRecordID *recordID, NSString *recordType) { STRONGIFY(self); - secinfo("ckksfetch", "CloudKit notification: deleted record(%@): %@", recordType, recordID); + ckksinfo_global("ckksfetch", "CloudKit notification: deleted record(%@): %@", recordType, recordID); // Add to the deletions, and remove any pending modifications [self.modifications removeObjectForKey: recordID]; @@ -229,25 +229,25 @@ self.fetchRecordZoneChangesOperation.recordZoneChangeTokensUpdatedBlock = ^(CKRecordZoneID *recordZoneID, CKServerChangeToken *serverChangeToken, NSData *clientChangeTokenData) { STRONGIFY(self); - secinfo("ckksfetch", "Received a new server change token (via block) for %@: %@ %@", recordZoneID, serverChangeToken, clientChangeTokenData); + ckksinfo_global("ckksfetch", "Received a new server change token (via block) for %@: %@ %@", recordZoneID, serverChangeToken, clientChangeTokenData); self.changeTokens[recordZoneID] = serverChangeToken; }; self.fetchRecordZoneChangesOperation.recordZoneFetchCompletionBlock = ^(CKRecordZoneID *recordZoneID, CKServerChangeToken *serverChangeToken, NSData *clientChangeTokenData, BOOL moreComing, NSError * recordZoneError) { STRONGIFY(self); - secnotice("ckksfetch", "Received a new server change token for %@: %@ %@", recordZoneID, serverChangeToken, clientChangeTokenData); + ckksinfo_global("ckksfetch", "Received a new server change token for %@: %@ %@", recordZoneID, serverChangeToken, clientChangeTokenData); self.changeTokens[recordZoneID] = serverChangeToken; self.allClientOptions[recordZoneID].previousServerChangeToken = serverChangeToken; self.moreComing |= moreComing; if(moreComing) { - secnotice("ckksfetch", "more changes pending for %@, will start a new fetch at change token %@", recordZoneID, self.changeTokens[recordZoneID]); + ckksnotice_global("ckksfetch", "more changes pending for %@, will start a new fetch at change token %@", recordZoneID, self.changeTokens[recordZoneID]); } - ckksnotice("ckksfetch", recordZoneID, "Record zone fetch complete: changeToken=%@ clientChangeTokenData=%@ moreComing=%@ error=%@", serverChangeToken, clientChangeTokenData, - moreComing ? @"YES" : @"NO", - recordZoneError); + ckksinfo("ckksfetch", recordZoneID, "Record zone fetch complete: changeToken=%@ clientChangeTokenData=%@ moreComing=%@ error=%@", serverChangeToken, clientChangeTokenData, + moreComing ? @"YES" : @"NO", + recordZoneError); [self sendChangesToClient:recordZoneID moreComing:moreComing]; }; @@ -257,7 +257,7 @@ self.fetchRecordZoneChangesOperation.fetchRecordZoneChangesCompletionBlock = ^(NSError * _Nullable operationError) { STRONGIFY(self); if(!self) { - secerror("ckksfetch: received callback for released object"); + ckkserror_global("ckksfetch", "received callback for released object"); return; } @@ -273,7 +273,7 @@ // If we were told that there were moreChanges coming for any zone, we'd like to fetch again. // This is true if we recieve no error or a network timeout. Any other error should cause a failure. if(self.moreComing && (operationError == nil || [CKKSReachabilityTracker isNetworkFailureError:operationError])) { - secnotice("ckksfetch", "Must issue another fetch (with potential error %@)", operationError); + ckksnotice_global("ckksfetch", "Must issue another fetch (with potential error %@)", operationError); self.moreComing = false; [self performFetch]; return; @@ -283,7 +283,7 @@ self.error = operationError; } - secnotice("ckksfetch", "Record zone changes fetch complete: error=%@", operationError); + ckksnotice_global("ckksfetcher", "Record zone changes fetch complete: error=%@", operationError); [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventFetchAllChanges count:self.fetchedItems]; @@ -300,7 +300,7 @@ for(CKRecordZoneNotification* rz in self.apnsPushes) { if(rz.ckksPushTracingEnabled) { - secnotice("ckksfetch", "Submitting post-fetch CKEventMetric due to notification %@", rz); + ckksnotice_global("ckksfetch", "Submitting post-fetch CKEventMetric due to notification %@", rz); // Schedule submitting this metric on another operation, so hopefully CK will have marked this fetch as done by the time that fires? CKEventMetric *metric = [[CKEventMetric alloc] initWithEventName:@"APNSPushMetrics"]; @@ -339,11 +339,11 @@ CKKSResultOperation* launchMetricOp = [CKKSResultOperation named:@"submit-metric" withBlock:^{ if(![metric associateWithCompletedOperation:rzcOperation]) { - secerror("ckksfetch: Couldn't associate metric with operation: %@ %@", metric, rzcOperation); + ckkserror_global("ckksfetch", "Couldn't associate metric with operation: %@ %@", metric, rzcOperation); } [container submitEventMetric:metric]; [[SecMetrics managerObject] submitEvent:metric2]; - secnotice("ckksfetch", "Metric submitted: %@", metric); + ckksnotice_global("ckksfetch", "Metric submitted: %@", metric); }]; [launchMetricOp addSuccessDependency:self.fetchCompletedOperation]; @@ -367,7 +367,7 @@ { id client = self.clientMap[recordZoneID]; if(!client) { - secerror("ckksfetch: no client registered for %@, so why did we get any data?", recordZoneID); + ckkserror_global("ckksfetch", "no client registered for %@, so why did we get any data?", recordZoneID); return; } @@ -395,8 +395,8 @@ BOOL resync = [self.resyncingZones containsObject:recordZoneID]; - ckksnotice("ckksfetch", recordZoneID, "Delivering fetched changes: changed=%lu deleted=%lu moreComing=%lu resync=%u", - (unsigned long)zoneModifications.count, (unsigned long)zoneDeletions.count, (unsigned long)moreComing, resync); + ckksnotice("ckksfetch", recordZoneID, "Delivering fetched changes: changed=%lu deleted=%lu moreComing=%lu resync=%u changeToken=%@", + (unsigned long)zoneModifications.count, (unsigned long)zoneDeletions.count, (unsigned long)moreComing, resync, self.changeTokens[recordZoneID]); // Tell the client about these changes! [client changesFetched:zoneModifications diff --git a/keychain/ckks/CKKSFixups.h b/keychain/ckks/CKKSFixups.h index 98e48dd7..d64fba89 100644 --- a/keychain/ckks/CKKSFixups.h +++ b/keychain/ckks/CKKSFixups.h @@ -40,11 +40,12 @@ typedef NS_ENUM(NSUInteger, CKKSFixup) { CKKSFixupFetchTLKShares, CKKSFixupLocalReload, CKKSFixupResaveDeviceStateEntries, + CKKSFixupDeleteAllCKKSTombstones, }; -#define CKKSCurrentFixupNumber (CKKSFixupResaveDeviceStateEntries) +#define CKKSCurrentFixupNumber (CKKSFixupDeleteAllCKKSTombstones) @interface CKKSFixups : NSObject -+(CKKSGroupOperation*)fixup:(CKKSFixup)lastfixup for:(CKKSKeychainView*)keychainView; ++(nullable CKKSGroupOperation*)fixup:(CKKSFixup)lastfixup for:(CKKSKeychainView*)keychainView; @end // Fixup declarations. You probably don't need to look at these @@ -61,6 +62,7 @@ typedef NS_ENUM(NSUInteger, CKKSFixup) { @interface CKKSFixupLocalReloadOperation : CKKSGroupOperation @property (weak) CKKSKeychainView* ckks; - (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)keychainView + fixupNumber:(CKKSFixup)fixupNumber ckoperationGroup:(CKOperationGroup*)ckoperationGroup; @end diff --git a/keychain/ckks/CKKSFixups.m b/keychain/ckks/CKKSFixups.m index 927cf56e..44f2ef5a 100644 --- a/keychain/ckks/CKKSFixups.m +++ b/keychain/ckks/CKKSFixups.m @@ -31,7 +31,7 @@ #import "keychain/ot/ObjCImprovements.h" @implementation CKKSFixups -+(CKKSGroupOperation*)fixup:(CKKSFixup)lastfixup for:(CKKSKeychainView*)keychainView ++(nullable CKKSGroupOperation*)fixup:(CKKSFixup)lastfixup for:(CKKSKeychainView*)keychainView { if(lastfixup == CKKSCurrentFixupNumber) { return nil; @@ -61,6 +61,7 @@ if(lastfixup < CKKSFixupLocalReload) { CKKSResultOperation* localSync = [[CKKSFixupLocalReloadOperation alloc] initWithCKKSKeychainView:keychainView + fixupNumber:CKKSFixupLocalReload ckoperationGroup:fixupCKGroup]; [localSync addNullableSuccessDependency:previousOp]; [fixups runBeforeGroupFinished:localSync]; @@ -75,6 +76,15 @@ previousOp = resave; } + if(lastfixup < CKKSFixupDeleteAllCKKSTombstones) { + CKKSResultOperation* localSync = [[CKKSFixupLocalReloadOperation alloc] initWithCKKSKeychainView:keychainView + fixupNumber:CKKSFixupDeleteAllCKKSTombstones + ckoperationGroup:fixupCKGroup]; + [localSync addNullableSuccessDependency:previousOp]; + [fixups runBeforeGroupFinished:localSync]; + previousOp = localSync; + } + (void)previousOp; return fixups; } @@ -111,13 +121,13 @@ return; } - [ckks dispatchSyncWithAccountKeys:^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; NSArray* cips = [CKKSCurrentItemPointer allInZone: ckks.zoneID error:&error]; if(error) { ckkserror("ckksfixup", ckks, "Couldn't fetch current item pointers: %@", error); - return false; + return CKKSDatabaseTransactionRollback; } NSMutableSet* recordIDs = [NSMutableSet set]; @@ -137,12 +147,12 @@ WEAKIFY(self); NSBlockOperation* doneOp = [NSBlockOperation named:@"fetch-records-operation-complete" withBlock:^{}]; - id fetch = [[ckks.cloudKitClassDependencies.fetchRecordsOperationClass alloc] initWithRecordIDs: [recordIDs allObjects]]; + CKDatabaseOperation* fetch = [[ckks.cloudKitClassDependencies.fetchRecordsOperationClass alloc] initWithRecordIDs: [recordIDs allObjects]]; fetch.fetchRecordsCompletionBlock = ^(NSDictionary * _Nullable recordsByRecordID, NSError * _Nullable error) { STRONGIFY(self); CKKSKeychainView* strongCKKS = self.ckks; - [strongCKKS dispatchSync:^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(error) { ckkserror("ckksfixup", strongCKKS, "Finished record fetch with error: %@", error); @@ -186,14 +196,14 @@ } [self runBeforeGroupFinished:doneOp]; - return true; + return CKKSDatabaseTransactionCommit; }]; }; [ckks.database addOperation: fetch]; [self dependOnBeforeGroupFinished:fetch]; [self dependOnBeforeGroupFinished:doneOp]; - return true; + return CKKSDatabaseTransactionCommit; }]; } @end @@ -229,25 +239,25 @@ return; } - [ckks dispatchSyncWithAccountKeys:^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ WEAKIFY(self); NSBlockOperation* doneOp = [NSBlockOperation named:@"fetch-records-operation-complete" withBlock:^{}]; NSPredicate *yes = [NSPredicate predicateWithValue:YES]; CKQuery *query = [[CKQuery alloc] initWithRecordType:SecCKRecordTLKShareType predicate:yes]; - id fetch = [[ckks.cloudKitClassDependencies.queryOperationClass alloc] initWithQuery:query]; + CKDatabaseOperation* fetch = [[ckks.cloudKitClassDependencies.queryOperationClass alloc] initWithQuery:query]; fetch.zoneID = ckks.zoneID; fetch.desiredKeys = nil; fetch.recordFetchedBlock = ^(CKRecord * _Nonnull record) { STRONGIFY(self); CKKSKeychainView* strongCKKS = self.ckks; - [strongCKKS dispatchSync:^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ ckksnotice("ckksfixup", strongCKKS, "Recieved tlk share record from query: %@", record); [strongCKKS _onqueueCKRecordChanged:record resync:true]; - return true; + return CKKSDatabaseTransactionCommit; }]; }; @@ -255,11 +265,11 @@ STRONGIFY(self); CKKSKeychainView* strongCKKS = self.ckks; - [strongCKKS dispatchSync:^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(error) { ckkserror("ckksfixup", strongCKKS, "Couldn't fetch all TLKShare records: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } ckksnotice("ckksfixup", strongCKKS, "Successfully fetched TLKShare records (%@)", cursor); @@ -273,7 +283,7 @@ } else { ckksnotice("ckksfixup", strongCKKS, "Updated zone fixup state to CKKSFixupFetchTLKShares"); } - return true; + return CKKSDatabaseTransactionCommit; }]; [self runBeforeGroupFinished:doneOp]; }; @@ -282,7 +292,7 @@ [self dependOnBeforeGroupFinished:fetch]; [self dependOnBeforeGroupFinished:doneOp]; - return true; + return CKKSDatabaseTransactionCommit; }]; } @end @@ -291,24 +301,31 @@ @interface CKKSFixupLocalReloadOperation () @property CKOperationGroup* group; +@property CKKSFixup fixupNumber; @end // In Server Generated CloudKit "Manatee Identity Lost" // items could be deleted from the local keychain after CKKS believed they were already synced, and therefore wouldn't resync // Perform a local resync operation +// +// In CKKS: adjust UUID and tombstone handling +// some CKKS participants uploaded entries with tomb=1 to CKKS +// Performing a local reload operation should find and delete those entries @implementation CKKSFixupLocalReloadOperation - (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)keychainView + fixupNumber:(CKKSFixup)fixupNumber ckoperationGroup:(CKOperationGroup *)ckoperationGroup { if((self = [super init])) { _ckks = keychainView; + _fixupNumber = fixupNumber; _group = ckoperationGroup; } return self; } - (NSString*)description { - return [NSString stringWithFormat:@"", self.ckks]; + return [NSString stringWithFormat:@"", (int)self.fixupNumber, self.ckks]; } - (void)groupStart { CKKSKeychainView* ckks = self.ckks; @@ -325,25 +342,26 @@ CKKSResultOperation* cleanup = [CKKSResultOperation named:@"local-reload-cleanup" withBlock:^{ STRONGIFY(self); __strong __typeof(self.ckks) strongCKKS = self.ckks; - [strongCKKS dispatchSync:^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(reload.error) { ckkserror("ckksfixup", strongCKKS, "Couldn't perform a reload: %@", reload.error); self.error = reload.error; - return false; + return CKKSDatabaseTransactionRollback; } - ckksnotice("ckksfixup", strongCKKS, "Successfully performed a reload fixup"); + ckksnotice("ckksfixup", strongCKKS, "Successfully performed a reload fixup. New fixup number is %d", + (int)self.fixupNumber); NSError* localerror = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:strongCKKS.zoneName error:&localerror]; - ckse.lastFixup = CKKSFixupLocalReload; + ckse.lastFixup = self.fixupNumber; [ckse saveToDatabase:&localerror]; if(localerror) { ckkserror("ckksfixup", strongCKKS, "Couldn't save CKKSZoneStateEntry(%@): %@", ckse, localerror); } else { ckksnotice("ckksfixup", strongCKKS, "Updated zone fixup state to CKKSFixupLocalReload"); } - return true; + return CKKSDatabaseTransactionCommit; }]; }]; [cleanup addNullableDependency:reload]; @@ -377,7 +395,7 @@ } // This operation simply loads all CDSEs, remakes them from their CKRecord, and resaves them - [ckks dispatchSync:^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; NSArray* cdses = [CKKSDeviceStateEntry allInZone:ckks.zoneID error:&error]; @@ -385,7 +403,7 @@ if(error) { ckkserror("ckksfixup", ckks, "Unable to fetch all CDSEs: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } for(CKKSDeviceStateEntry* cdse in cdses) { @@ -397,7 +415,7 @@ if(error) { ckkserror("ckksfixup", ckks, "Unable to save CDSE: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } } else { ckksnotice("ckksfixup", ckks, "Saved CDSE has no stored record: %@", cdse); @@ -413,12 +431,12 @@ if(localerror) { ckkserror("ckksfixup", ckks, "Couldn't save CKKSZoneStateEntry(%@): %@", ckse, localerror); self.error = localerror; - return false; + return CKKSDatabaseTransactionRollback; } ckksnotice("ckksfixup", ckks, "Updated zone fixup state to CKKSFixupResaveDeviceStateEntries"); - return true; + return CKKSDatabaseTransactionCommit; }]; } diff --git a/keychain/ckks/CKKSGroupOperation.m b/keychain/ckks/CKKSGroupOperation.m index d85e9fad..bc984f44 100644 --- a/keychain/ckks/CKKSGroupOperation.m +++ b/keychain/ckks/CKKSGroupOperation.m @@ -25,7 +25,7 @@ #import "CKKSGroupOperation.h" #import "keychain/ot/ObjCImprovements.h" -#include +#import "keychain/ckks/CKKS.h" @interface CKKSGroupOperation() @property bool fillInError; @@ -53,12 +53,12 @@ _startOperation = [NSBlockOperation blockOperationWithBlock:^{ STRONGIFY(self); if(!self) { - secerror("ckks: received callback for released object"); + ckkserror_global("ckks", "received callback for released object"); return; } if(![self allDependentsSuccessful]) { - secdebug("ckksgroup", "Not running due to some failed dependent: %@", self.error); + ckksinfo_global("ckksgroup", "Not running due to some failed dependent: %@", self.error); [self cancel]; return; } @@ -71,7 +71,7 @@ _finishOperation = [NSBlockOperation blockOperationWithBlock:^{ STRONGIFY(self); if(!self) { - secerror("ckks: received callback for released object"); + ckkserror_global("ckks", "received callback for released object"); return; } @@ -114,37 +114,62 @@ } - (NSString*)description { - if(self.isFinished) { + + static __thread unsigned __descriptionRecursion = 0; + NSString* state = [self operationStateString]; + NSString *desc = NULL; + + __descriptionRecursion++; + + if(__descriptionRecursion > 10) { + desc = [NSString stringWithFormat: @"<%@: %@ recursion>", [self selfname], state]; + + } else if(self.isFinished) { if(self.error) { - return [NSString stringWithFormat: @"<%@: %@ %@ - %@>", [self selfname], - [self operationStateString], + desc = [NSString stringWithFormat: @"<%@: %@ %@ - %@>", [self selfname], + state, self.finishDate, self.error]; } else { - return [NSString stringWithFormat: @"<%@: %@ %@>", [self selfname], - [self operationStateString], + desc = [NSString stringWithFormat: @"<%@: %@ %@>", [self selfname], + state, self.finishDate]; } - } + } else { - NSMutableArray* ops = [self.operationQueue.operations mutableCopy]; + NSString* opsString = nil; - [ops removeObject: self.finishOperation]; + if (self.operationQueue.operationCount + self.finishOperation.dependencies.count > 20) { + opsString = @"Potentially more than 20 operations"; + } else { + NSMutableArray* ops = [self.operationQueue.operations mutableCopy]; + + [ops removeObject: self.finishOperation]; + + // Any extra dependencies from the finish operation should be considered part of this group + for(NSOperation* finishDep in self.finishOperation.dependencies) { + if (ops.count > 20) { + opsString = @"Potentially more than 20 operations"; + break; + } + if(finishDep != self.startOperation && (NSNotFound == [ops indexOfObject: finishDep])) { + [ops addObject: finishDep]; + } + } + if (opsString == nil) { + opsString = [ops componentsJoinedByString:@", "]; + } + } - // Any extra dependencies from the finish operation should be considered part of this group - for(NSOperation* finishDep in self.finishOperation.dependencies) { - if(finishDep != self.startOperation && (NSNotFound == [ops indexOfObject: finishDep])) { - [ops addObject: finishDep]; + if(self.error) { + desc = [NSString stringWithFormat: @"<%@: %@ [%@] error:%@>", [self selfname], state, opsString, self.error]; + } else { + desc = [NSString stringWithFormat: @"<%@: %@ [%@]%@>", [self selfname], state, opsString, [self pendingDependenciesString:@" dep:"]]; } } + __descriptionRecursion--; - NSString* opsString = [ops componentsJoinedByString:@", "]; - - if(self.error) { - return [NSString stringWithFormat: @"<%@: %@ [%@] error:%@>", [self selfname], [self operationStateString], opsString, self.error]; - } else { - return [NSString stringWithFormat: @"<%@: %@ [%@]%@>", [self selfname], [self operationStateString], opsString, [self pendingDependenciesString:@" dep:"]]; - } + return desc; } - (NSString*)debugDescription { @@ -275,7 +300,7 @@ if([self isCancelled]) { // Cancelled operations can't add anything. - secnotice("ckksgroup", "Can't add operation dependency to cancelled group"); + ckksnotice_global("ckksgroup", "Can't add operation dependency to cancelled group"); return; } diff --git a/keychain/ckks/CKKSHealKeyHierarchyOperation.h b/keychain/ckks/CKKSHealKeyHierarchyOperation.h index 2e30b8c3..7fbbb63e 100644 --- a/keychain/ckks/CKKSHealKeyHierarchyOperation.h +++ b/keychain/ckks/CKKSHealKeyHierarchyOperation.h @@ -23,6 +23,8 @@ #import #import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" #if OCTAGON @@ -30,12 +32,16 @@ NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -@interface CKKSHealKeyHierarchyOperation : CKKSGroupOperation +@interface CKKSHealKeyHierarchyOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; +@property OctagonState* nextState; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; - +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSHealKeyHierarchyOperation.m b/keychain/ckks/CKKSHealKeyHierarchyOperation.m index 21351856..69720cb7 100644 --- a/keychain/ckks/CKKSHealKeyHierarchyOperation.m +++ b/keychain/ckks/CKKSHealKeyHierarchyOperation.m @@ -28,6 +28,7 @@ #import "CKKSGroupOperation.h" #import "CKKSAnalytics.h" #import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/CKKSHealTLKSharesOperation.h" #import "keychain/categories/NSError+UsefulConstructors.h" #import "keychain/ot/ObjCImprovements.h" @@ -35,18 +36,26 @@ @interface CKKSHealKeyHierarchyOperation () @property NSBlockOperation* cloudkitModifyOperationFinished; -@property CKOperationGroup* ckoperationGroup; @end @implementation CKKSHealKeyHierarchyOperation +@synthesize intendedState = _intendedState; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { - if(self = [super init]) { + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if((self = [super init])) { + _deps = dependencies; _ckks = ckks; - _ckoperationGroup = ckoperationGroup; + + _intendedState = intendedState; + _nextState = errorState; } return self; } @@ -73,11 +82,13 @@ return; } + NSArray* currentTrustStates = self.deps.currentTrustStates; + // Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety. - [ckks dispatchSyncWithAccountKeys: ^bool{ + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { ckksnotice("ckksheal", ckks, "CKKSHealKeyHierarchyOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } NSError* error = nil; @@ -109,8 +120,8 @@ // If we haven't done one yet, initiate a refetch of everything from cloudkit, and write down that we did so if(!ckks.keyStateMachineRefetched) { ckksnotice("ckksheal", ckks, "Have current key pointers, but no keys. This is exceptional; requesting full refetch"); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateNeedFullRefetch withError:nil]; - return true; + self.nextState = SecCKKSZoneKeyStateNeedFullRefetch; + return CKKSDatabaseTransactionCommit; } } @@ -150,39 +161,42 @@ newTLK = topKey; } else if(![newTLK.uuid isEqualToString: topKey.uuid]) { ckkserror("ckksheal", ckks, "key hierarchy has split: there's two top keys. Currently we don't handle this situation."); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: [NSError errorWithDomain:CKKSErrorDomain - code:CKKSSplitKeyHierarchy - userInfo:@{NSLocalizedDescriptionKey: - [NSString stringWithFormat:@"Key hierarchy has split: %@ and %@ are roots", newTLK, topKey]}]]; - return true; + self.error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSSplitKeyHierarchy + description:[NSString stringWithFormat:@"Key hierarchy has split: %@ and %@ are roots", newTLK, topKey]]; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; } } if(!newTLK) { // We don't have any TLKs lying around, but we're supposed to heal the key hierarchy. This isn't any good; let's wait for TLK creation. ckkserror("ckksheal", ckks, "No possible TLK found. Waiting for creation."); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForTLKCreation withError:nil]; - return true; + self.nextState = SecCKKSZoneKeyStateWaitForTLKCreation; + return CKKSDatabaseTransactionCommit; } - if(![ckks _onqueueWithAccountKeysCheckTLK: newTLK error: &error]) { - // Was this error "I've never seen that TLK before in my life"? If so, enter the "wait for TLK sync" state. - if(error && [error.domain isEqualToString: @"securityd"] && error.code == errSecItemNotFound) { - ckksnotice("ckksheal", ckks, "Received a TLK which we don't have in the local keychain(%@). Entering waitfortlk.", newTLK); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForTLK withError:nil]; - return true; - } else if(error && [ckks.lockStateTracker isLockedError:error]) { - ckksnotice("ckkskey", ckks, "Received a TLK(%@), but keybag appears to be locked. Entering WaitForUnlock.", newTLK); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForUnlock withError:nil]; - return true; + if(![newTLK validTLK:&error]) { + // Something has gone horribly wrong. Enter error state. + ckkserror("ckkskey", ckks, "CKKS claims %@ is not a valid TLK: %@", newTLK, error); + self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSInvalidTLK description:@"Invalid TLK from CloudKit (during heal)" underlying:error]; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; + } + // This key is our proposed TLK. + if(![newTLK tlkMaterialPresentOrRecoverableViaTLKShare:currentTrustStates + error:&error]) { + // TLK is valid, but not present locally + if(error && [self.deps.lockStateTracker isLockedError:error]) { + ckksnotice("ckkskey", ckks, "Received a TLK(%@), but keybag appears to be locked. Entering a waiting state.", newTLK); + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; } else { - // Otherwise, something has gone horribly wrong. enter error state. - ckkserror("ckksheal", ckks, "CKKS claims %@ is not a valid TLK: %@", newTLK, error); - NSError* newError = [NSError errorWithDomain:CKKSErrorDomain code:CKKSInvalidTLK description:@"Invalid TLK from CloudKit (during heal)" underlying:error]; - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:newError]; - return true; + ckksnotice("ckkskey", ckks, "Received a TLK(%@) which we don't have in the local keychain: %@", newTLK, error); + self.error = error; + self.nextState = SecCKKSZoneKeyStateTLKMissing; } + return CKKSDatabaseTransactionCommit; } // We have our new TLK. @@ -224,12 +238,14 @@ if(error && [ckks.lockStateTracker isLockedError:error]) { ckksnotice("ckksheal", ckks, "Couldn't create a new class A key, but keybag appears to be locked. Entering waitforunlock."); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForUnlock withError:error]; - return true; + self.error = error; + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + return CKKSDatabaseTransactionCommit; } else if(error) { ckkserror("ckksheal", ckks, "couldn't create new classA key: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:error]; - return true; + self.error = error; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; } keyset.classA = newClassAKey; @@ -242,12 +258,14 @@ if(error && [ckks.lockStateTracker isLockedError:error]) { ckksnotice("ckksheal", ckks, "Couldn't create a new class C key, but keybag appears to be locked. Entering waitforunlock."); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForUnlock withError:error]; - return true; + self.error = error; + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + return CKKSDatabaseTransactionCommit; } else if(error) { ckkserror("ckksheal", ckks, "couldn't create new class C key: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:error]; - return true; + self.error = error; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; } keyset.classC = newClassCKey; @@ -279,11 +297,12 @@ } // We've selected a new TLK. Compute any TLKShares that should go along with it. - NSSet* tlkShares = [ckks _onqueueCreateMissingKeyShares:keyset.tlk - error:&error]; + NSSet* tlkShares = [CKKSHealTLKSharesOperation createMissingKeyShares:keyset + trustStates:currentTrustStates + error:&error]; if(error) { ckkserror("ckksshare", ckks, "Unable to create TLK shares for new tlk: %@", error); - return false; + return CKKSDatabaseTransactionRollback; } for(CKKSTLKShareRecord* share in tlkShares) { @@ -316,8 +335,8 @@ modifyRecordsOp.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; modifyRecordsOp.configuration.isCloudKitSupportOperation = YES; - modifyRecordsOp.group = self.ckoperationGroup; - ckksnotice("ckksheal", ckks, "Operation group is %@", self.ckoperationGroup); + modifyRecordsOp.group = self.deps.ckoperationGroup; + ckksnotice("ckksheal", ckks, "Operation group is %@", self.deps.ckoperationGroup); modifyRecordsOp.perRecordCompletionBlock = ^(CKRecord *record, NSError * _Nullable error) { STRONGIFY(self); @@ -335,15 +354,15 @@ STRONGIFY(self); CKKSKeychainView* strongCKKS = self.ckks; if(!self) { - secerror("ckks: received callback for released object"); + ckkserror_global("ckks", "received callback for released object"); return; } ckksnotice("ckksheal", strongCKKS, "Completed Key Heal CloudKit operation with error: %@", error); - [strongCKKS dispatchSyncWithAccountKeys: ^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(error == nil) { - [[CKKSAnalytics logger] logSuccessForEvent:CKKSEventProcessHealKeyHierarchy inView:ckks]; + [[CKKSAnalytics logger] logSuccessForEvent:CKKSEventProcessHealKeyHierarchy zoneName:ckks.zoneName]; // Success. Persist the keys to the CKKS database. // Save the new CKRecords to the before persisting to database @@ -381,20 +400,22 @@ if(localerror != nil) { ckkserror("ckksheal", strongCKKS, "couldn't save new key hierarchy to database; this is very bad: %@", localerror); - [strongCKKS _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: localerror]; - return false; + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionRollback; } else { // Everything is groovy. HOWEVER, we might still not have processed the keys. Ask for that! - [strongCKKS _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateProcess withError: nil]; + self.nextState = SecCKKSZoneKeyStateProcess; } } else { // ERROR. This isn't a total-failure error state, but one that should kick off a healing process. - [[CKKSAnalytics logger] logUnrecoverableError:error forEvent:CKKSEventProcessHealKeyHierarchy inView:ckks withAttributes:NULL]; + [[CKKSAnalytics logger] logUnrecoverableError:error forEvent:CKKSEventProcessHealKeyHierarchy zoneName:ckks.zoneName withAttributes:NULL]; ckkserror("ckksheal", strongCKKS, "couldn't save new key hierarchy to CloudKit: %@", error); [strongCKKS _onqueueCKWriteFailed:error attemptedRecordsChanged:attemptedRecords]; - [strongCKKS _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateNewTLKsFailed withError: nil]; + + self.nextState = SecCKKSZoneKeyStateNewTLKsFailed; } - return true; + return CKKSDatabaseTransactionCommit; }]; // Notify that we're done @@ -406,37 +427,46 @@ } // Check if CKKS can recover this TLK. - bool haveTLK = [ckks _onqueueWithAccountKeysCheckTLK:keyset.tlk error:&error]; - if(error && [ckks.lockStateTracker isLockedError:error]) { - ckksnotice("ckkskey", ckks, "Failed to load TLK from keychain, keybag is locked. Entering waitforunlock: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForUnlock withError:nil]; - return false; - } else if(error && [error.domain isEqualToString: @"securityd"] && error.code == errSecItemNotFound) { - ckkserror("ckksheal", ckks, "CKKS couldn't find TLK, triggering move to wait state: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateWaitForTLK withError: nil]; - } else if(!haveTLK) { - ckkserror("ckksheal", ckks, "CKKS errored examining TLK, triggering move to bad state: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:error]; - return false; + if(![keyset.tlk validTLK:&error]) { + // Something has gone horribly wrong. Enter error state. + ckkserror("ckkskey", ckks, "CKKS claims %@ is not a valid TLK: %@", keyset.tlk, error); + self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSInvalidTLK description:@"Invalid TLK from CloudKit (during heal)" underlying:error]; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; + } + + // This key is our proposed TLK. + if(![keyset.tlk tlkMaterialPresentOrRecoverableViaTLKShare:currentTrustStates + error:&error]) { + // TLK is valid, but not present locally + if(error && [self.deps.lockStateTracker isLockedError:error]) { + ckksnotice("ckkskey", ckks, "Received a TLK(%@), but keybag appears to be locked. Entering a waiting state.", keyset.tlk); + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + } else { + ckksnotice("ckkskey", ckks, "Received a TLK(%@) which we don't have in the local keychain: %@", keyset.tlk, error); + self.error = error; + self.nextState = SecCKKSZoneKeyStateTLKMissing; + } + return CKKSDatabaseTransactionCommit; } if(![self ensureKeyPresent:keyset.tlk]) { - return false; + return CKKSDatabaseTransactionRollback; } if(![self ensureKeyPresent:keyset.classA]) { - return false; + return CKKSDatabaseTransactionRollback; } if(![self ensureKeyPresent:keyset.classC]) { - return false; + return CKKSDatabaseTransactionRollback; } // Seems good to us. Check if we're ready? - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateReady withError: nil]; + self.nextState = self.intendedState; - return true; + return CKKSDatabaseTransactionCommit; }]; } @@ -450,16 +480,29 @@ error = nil; [key unwrapViaKeyHierarchy: &error]; if(error) { + if([ckks.lockStateTracker isLockedError:error]) { + ckkserror("ckksheal", ckks, "Couldn't unwrap key(%@) using key hierarchy due to the lock state: %@", key, error); + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + self.error = error; + return false; + } ckkserror("ckksheal", ckks, "Couldn't unwrap key(%@) using key hierarchy. Keys are broken, quitting: %@", key, error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; + self.error = error; + self.nextState = SecCKKSZoneKeyStateError; self.error = error; return false; } [key saveKeyMaterialToKeychain:&error]; if(error) { + if([ckks.lockStateTracker isLockedError:error]) { + ckkserror("ckksheal", ckks, "Couldn't save key(%@) to keychain due to the lock state: %@", key, error); + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + self.error = error; + return false; + } ckkserror("ckksheal", ckks, "Couldn't save key(%@) to keychain: %@", key, error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; self.error = error; + self.nextState = SecCKKSZoneKeyStateError; return false; } } diff --git a/keychain/ckks/CKKSHealTLKSharesOperation.h b/keychain/ckks/CKKSHealTLKSharesOperation.h index 9dc61050..910cd917 100644 --- a/keychain/ckks/CKKSHealTLKSharesOperation.h +++ b/keychain/ckks/CKKSHealTLKSharesOperation.h @@ -23,18 +23,32 @@ #import #import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ckks/CKKSCurrentKeyPointer.h" +#import "keychain/ot/OctagonStateMachine.h" #if OCTAGON NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; +@class CKKSOperationDependencies; -@interface CKKSHealTLKSharesOperation : CKKSGroupOperation +@interface CKKSHealTLKSharesOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; +- (instancetype)initWithOperationDependencies:(CKKSOperationDependencies*)operationDependencies + ckks:(CKKSKeychainView*)ckks; + + +// For this keyset, who doesn't yet have a CKKSTLKShare for its TLK, shared to their current Octagon keys? +// Note that we really want a record sharing the TLK to ourselves, so this function might return +// a non-empty set even if all peers have the TLK: it wants us to make a record for ourself. +// If you pass in a non-empty set in afterUploading, those records will be included in the calculation. ++ (NSSet* _Nullable)createMissingKeyShares:(CKKSCurrentKeySet*)keyset + trustStates:(NSArray*)trustStates + error:(NSError* __autoreleasing*)errore; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSHealTLKSharesOperation.m b/keychain/ckks/CKKSHealTLKSharesOperation.m index a407f466..bd303afd 100644 --- a/keychain/ckks/CKKSHealTLKSharesOperation.m +++ b/keychain/ckks/CKKSHealTLKSharesOperation.m @@ -38,18 +38,25 @@ @interface CKKSHealTLKSharesOperation () @property NSBlockOperation* cloudkitModifyOperationFinished; -@property CKOperationGroup* ckoperationGroup; @end @implementation CKKSHealTLKSharesOperation +@synthesize intendedState = _intendedState; +@synthesize nextState = _nextState; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { + +- (instancetype)initWithOperationDependencies:(CKKSOperationDependencies*)operationDependencies + ckks:(CKKSKeychainView*)ckks +{ if(self = [super init]) { _ckks = ckks; - _ckoperationGroup = ckoperationGroup; + _deps = operationDependencies; + + _nextState = SecCKKSZoneKeyStateHealTLKSharesFailed; + _intendedState = SecCKKSZoneKeyStateBecomeReady; } return self; } @@ -63,173 +70,286 @@ WEAKIFY(self); - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksshare", ckks, "no CKKS object"); + if(self.cancelled) { + ckksnotice("ckksshare", self.deps.zoneID, "CKKSHealTLKSharesOperation cancelled, quitting"); return; } - if(self.cancelled) { - ckksnotice("ckksshare", ckks, "CKKSHealTLKSharesOperation cancelled, quitting"); + NSArray* trustStates = [self.deps currentTrustStates]; + + NSError* error = nil; + __block CKKSCurrentKeySet* keyset = nil; + + [self.deps.databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{ + keyset = [CKKSCurrentKeySet loadForZone:self.deps.zoneID]; + }]; + + if(keyset.error) { + self.nextState = SecCKKSZoneKeyStateUnhealthy; + self.error = keyset.error; + ckkserror("ckksshare", self.deps.zoneID, "couldn't load current keys: can't fix TLK shares"); return; + } else { + ckksnotice("ckksshare", self.deps.zoneID, "Key set is %@", keyset); } - [ckks dispatchSyncWithAccountKeys: ^bool{ - if(self.cancelled) { - ckksnotice("ckksshare", ckks, "CKKSHealTLKSharesOperation cancelled, quitting"); - return false; + [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventTLKShareProcessing zone:self.deps.zoneID.zoneName]; + + // Okay! Perform the checks. + if(![keyset.tlk loadKeyMaterialFromKeychain:&error] || error) { + // Well, that's no good. We can't share a TLK we don't have. + if([self.deps.lockStateTracker isLockedError: error]) { + ckkserror("ckksshare", self.deps.zoneID, "Keychain is locked: can't fix shares yet: %@", error); + self.nextState = SecCKKSZoneKeyStateBecomeReady; + } else { + ckkserror("ckksshare", self.deps.zoneID, "couldn't load current tlk from keychain: %@", error); + self.nextState = SecCKKSZoneKeyStateUnhealthy; } + return; + } + + NSSet* newShares = [CKKSHealTLKSharesOperation createMissingKeyShares:keyset + trustStates:trustStates + error:&error]; + if(error) { + ckkserror("ckksshare", self.deps.zoneID, "Unable to create shares: %@", error); + self.nextState = SecCKKSZoneKeyStateUnhealthy; + return; + } + + if(newShares.count == 0u) { + ckksnotice("ckksshare", self.deps.zoneID, "Don't believe we need to change any TLKShares, stopping"); + self.nextState = self.intendedState; + return; + } + + keyset.pendingTLKShares = [newShares allObjects]; - NSError* error = nil; + // Let's double-check: if we upload these TLKShares, will the world be right? + BOOL newSharesSufficient = [CKKSHealTLKSharesOperation areNewSharesSufficient:keyset + trustStates:trustStates + error:&error]; + if(!newSharesSufficient || error) { + ckksnotice("ckksshare", self.deps.zoneID, "New shares won't resolve the share issue; erroring to avoid infinite loops"); + self.nextState = SecCKKSZoneKeyStateError; + return; + } + + // Fire up our CloudKit operation! + + NSMutableArray* recordsToSave = [[NSMutableArray alloc] init]; + NSMutableArray* recordIDsToDelete = [[NSMutableArray alloc] init]; + NSMutableDictionary* attemptedRecords = [[NSMutableDictionary alloc] init]; + + ckksnotice("ckksshare", self.deps.zoneID, "Uploading %d new TLKShares", (unsigned int)newShares.count); + for(CKKSTLKShareRecord* share in newShares) { + ckksnotice("ckksshare", self.deps.zoneID, "Uploading TLKShare to %@ (as %@)", share.share.receiverPeerID, share.senderPeerID); + + CKRecord* record = [share CKRecordWithZoneID:self.deps.zoneID]; + [recordsToSave addObject: record]; + attemptedRecords[record.recordID] = record; + } + + // Use the spare operation trick to wait for the CKModifyRecordsOperation to complete + self.cloudkitModifyOperationFinished = [NSBlockOperation named:@"heal-tlkshares-modify-operation-finished" withBlock:^{}]; + [self dependOnBeforeGroupFinished: self.cloudkitModifyOperationFinished]; + + // Get the CloudKit operation ready... + CKModifyRecordsOperation* modifyRecordsOp = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:recordsToSave + recordIDsToDelete:recordIDsToDelete]; + modifyRecordsOp.atomic = YES; + modifyRecordsOp.longLived = NO; + + // very important: get the TLKShares off-device ASAP + modifyRecordsOp.configuration.automaticallyRetryNetworkFailures = NO; + modifyRecordsOp.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; + modifyRecordsOp.configuration.isCloudKitSupportOperation = YES; - CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:ckks.zoneID]; + modifyRecordsOp.group = self.deps.ckoperationGroup; + ckksnotice("ckksshare", self.deps.zoneID, "Operation group is %@", self.deps.ckoperationGroup); - if(keyset.error) { - self.error = keyset.error; - ckkserror("ckksshare", ckks, "couldn't load current keys: can't fix TLK shares"); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateUnhealthy withError:nil]; - return true; + modifyRecordsOp.perRecordCompletionBlock = ^(CKRecord *record, NSError * _Nullable error) { + STRONGIFY(self); + + // These should all fail or succeed as one. Do the hard work in the records completion block. + if(!error) { + ckksnotice("ckksshare", self.deps.zoneID, "Successfully completed upload for record %@", record.recordID.recordName); } else { - ckksnotice("ckksshare", ckks, "Key set is %@", keyset); + ckkserror("ckksshare", self.deps.zoneID, "error on row: %@ %@", record.recordID, error); } + }; + + modifyRecordsOp.modifyRecordsCompletionBlock = ^(NSArray *savedRecords, NSArray *deletedRecordIDs, NSError *error) { + STRONGIFY(self); + + CKKSKeychainView* strongCKKS = self.ckks; + + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + if(error == nil) { + // Success. Persist the records to the CKKS database + ckksnotice("ckksshare", self.deps.zoneID, "Completed TLK Share heal operation with success"); + NSError* localerror = nil; + + // Save the new CKRecords to the database + for(CKRecord* record in savedRecords) { + CKKSTLKShareRecord* savedShare = [[CKKSTLKShareRecord alloc] initWithCKRecord:record]; + bool saved = [savedShare saveToDatabase:&localerror]; + + if(!saved || localerror != nil) { + // erroring means we were unable to save the new TLKShare records to the database. This will cause us to try to reupload them. Fail. + // No recovery from this, really... + ckkserror("ckksshare", self.deps.zoneID, "Couldn't save new TLKShare record to database: %@", localerror); + self.error = localerror; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionCommit; + + } else { + ckksnotice("ckksshare", self.deps.zoneID, "Successfully completed upload for %@", savedShare); + } + } - [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventTLKShareProcessing zone:ckks.zoneName]; - - // Okay! Perform the checks. - if(![keyset.tlk loadKeyMaterialFromKeychain:&error] || error) { - // Well, that's no good. We can't share a TLK we don't have. - if([ckks.lockStateTracker isLockedError: error]) { - ckkserror("ckksshare", ckks, "Keychain is locked: can't fix shares yet: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateReadyPendingUnlock withError:nil]; + // Successfully sharing TLKs means we're now in ready! + self.nextState = SecCKKSZoneKeyStateBecomeReady; } else { - // TODO go to waitfortlk - ckkserror("ckksshare", ckks, "couldn't load current tlk from keychain: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateUnhealthy withError:nil]; + ckkserror("ckksshare", self.deps.zoneID, "Completed TLK Share heal operation with error: %@", error); + [strongCKKS _onqueueCKWriteFailed:error attemptedRecordsChanged:attemptedRecords]; + // Send the key state machine into tlksharesfailed + self.nextState = SecCKKSZoneKeyStateHealTLKSharesFailed; } - return true; - } + return CKKSDatabaseTransactionCommit; + }]; - NSSet* newShares = [ckks _onqueueCreateMissingKeyShares:keyset.tlk - error:&error]; - if(error) { - ckkserror("ckksshare", ckks, "Unable to create shares: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateUnhealthy withError:nil]; - return false; - } + // Notify that we're done + [self.operationQueue addOperation: self.cloudkitModifyOperationFinished]; + }; + + [self.ckks.database addOperation:modifyRecordsOp]; +} - if(newShares.count == 0u) { - ckksnotice("ckksshare", ckks, "Don't believe we need to change any TLKShares, stopping"); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateReady withError:nil]; - return true; +- (void)cancel { + [self.cloudkitModifyOperationFinished cancel]; + [super cancel]; +} + ++ (BOOL)areNewSharesSufficient:(CKKSCurrentKeySet*)keyset + trustStates:(NSArray*)trustStates + error:(NSError* __autoreleasing*)error +{ + for(CKKSPeerProviderState* trustState in trustStates) { + NSError* localError = nil; + NSSet>* peersMissingShares = [trustState findPeersMissingTLKSharesFor:keyset + error:&localError]; + if(peersMissingShares == nil || localError) { + if(trustState.essential) { + if(error) { + *error = localError; + } + return NO; + } else { + ckksnotice("ckksshare", keyset.tlk, "Failed to find peers for nonessential system: %@", trustState); + // Not a hard failure. + } } - // Let's double-check: if we upload these TLKShares, will the world be right? - BOOL newSharesSufficient = [ckks _onqueueAreNewSharesSufficient:newShares - currentTLK:keyset.tlk - error:&error]; - if(!newSharesSufficient || error) { - ckksnotice("ckksshare", ckks, "New shares won't resolve the share issue; erroring to avoid infinite loops"); - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:error]; - return true; + if(peersMissingShares.count > 0) { + ckksnotice("ckksshare", keyset.tlk, "New share set is missing shares for peers: %@", peersMissingShares); + return NO; } + } - // Fire up our CloudKit operation! + return YES; +} - NSMutableArray* recordsToSave = [[NSMutableArray alloc] init]; - NSMutableArray* recordIDsToDelete = [[NSMutableArray alloc] init]; - NSMutableDictionary* attemptedRecords = [[NSMutableDictionary alloc] init]; - for(CKKSTLKShareRecord* share in newShares) { - CKRecord* record = [share CKRecordWithZoneID:ckks.zoneID]; - [recordsToSave addObject: record]; - attemptedRecords[record.recordID] = record; - } ++ (NSSet* _Nullable)createMissingKeyShares:(CKKSCurrentKeySet*)keyset + trustStates:(NSArray*)trustStates + error:(NSError* __autoreleasing*)error +{ + NSError* localerror = nil; + NSSet* newShares = nil; - // Use the spare operation trick to wait for the CKModifyRecordsOperation to complete - self.cloudkitModifyOperationFinished = [NSBlockOperation named:@"heal-tlkshares-modify-operation-finished" withBlock:^{}]; - [self dependOnBeforeGroupFinished: self.cloudkitModifyOperationFinished]; + // If any one of our trust states succeed, this function doesn't have an error + for(CKKSPeerProviderState* trustState in trustStates) { + NSError* stateError = nil; + NSSet* newTrustShares = [self createMissingKeyShares:keyset + peers:trustState + error:&stateError]; - // Get the CloudKit operation ready... - CKModifyRecordsOperation* modifyRecordsOp = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:recordsToSave - recordIDsToDelete:recordIDsToDelete]; - modifyRecordsOp.atomic = YES; - modifyRecordsOp.longLived = NO; - // very important: get the TLKShares off-device ASAP - modifyRecordsOp.configuration.automaticallyRetryNetworkFailures = NO; - modifyRecordsOp.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; - modifyRecordsOp.configuration.isCloudKitSupportOperation = YES; + if(newTrustShares && !stateError) { + newShares = newShares ? [newShares setByAddingObjectsFromSet:newTrustShares] : newTrustShares; + } else { + ckksnotice("ckksshare", keyset.tlk, "Unable to create shares for trust set %@: %@", trustState, stateError); + if(localerror == nil) { + localerror = stateError; + } + } + } - modifyRecordsOp.group = self.ckoperationGroup; - ckksnotice("ckksshare", ckks, "Operation group is %@", self.ckoperationGroup); + // Only report an error if none of the trust states were able to succeed + if(newShares) { + return newShares; + } else { + if(error && localerror) { + *error = localerror; + } + return nil; + } +} - modifyRecordsOp.perRecordCompletionBlock = ^(CKRecord *record, NSError * _Nullable error) { - STRONGIFY(self); - CKKSKeychainView* blockCKKS = self.ckks; ++ (NSSet*)createMissingKeyShares:(CKKSCurrentKeySet*)keyset + peers:(CKKSPeerProviderState*)trustState + error:(NSError* __autoreleasing*)error +{ + NSError* localerror = nil; + if(![keyset.tlk ensureKeyLoaded:&localerror]) { + ckkserror("ckksshare", keyset.tlk, "TLK not loaded; cannot make shares for peers: %@", localerror); + if(error) { + *error = localerror; + } + return nil; + } - // These should all fail or succeed as one. Do the hard work in the records completion block. - if(!error) { - ckksnotice("ckksshare", blockCKKS, "Successfully completed upload for record %@", record.recordID.recordName); - } else { - ckkserror("ckksshare", blockCKKS, "error on row: %@ %@", record.recordID, error); - } - }; - - modifyRecordsOp.modifyRecordsCompletionBlock = ^(NSArray *savedRecords, NSArray *deletedRecordIDs, NSError *error) { - STRONGIFY(self); - CKKSKeychainView* strongCKKS = self.ckks; - if(!self) { - secerror("ckks: received callback for released object"); - return; - } + NSSet>* remainingPeers = [trustState findPeersMissingTLKSharesFor:keyset + error:&localerror]; + if(!remainingPeers) { + ckkserror("ckksshare", keyset.tlk, "Unable to find peers missing TLKShares: %@", localerror); + if(error) { + *error = localerror; + } + return nil; + } - [strongCKKS dispatchSyncWithAccountKeys: ^bool { - if(error == nil) { - // Success. Persist the records to the CKKS database - ckksnotice("ckksshare", strongCKKS, "Completed TLK Share heal operation with success"); - NSError* localerror = nil; - - // Save the new CKRecords to the database - for(CKRecord* record in savedRecords) { - CKKSTLKShareRecord* savedShare = [[CKKSTLKShareRecord alloc] initWithCKRecord:record]; - bool saved = [savedShare saveToDatabase:&localerror]; - - if(!saved || localerror != nil) { - // erroring means we were unable to save the new TLKShare records to the database. This will cause us to try to reupload them. Fail. - // No recovery from this, really... - ckkserror("ckksshare", strongCKKS, "Couldn't save new TLKShare record to database: %@", localerror); - [strongCKKS _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError: localerror]; - return true; - - } else { - ckksnotice("ckksshare", strongCKKS, "Successfully completed upload for %@", savedShare); - } - } + NSMutableSet* newShares = [NSMutableSet set]; - // Successfully sharing TLKs means we're now in ready! - [strongCKKS _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateReady withError: nil]; - } else { - ckkserror("ckksshare", strongCKKS, "Completed TLK Share heal operation with error: %@", error); - [strongCKKS _onqueueCKWriteFailed:error attemptedRecordsChanged:attemptedRecords]; - // Send the key state machine into tlksharesfailed - [strongCKKS _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateHealTLKSharesFailed withError: nil]; - } - return true; - }]; + for(id peer in remainingPeers) { + if(!peer.publicEncryptionKey) { + ckksnotice("ckksshare", keyset.tlk, "No need to make TLK for %@; they don't have any encryption keys", peer); + continue; + } - // Notify that we're done - [self.operationQueue addOperation: self.cloudkitModifyOperationFinished]; - }; + // Create a share for this peer. + ckksnotice("ckksshare", keyset.tlk, "Creating share of %@ as %@ for %@", keyset.tlk, trustState.currentSelfPeers.currentSelf, peer); + CKKSTLKShareRecord* newShare = [CKKSTLKShareRecord share:keyset.tlk + as:trustState.currentSelfPeers.currentSelf + to:peer + epoch:-1 + poisoned:0 + error:&localerror]; + + if(localerror) { + ckkserror("ckksshare", keyset.tlk, "Couldn't create new share for %@: %@", peer, localerror); + if(error) { + *error = localerror; + } + return nil; + } - [ckks.database addOperation: modifyRecordsOp]; - return true; - }]; -} + [newShares addObject: newShare]; + } -- (void)cancel { - [self.cloudkitModifyOperationFinished cancel]; - [super cancel]; + return newShares; } @end; diff --git a/keychain/ckks/CKKSIncomingQueueEntry.h b/keychain/ckks/CKKSIncomingQueueEntry.h index 8d425b21..64e36437 100644 --- a/keychain/ckks/CKKSIncomingQueueEntry.h +++ b/keychain/ckks/CKKSIncomingQueueEntry.h @@ -46,8 +46,9 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype _Nullable)tryFromDatabase:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (NSArray* _Nullable)fetch:(ssize_t)n - startingAtUUID:(NSString*)uuid + startingAtUUID:(NSString* _Nullable)uuid state:(NSString*)state + action:(NSString* _Nullable)action zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; diff --git a/keychain/ckks/CKKSIncomingQueueEntry.m b/keychain/ckks/CKKSIncomingQueueEntry.m index 0aa13111..4e3e51fd 100644 --- a/keychain/ckks/CKKSIncomingQueueEntry.m +++ b/keychain/ckks/CKKSIncomingQueueEntry.m @@ -84,9 +84,11 @@ + (NSArray*)fetch:(ssize_t)n startingAtUUID:(NSString*)uuid state:(NSString*)state + action:(NSString* _Nullable)action zoneID:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { NSMutableDictionary* whereDict = [@{@"state": CKKSNilToNSNull(state), @"ckzone":CKKSNilToNSNull(zoneID.zoneName)} mutableCopy]; + whereDict[@"action"] = action; if(uuid) { whereDict[@"UUID"] = [CKKSSQLWhereValue op:CKKSSQLWhereComparatorGreaterThan value:uuid]; } diff --git a/keychain/ckks/CKKSIncomingQueueOperation.h b/keychain/ckks/CKKSIncomingQueueOperation.h index 8b897285..1dd41023 100644 --- a/keychain/ckks/CKKSIncomingQueueOperation.h +++ b/keychain/ckks/CKKSIncomingQueueOperation.h @@ -24,23 +24,38 @@ #import #import "keychain/ckks/CKKSGroupOperation.h" #if OCTAGON + +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; @class CKKSItem; -@interface CKKSIncomingQueueOperation : CKKSResultOperation +@interface CKKSIncomingQueueOperation : CKKSResultOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; // Set this to true if this instance of CKKSIncomingQueueOperation // should error if it can't process class A items due to the keychain being locked. @property bool errorOnClassAFailure; +// Set this to true if you're pretty sure that the policy set on the CKKS object +// should be considered authoritative, and items that do not match this policy should +// be moved. +@property bool handleMismatchedViewItems; + @property size_t successfulItemsProcessed; @property size_t errorItemsProcessed; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks errorOnClassAFailure:(bool)errorOnClassAFailure; +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intending + errorState:(OctagonState*)errorState + errorOnClassAFailure:(bool)errorOnClassAFailure + handleMismatchedViewItems:(bool)handleMismatchedViewItems; // Use this to turn a CKKS item into a keychain dictionary suitable for keychain insertion + (NSDictionary* _Nullable)decryptCKKSItemToAttributes:(CKKSItem*)item error:(NSError**)error; diff --git a/keychain/ckks/CKKSIncomingQueueOperation.m b/keychain/ckks/CKKSIncomingQueueOperation.m index e5c96b49..b025a03c 100644 --- a/keychain/ckks/CKKSIncomingQueueOperation.m +++ b/keychain/ckks/CKKSIncomingQueueOperation.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2016-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,23 +21,24 @@ * @APPLE_LICENSE_HEADER_END@ */ -#import "CKKSKeychainView.h" -#import "CKKSIncomingQueueOperation.h" -#import "CKKSIncomingQueueEntry.h" -#import "CKKSItemEncrypter.h" -#import "CKKSOutgoingQueueEntry.h" -#import "CKKSKey.h" -#import "CKKSManifest.h" -#import "CKKSAnalytics.h" -#import "CKKSPowerCollection.h" +#import "keychain/analytics/CKKSPowerCollection.h" +#import "keychain/ckks/CKKSAnalytics.h" #import "keychain/ckks/CKKSCurrentItemPointer.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSIncomingQueueOperation.h" +#import "keychain/ckks/CKKSItemEncrypter.h" +#import "keychain/ckks/CKKSKey.h" +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CKKSStates.h" +#import "keychain/ckks/CKKSViewManager.h" +#import "keychain/ckks/CloudKitCategories.h" #import "keychain/ot/ObjCImprovements.h" #include "keychain/securityd/SecItemServer.h" #include "keychain/securityd/SecItemDb.h" #include -#include #import #if OCTAGON @@ -46,17 +47,32 @@ @property bool newOutgoingEntries; @property bool pendingClassAEntries; @property bool missingKey; + +@property NSMutableSet* viewsToScan; @end @implementation CKKSIncomingQueueOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks errorOnClassAFailure:(bool)errorOnClassAFailure { + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intending + errorState:(OctagonState*)errorState + errorOnClassAFailure:(bool)errorOnClassAFailure + handleMismatchedViewItems:(bool)handleMismatchedViewItems +{ if(self = [super init]) { + _deps = dependencies; _ckks = ckks; + _intendedState = intending; + _nextState = errorState; + // Can't process unless we have a reasonable key hierarchy. if(ckks.keyStateReadyDependency) { [self addDependency: ckks.keyStateReadyDependency]; @@ -67,95 +83,51 @@ _errorOnClassAFailure = errorOnClassAFailure; _pendingClassAEntries = false; - [self linearDependencies:ckks.incomingQueueOperations]; - - if ([CKKSManifest shouldSyncManifests]) { - WEAKIFY(self); - CKKSResultOperation* updateManifestOperation = [CKKSResultOperation operationWithBlock:^{ - STRONGIFY(self); - CKKSKeychainView* strongCKKS = self.ckks; - __block NSError* error = nil; - if (!strongCKKS || !self) { - ckkserror("ckksincoming", strongCKKS, "update manifest operation fired for released object"); - return; - } + _handleMismatchedViewItems = handleMismatchedViewItems; - [strongCKKS dispatchSyncWithAccountKeys:^bool{ - strongCKKS.latestManifest = [CKKSManifest latestTrustedManifestForZone:strongCKKS.zoneName error:&error]; - if (error) { - self.error = error; - ckkserror("ckksincoming", strongCKKS, "failed to get latest manifest: %@", error); - return false; - } - else { - return true; - } - }]; - }]; - updateManifestOperation.name = @"update-manifest-operation"; + _viewsToScan = [NSMutableSet set]; - [ckks scheduleOperation:updateManifestOperation]; - [self addSuccessDependency:updateManifestOperation]; - } + [self linearDependencies:ckks.incomingQueueOperations]; } return self; } -- (bool)processNewCurrentItemPointers:(NSArray*)queueEntries withManifest:(CKKSManifest*)manifest egoManifest:(CKKSEgoManifest*)egoManifest +- (bool)processNewCurrentItemPointers:(NSArray*)queueEntries { - CKKSKeychainView* ckks = self.ckks; - NSError* error = nil; for(CKKSCurrentItemPointer* p in queueEntries) { @autoreleasepool { - if ([CKKSManifest shouldSyncManifests]) { - if (![manifest validateCurrentItem:p withError:&error]) { - ckkserror("ckksincoming", ckks, "Unable to validate current item pointer (%@) against manifest (%@)", p, manifest); - if ([CKKSManifest shouldEnforceManifests]) { - return false; - } - } - } - p.state = SecCKKSProcessedStateLocal; [p saveToDatabase:&error]; - ckksnotice("ckkspointer", ckks, "Saving new current item pointer: %@", p); + ckksnotice("ckkspointer", self.deps.zoneID, "Saving new current item pointer: %@", p); if(error) { - ckkserror("ckksincoming", ckks, "Error saving new current item pointer: %@ %@", error, p); + ckkserror("ckksincoming", self.deps.zoneID, "Error saving new current item pointer: %@ %@", error, p); } - - // Schedule a view change notification - [ckks.notifyViewChangedScheduler trigger]; } } if(queueEntries.count > 0) { - // Schedule a view change notification - [ckks.notifyViewChangedScheduler trigger]; + [self.deps.notifyViewChangedScheduler trigger]; } return (error == nil); } -- (bool)processQueueEntries:(NSArray*)queueEntries withManifest:(CKKSManifest*)manifest egoManifest:(CKKSEgoManifest*)egoManifest +- (bool)processQueueEntries:(NSArray*)queueEntries { CKKSKeychainView* ckks = self.ckks; + dispatch_assert_queue(ckks.queue); NSMutableArray* newOrChangedRecords = [[NSMutableArray alloc] init]; NSMutableArray* deletedRecordIDs = [[NSMutableArray alloc] init]; for(id entry in queueEntries) { @autoreleasepool { - if(self.cancelled) { - ckksnotice("ckksincoming", ckks, "CKKSIncomingQueueOperation cancelled, quitting"); - return false; - } - NSError* error = nil; CKKSIncomingQueueEntry* iqe = (CKKSIncomingQueueEntry*) entry; - ckksnotice("ckksincoming", ckks, "ready to process an incoming queue entry: %@ %@ %@", iqe, iqe.uuid, iqe.action); + ckksnotice("ckksincoming", self.deps.zoneID, "ready to process an incoming queue entry: %@ %@ %@", iqe, iqe.uuid, iqe.action); // Note that we currently unencrypt the item before deleting it, instead of just deleting it // This finds the class, which is necessary for the deletion process. We could just try to delete @@ -163,10 +135,10 @@ NSDictionary* attributes = [CKKSIncomingQueueOperation decryptCKKSItemToAttributes:iqe.item error:&error]; if(!attributes || error) { - if([ckks.lockStateTracker isLockedError:error]) { + if([self.deps.lockStateTracker isLockedError:error]) { NSError* localerror = nil; - ckkserror("ckksincoming", ckks, "Keychain is locked; can't decrypt IQE %@", iqe); - CKKSKey* key = [CKKSKey tryFromDatabase:iqe.item.parentKeyUUID zoneID:ckks.zoneID error:&localerror]; + ckkserror("ckksincoming", self.deps.zoneID, "Keychain is locked; can't decrypt IQE %@", iqe); + CKKSKey* key = [CKKSKey tryFromDatabase:iqe.item.parentKeyUUID zoneID:self.deps.zoneID error:&localerror]; if(localerror || ([key.keyclass isEqualToString:SecCKKSKeyClassA] && self.errorOnClassAFailure)) { self.error = error; } @@ -177,11 +149,12 @@ } } else if ([error.domain isEqualToString:@"securityd"] && error.code == errSecItemNotFound) { - ckkserror("ckksincoming", ckks, "Coudn't find key in keychain; will attempt to poke key hierarchy: %@", error) + ckkserror("ckksincoming", self.deps.zoneID, "Coudn't find key in keychain; will attempt to poke key hierarchy: %@", error) self.missingKey = true; + self.error = error; } else { - ckkserror("ckksincoming", ckks, "Couldn't decrypt IQE %@ for some reason: %@", iqe, error); + ckkserror("ckksincoming", self.deps.zoneID, "Couldn't decrypt IQE %@ for some reason: %@", iqe, error); self.error = error; } self.errorItemsProcessed += 1; @@ -193,7 +166,7 @@ self.error = [NSError errorWithDomain:@"securityd" code:errSecInternalError userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Item did not have a reasonable class: %@", classStr]}]; - ckkserror("ckksincoming", ckks, "Synced item seems wrong: %@", self.error); + ckkserror("ckksincoming", self.deps.zoneID, "Synced item seems wrong: %@", self.error); self.errorItemsProcessed += 1; continue; } @@ -201,72 +174,130 @@ const SecDbClass * classP = !classStr ? NULL : kc_class_with_name((__bridge CFStringRef) classStr); if(!classP) { - ckkserror("ckksincoming", ckks, "unknown class in object: %@ %@", classStr, iqe); + ckkserror("ckksincoming", self.deps.zoneID, "unknown class in object: %@ %@", classStr, iqe); iqe.state = SecCKKSStateError; [iqe saveToDatabase:&error]; if(error) { - ckkserror("ckksincoming", ckks, "Couldn't save errored IQE to database: %@", error); + ckkserror("ckksincoming", self.deps.zoneID, "Couldn't save errored IQE to database: %@", error); self.error = error; } self.errorItemsProcessed += 1; continue; } - if([iqe.action isEqualToString: SecCKKSActionAdd] || [iqe.action isEqualToString: SecCKKSActionModify]) { - BOOL requireManifestValidation = [CKKSManifest shouldEnforceManifests]; - BOOL manifestValidatesItem = [manifest validateItem:iqe.item withError:&error]; - - if (!requireManifestValidation || manifestValidatesItem) { - [self _onqueueHandleIQEChange: iqe attributes:attributes class:classP]; - [newOrChangedRecords addObject:[iqe.item CKRecordWithZoneID:ckks.zoneID]]; - } - else { - ckkserror("ckksincoming", ckks, "could not validate incoming item against manifest with error: %@", error); - if (![self _onqueueUpdateIQE:iqe withState:SecCKKSStateUnauthenticated error:&error]) { - ckkserror("ckksincoming", ckks, "failed to save incoming item back to database in unauthenticated state with error: %@", error); - return false; - } - self.errorItemsProcessed += 1; - continue; - } - } else if ([iqe.action isEqualToString: SecCKKSActionDelete]) { - BOOL requireManifestValidation = [CKKSManifest shouldEnforceManifests]; - BOOL manifestValidatesDelete = ![manifest itemUUIDExistsInManifest:iqe.uuid]; - - if (!requireManifestValidation || manifestValidatesDelete) { - // if the item does not exist in the latest manifest, we're good to delete it - [self _onqueueHandleIQEDelete: iqe class:classP]; - [deletedRecordIDs addObject:[[CKRecordID alloc] initWithRecordName:iqe.uuid zoneID:ckks.zoneID]]; - } - else { - // if the item DOES exist in the manifest, we can't trust the deletion - ckkserror("ckksincoming", ckks, "could not validate incoming item deletion against manifest"); - if (![self _onqueueUpdateIQE:iqe withState:SecCKKSStateUnauthenticated error:&error]) { - ckkserror("ckksincoming", ckks, "failed to save incoming item deletion back to database in unauthenticated state with error: %@", error); + NSString* intendedView = [self.deps.syncingPolicy mapDictionaryToView:attributes]; + if(![self.deps.zoneID.zoneName isEqualToString:intendedView]) { + if(self.handleMismatchedViewItems) { + [self _onqueueHandleMismatchedViewItem:iqe + secDbClass:classP + attributes:attributes + intendedView:intendedView]; + } else { + ckksnotice("ckksincoming", ckks, "Received an item (%@), but our current policy claims it should be in view %@", iqe.uuid, intendedView); + [self _onqueueUpdateIQE:iqe withState:SecCKKSStateMismatchedView error:&error]; + if(error) { + ckkserror("ckksincoming", ckks, "Couldn't save mismatched IQE to database: %@", error); self.errorItemsProcessed += 1; - return false; + self.error = error; } + + [ckks receivedItemForWrongView]; } + continue; + } + + if([iqe.action isEqualToString: SecCKKSActionAdd] || [iqe.action isEqualToString: SecCKKSActionModify]) { + [self _onqueueHandleIQEChange:iqe + attributes:attributes + class:classP + sortedForThisView:YES]; + [newOrChangedRecords addObject:[iqe.item CKRecordWithZoneID:self.deps.zoneID]]; + + } else if ([iqe.action isEqualToString: SecCKKSActionDelete]) { + [self _onqueueHandleIQEDelete: iqe class:classP]; + [deletedRecordIDs addObject:[[CKRecordID alloc] initWithRecordName:iqe.uuid zoneID:self.deps.zoneID]]; } } } if(newOrChangedRecords.count > 0 || deletedRecordIDs > 0) { // Schedule a view change notification - [ckks.notifyViewChangedScheduler trigger]; + [self.deps.notifyViewChangedScheduler trigger]; } if(self.missingKey) { - [ckks.pokeKeyStateMachineScheduler trigger]; + // TODO: will be removed when the IncomingQueueOperation is part of the state machine + [ckks.stateMachine _onqueuePokeStateMachine]; + self.nextState = SecCKKSZoneKeyStateUnhealthy; } - if ([CKKSManifest shouldSyncManifests]) { - [egoManifest updateWithNewOrChangedRecords:newOrChangedRecords deletedRecordIDs:deletedRecordIDs]; - } return true; } +- (void)_onqueueHandleMismatchedViewItem:(CKKSIncomingQueueEntry*)iqe + secDbClass:(const SecDbClass*)secDbClass + attributes:(NSDictionary*)attributes + intendedView:(NSString* _Nullable)intendedView +{ + ckksnotice("ckksincoming", self.deps.zoneID, "Received an item (%@), which should be in view %@", iqe.uuid, intendedView); + + // Here's the plan: + // + // If this is an add or a modify, we will execute the modification _if we do not currently have this item_. + // Then, ask the view that should handle this item to scan. + // + // When, we will leave the CloudKit record in the existing 'wrong' view. + // This will allow garbage to collect, but should prevent item loss in complicated multi-device scenarios. + // + // If this is a deletion, then we will inspect the other zone's current on-disk state. If it knows about the item, + // we will ignore the deletion from this view. Otherwise, we will proceed with the deletion. + // Note that the deletion approach already ensures that the UUID of the deleted item matches the UUID of the CKRecord. + // This protects against an item being in multiple views, and deleted from only one. + + if([iqe.action isEqualToString:SecCKKSActionAdd] || [iqe.action isEqualToString:SecCKKSActionModify]) { + CFErrorRef cferror = NULL; + SecDbItemRef item = SecDbItemCreateWithAttributes(NULL, secDbClass, (__bridge CFDictionaryRef) attributes, KEYBAG_DEVICE, &cferror); + + if(!item || cferror) { + ckkserror("ckksincoming", self.deps.zoneID, "Unable to create SecDbItemRef from IQE: %@", cferror); + return; + } + + [self _onqueueHandleIQEChange:iqe item:item sortedForThisView:NO]; + [self.viewsToScan addObject:intendedView]; + + CFReleaseNull(item); + + } else if ([iqe.action isEqualToString:SecCKKSActionDelete]) { + NSError* loadError = nil; + + CKRecordZoneID* otherZoneID = [[CKRecordZoneID alloc] initWithZoneName:intendedView ownerName:CKCurrentUserDefaultName]; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:iqe.uuid zoneID:otherZoneID error:&loadError]; + + if(!ckme || loadError) { + ckksnotice("ckksincoming", self.deps.zoneID, "Unable to load CKKSMirrorEntry from database* %@", loadError); + return; + } + + if(ckme) { + ckksnotice("ckksincoming", self.deps.zoneID, "Other view (%@) already knows about this item, dropping incoming queue entry: %@", intendedView, ckme); + NSError* saveError = nil; + [iqe deleteFromDatabase:&saveError]; + if(saveError) { + ckkserror("ckksincoming", self.deps.zoneID, "Unable to delete IQE: %@", saveError); + } + + } else { + ckksnotice("ckksincoming", self.deps.zoneID, "Other view (%@) does not know about this item; processing delete for %@", intendedView, iqe); + [self _onqueueHandleIQEDelete:iqe class:secDbClass]; + } + + } else { + // We don't recognize this action. Do nothing. + } +} + + (NSDictionary* _Nullable)decryptCKKSItemToAttributes:(CKKSItem*)item error:(NSError**)error { NSMutableDictionary* attributes = [[CKKSItemEncrypter decryptItemToDictionary:item error:error] mutableCopy]; @@ -313,11 +344,13 @@ return true; } -- (void) main { - // Synchronous, on some thread. Get back on the CKKS queue for thread-safety. +- (void)main +{ CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksincoming", ckks, "no CKKS object"); + + if(!ckks.itemSyncingEnabled) { + ckkserror("ckksincoming", self.deps.zoneID, "Item syncing for this view is disabled"); + self.nextState = self.intendedState; return; } @@ -325,247 +358,329 @@ self.completionBlock = ^(void) { STRONGIFY(self); if (!self) { - ckkserror("ckksincoming", ckks, "received callback for released object"); + ckkserror("ckksincoming", self.deps.zoneID, "received callback for released object"); return; } CKKSAnalytics* logger = [CKKSAnalytics logger]; if (!self.error) { - [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassC inView:ckks]; + [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassC zoneName:self.deps.zoneID.zoneName]; + if (!self.pendingClassAEntries) { - [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassA inView:ckks]; + [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassA zoneName:self.deps.zoneID.zoneName]; } } else { [logger logRecoverableError:self.error forEvent:self.errorOnClassAFailure ? CKKSEventProcessIncomingQueueClassA : CKKSEventProcessIncomingQueueClassC - inView:ckks + zoneName:self.deps.zoneID.zoneName withAttributes:NULL]; } }; - __block bool errored = false; - [ckks dispatchSync: ^bool{ - if(self.cancelled) { - ckksnotice("ckksincoming", ckks, "CKKSIncomingQueueOperation cancelled, quitting"); - return false; - } - ckks.lastIncomingQueueOperation = self; + ckksnotice("ckksincoming", self.deps.zoneID, "Processing incoming queue"); - ckksnotice("ckksincoming", ckks, "Processing incoming queue"); + // First, process all item deletions. + // Then, process all modifications and additions. + // Therefore, if there's both a delete and a re-add of a single Primary Key item in the queue, + // we should end up with the item still existing in tthe keychain afterward. + // But, since we're dropping off the queue inbetween, we might accidentally tell our clients that + // their item doesn't exist. Fixing that would take quite a bit of complexity and memory. - if ([CKKSManifest shouldSyncManifests]) { - if (!ckks.latestManifest) { - // Until we can make manifests in our unit tests, we can't abort here - ckkserror("ckksincoming", ckks, "no manifest in ckks"); - } - if (!ckks.egoManifest) { - ckkserror("ckksincoming", ckks, "no ego manifest in ckks"); - } - } - - bool ok = true; // Should commit transaction? - __block NSError* error = nil; + BOOL success = [self loadAndProcessEntriesWithActionFilter:SecCKKSActionDelete]; + if(!success) { + ckksnotice("ckksincoming", self.deps.zoneID, "Early-exiting from IncomingQueueOperation (after processing deletes): %@", self.error); + return; + } - if ([CKKSManifest shouldSyncManifests]) { - NSInteger unauthenticatedItemCount = [CKKSIncomingQueueEntry countByState:SecCKKSStateUnauthenticated zone:ckks.zoneID error:&error]; - if (error || unauthenticatedItemCount < 0) { - ckkserror("ckksincoming", ckks, "Error fetching incoming queue state counts: %@", error); - self.error = error; - return false; - } + success = [self loadAndProcessEntriesWithActionFilter:nil]; + if(!success) { + ckksnotice("ckksincoming", self.deps.zoneID, "Early-exiting from IncomingQueueOperation (after processing all incoming entries): %@", self.error); + return; + } - // take any existing unauthenticated entries and put them back in the new state - NSArray* unauthenticatedEntries = nil; - NSString* lastMaxUUID = nil; - NSInteger numEntriesProcessed = 0; - while (numEntriesProcessed < unauthenticatedItemCount && (unauthenticatedEntries == nil || unauthenticatedEntries.count == SecCKKSIncomingQueueItemsAtOnce)) { - if(self.cancelled) { - ckksnotice("ckksincoming", ckks, "CKKSIncomingQueueOperation cancelled, quitting"); - return false; - } + ckksnotice("ckksincoming", self.deps.zoneID, "Processed %lu items in incoming queue (%lu errors)", (unsigned long)self.successfulItemsProcessed, (unsigned long)self.errorItemsProcessed); - unauthenticatedEntries = [CKKSIncomingQueueEntry fetch:SecCKKSIncomingQueueItemsAtOnce - startingAtUUID:lastMaxUUID - state:SecCKKSStateUnauthenticated - zoneID:ckks.zoneID - error:&error]; - if (error) { - ckkserror("ckksincoming", ckks, "Error fetching unauthenticated queue records: %@", error); - self.error = error; - return false; - } - - if (unauthenticatedEntries.count == 0) { - ckksinfo("ckksincoming", ckks, "No unauthenticated entries in incoming queue to process"); - break; - } + if(![self fixMismatchedViewItems]) { + ckksnotice("ckksincoming", ckks, "Early-exiting from IncomingQueueOperation due to failure fixing mismatched items"); + return; + } - for (CKKSIncomingQueueEntry* unauthenticatedEntry in unauthenticatedEntries) { - if (![self _onqueueUpdateIQE:unauthenticatedEntry withState:SecCKKSStateNew error:&error]) { - ckkserror("ckksincoming", ckks, "Error saving unauthenticated entry back to new state: %@", error); - self.error = error; - return false; - } + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; - lastMaxUUID = ([lastMaxUUID compare:unauthenticatedEntry.uuid] == NSOrderedDescending) ? lastMaxUUID : unauthenticatedEntry.uuid; - } + NSArray* newCIPs = [CKKSCurrentItemPointer remoteItemPointers:self.deps.zoneID error:&error]; + if(error || !newCIPs) { + ckkserror("ckksincoming", self.deps.zoneID, "Could not load remote item pointers: %@", error); + } else { + if (![self processNewCurrentItemPointers:newCIPs]) { + return CKKSDatabaseTransactionRollback; } + ckksnotice("ckksincoming", self.deps.zoneID, "Processed %lu items in CIP queue", (unsigned long)newCIPs.count); } - errored = !ok; - return ok; + + return CKKSDatabaseTransactionCommit; }]; - if(errored) { - ckksnotice("ckksincoming", ckks, "Early-exiting from IncomingQueueOperation"); - return; + if(self.newOutgoingEntries) { + //[self.deps.flagHandler handleFlag:CKKSFlagProcessOutgoingQueue]; + [ckks processOutgoingQueue:[CKOperationGroup CKKSGroupWithName:@"incoming-queue-response"]]; + } + + if(self.pendingClassAEntries) { + [ckks processIncomingQueueAfterNextUnlock]; + //OctagonPendingFlag* whenUnlocked = [[OctagonPendingFlag alloc] initWithFlag:CKKSFlagProcessIncomingQueue + // conditions:OctagonPendingConditionsDeviceUnlocked]; + //[self.deps.flagHandler handlePendingFlag:whenUnlocked]; + } + + for(NSString* viewName in self.viewsToScan) { + CKKSKeychainView* view = [[CKKSViewManager manager] findView:viewName]; + ckksnotice("ckksincoming", ckks, "Requesting scan for %@ (%@)", view, viewName); + [view scanLocalItems:@"policy-mismatch"]; } + self.nextState = self.intendedState; +} + +- (BOOL)loadAndProcessEntriesWithActionFilter:(NSString* _Nullable)actionFilter +{ + __block bool errored = false; + // Now for the tricky bit: take and drop the account queue for each batch of queue entries // This is for peak memory concerns, but also to allow keychain API clients to make changes while we're processing many items // Note that IncomingQueueOperations are no longer transactional: they can partially succeed. This might make them harder to reason about. __block NSUInteger lastCount = SecCKKSIncomingQueueItemsAtOnce; __block NSString* lastMaxUUID = nil; + id databaseProvider = self.deps.databaseProvider; + while(lastCount == SecCKKSIncomingQueueItemsAtOnce) { - [ckks dispatchSync: ^bool{ + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSArray * queueEntries = nil; if(self.cancelled) { - ckksnotice("ckksincoming", ckks, "CKKSIncomingQueueOperation cancelled, quitting"); + ckksnotice("ckksincoming", self.deps.zoneID, "CKKSIncomingQueueOperation cancelled, quitting"); errored = true; - return false; + return CKKSDatabaseTransactionRollback; } NSError* error = nil; - queueEntries = [CKKSIncomingQueueEntry fetch: SecCKKSIncomingQueueItemsAtOnce + queueEntries = [CKKSIncomingQueueEntry fetch:SecCKKSIncomingQueueItemsAtOnce startingAtUUID:lastMaxUUID state:SecCKKSStateNew - zoneID:ckks.zoneID - error: &error]; + action:actionFilter + zoneID:self.deps.zoneID + error:&error]; if(error != nil) { - ckkserror("ckksincoming", ckks, "Error fetching incoming queue records: %@", error); + ckkserror("ckksincoming", self.deps.zoneID, "Error fetching incoming queue records: %@", error); self.error = error; - errored = true; - return false; + return CKKSDatabaseTransactionRollback; } lastCount = queueEntries.count; if([queueEntries count] == 0) { // Nothing to do! exit. - ckksnotice("ckksincoming", ckks, "Nothing in incoming queue to process"); - return true; + ckksinfo("ckksincoming", self.deps.zoneID, "Nothing in incoming queue to process (filter: %@)", actionFilter); + return CKKSDatabaseTransactionCommit; } - [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventOutgoingQueue zone:ckks.zoneName count:[queueEntries count]]; + [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventIncommingQueue zone:self.deps.zoneID.zoneName count:[queueEntries count]]; - if (![self processQueueEntries:queueEntries withManifest:ckks.latestManifest egoManifest:ckks.egoManifest]) { - ckksnotice("ckksincoming", ckks, "processQueueEntries didn't complete successfully"); + if (![self processQueueEntries:queueEntries]) { + ckksnotice("ckksincoming", self.deps.zoneID, "processQueueEntries didn't complete successfully"); errored = true; - return false; + return CKKSDatabaseTransactionRollback; } // Find the highest UUID for the next fetch. for(CKKSIncomingQueueEntry* iqe in queueEntries) { lastMaxUUID = ([lastMaxUUID compare:iqe.uuid] == NSOrderedDescending) ? lastMaxUUID : iqe.uuid; - }; - return true; + } + + return CKKSDatabaseTransactionCommit; }]; if(errored) { - ckksnotice("ckksincoming", ckks, "Early-exiting from IncomingQueueOperation"); - return; + ckksnotice("ckksincoming", self.deps.zoneID, "Early-exiting from IncomingQueueOperation"); + return false; } } - ckksnotice("ckksincoming", ckks, "Processed %lu items in incoming queue (%lu errors)", (unsigned long)self.successfulItemsProcessed, (unsigned long)self.errorItemsProcessed); + return true; +} +- (BOOL)fixMismatchedViewItems +{ + if(!self.handleMismatchedViewItems) { + return YES; + } - [ckks dispatchSync: ^bool{ - NSError* error = nil; + ckksnotice("ckksincoming", self.deps.zoneID, "Handling policy-mismatched items"); + __block NSUInteger lastCount = SecCKKSIncomingQueueItemsAtOnce; + __block NSString* lastMaxUUID = nil; + __block BOOL errored = NO; - NSArray* newCIPs = [CKKSCurrentItemPointer remoteItemPointers:ckks.zoneID error:&error]; - if(error || !newCIPs) { - ckkserror("ckksincoming", ckks, "Could not load remote item pointers: %@", error); - } else { - if (![self processNewCurrentItemPointers:newCIPs withManifest:ckks.latestManifest egoManifest:ckks.egoManifest]) { - return false; + id databaseProvider = self.deps.databaseProvider; + + while(lastCount == SecCKKSIncomingQueueItemsAtOnce) { + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + NSArray* queueEntries = [CKKSIncomingQueueEntry fetch:SecCKKSIncomingQueueItemsAtOnce + startingAtUUID:lastMaxUUID + state:SecCKKSStateMismatchedView + action:nil + zoneID:self.deps.zoneID + error:&error]; + if(error) { + ckksnotice("ckksincoming", self.deps.zoneID, "Cannot fetch mismatched view items"); + self.error = error; + errored = true; + return CKKSDatabaseTransactionRollback; } - ckksnotice("ckksincoming", ckks, "Processed %lu items in CIP queue", (unsigned long)newCIPs.count); - } - if(self.newOutgoingEntries) { - // No operation group - [ckks processOutgoingQueue:nil]; - } + lastCount = queueEntries.count; - if(self.pendingClassAEntries) { - [self.ckks processIncomingQueueAfterNextUnlock]; - } + if(queueEntries.count == 0) { + ckksnotice("ckksincoming", self.deps.zoneID, "No mismatched view items"); + return CKKSDatabaseTransactionCommit; + } - return true; - }]; -} + ckksnotice("ckksincoming", self.deps.zoneID, "Inspecting %lu mismatched items", (unsigned long)queueEntries.count); -- (void)_onqueueHandleIQEChange: (CKKSIncomingQueueEntry*) iqe attributes:(NSDictionary*)attributes class:(const SecDbClass *)classP { - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksincoming", ckks, "no CKKS object"); - return; + if (![self processQueueEntries:queueEntries]) { + ckksnotice("ckksincoming", self.deps.zoneID, "processQueueEntries didn't complete successfully"); + errored = true; + return CKKSDatabaseTransactionRollback; + } + + for(CKKSIncomingQueueEntry* iqe in queueEntries) { + lastMaxUUID = ([lastMaxUUID compare:iqe.uuid] == NSOrderedDescending) ? lastMaxUUID : iqe.uuid; + } + + return CKKSDatabaseTransactionCommit; + }]; } - dispatch_assert_queue(ckks.queue); + return !errored; +} + +- (void)_onqueueHandleIQEChange:(CKKSIncomingQueueEntry*)iqe + attributes:(NSDictionary*)attributes + class:(const SecDbClass *)classP + sortedForThisView:(BOOL)sortedForThisView +{ + __block CFErrorRef cferror = NULL; + SecDbItemRef item = SecDbItemCreateWithAttributes(NULL, classP, (__bridge CFDictionaryRef) attributes, KEYBAG_DEVICE, &cferror); + if(!item || cferror) { + ckkserror("ckksincoming", self.deps.zoneID, "Unable to make SecDbItemRef out of attributes: %@", cferror); + return; + } + CFReleaseNull(cferror); + + [self _onqueueHandleIQEChange:iqe + item:item + sortedForThisView:sortedForThisView]; + + CFReleaseNull(item); +} + +- (void)_onqueueHandleIQEChange:(CKKSIncomingQueueEntry*)iqe + item:(SecDbItemRef)item + sortedForThisView:(BOOL)sortedForThisView +{ bool ok = false; __block CFErrorRef cferror = NULL; __block NSError* error = NULL; - SecDbItemRef item = SecDbItemCreateWithAttributes(NULL, classP, (__bridge CFDictionaryRef) attributes, KEYBAG_DEVICE, &cferror); + if(SecDbItemIsTombstone(item)) { + ckkserror("ckksincoming", self.deps.zoneID, "Rejecting a tombstone item addition from CKKS(%@): %@", iqe.uuid, item); + + NSError* error = nil; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry withItem:item action:SecCKKSActionDelete zoneID:self.deps.zoneID error:&error]; + [oqe saveToDatabase:&error]; + + if(error) { + ckkserror("ckksincoming", self.deps.zoneID, "Unable to save new deletion OQE: %@", error); + } else { + [iqe deleteFromDatabase: &error]; + if(error) { + ckkserror("ckksincoming", self.deps.zoneID, "couldn't delete CKKSIncomingQueueEntry: %@", error); + self.error = error; + self.errorItemsProcessed += 1; + } else { + self.successfulItemsProcessed += 1; + } + } + self.newOutgoingEntries = true; + + return; + } __block NSDate* moddate = (__bridge NSDate*) CFDictionaryGetValue(item->attributes, kSecAttrModificationDate); ok = kc_with_dbt(true, &cferror, ^(SecDbConnectionRef dbt){ bool replaceok = SecDbItemInsertOrReplace(item, dbt, &cferror, ^(SecDbItemRef olditem, SecDbItemRef *replace) { - // If the UUIDs do not match, then select the item with the 'lower' UUID, and tell CKKS to + // If the UUIDs do not match, then check to be sure that the local item is known to CKKS. If not, accept the cloud value. + // Otherwise, when the UUIDs do not match, then select the item with the 'lower' UUID, and tell CKKS to // delete the item with the 'higher' UUID. // Otherwise, the cloud wins. - SecADAddValueForScalarKey((__bridge CFStringRef) SecCKKSAggdPrimaryKeyConflict,1); + [SecCoreAnalytics sendEvent:SecCKKSAggdPrimaryKeyConflict event:@{SecCoreAnalyticsValue: @1}]; // Note that SecDbItemInsertOrReplace CFReleases any replace pointer it's given, so, be careful if(!CFDictionaryContainsKey(olditem->attributes, kSecAttrUUID)) { // No UUID -> no good. - ckksnotice("ckksincoming", ckks, "Replacing item (it doesn't have a UUID) for %@", iqe.uuid); + ckksnotice("ckksincoming", self.deps.zoneID, "Replacing item (it doesn't have a UUID) for %@", iqe.uuid); if(replace) { *replace = CFRetainSafe(item); } return; } + // If this item arrived in what we believe to be the wrong view, drop the modification entirely. + if(!sortedForThisView) { + ckksnotice("ckksincoming", self.deps.zoneID, "Primary key conflict; dropping CK item (arriving from wrong view) %@", item); + return; + } + CFStringRef itemUUID = CFDictionaryGetValue(item->attributes, kSecAttrUUID); CFStringRef olditemUUID = CFDictionaryGetValue(olditem->attributes, kSecAttrUUID); + // Is the old item already somewhere in CKKS? + NSError* ckmeError = nil; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:(__bridge NSString*)olditemUUID + zoneID:self.deps.zoneID + error:&ckmeError]; + + if(ckmeError) { + ckksnotice("ckksincoming", self.deps.zoneID, "Unable to fetch ckme: %@", ckmeError); + // We'll just have to assume that there is a CKME, and let the comparison analysis below win + } + CFComparisonResult compare = CFStringCompare(itemUUID, olditemUUID, 0); CKKSOutgoingQueueEntry* oqe = nil; - if (compare == kCFCompareGreaterThan) { + if (compare == kCFCompareGreaterThan && (ckme || ckmeError)) { // olditem wins; don't change olditem; delete item - ckksnotice("ckksincoming", ckks, "Primary key conflict; dropping CK item %@", item); - oqe = [CKKSOutgoingQueueEntry withItem:item action:SecCKKSActionDelete ckks:ckks error:&error]; + ckksnotice("ckksincoming", self.deps.zoneID, "Primary key conflict; dropping CK item %@", item); + oqe = [CKKSOutgoingQueueEntry withItem:item action:SecCKKSActionDelete zoneID:self.deps.zoneID error:&error]; [oqe saveToDatabase: &error]; self.newOutgoingEntries = true; moddate = nil; } else { - // item wins - ckksnotice("ckksincoming", ckks, "Primary key conflict; replacing %@ with CK item %@", olditem, item); + // item wins, either due to the UUID winning or the item not being in CKKS yet + ckksnotice("ckksincoming", self.deps.zoneID, "Primary key conflict; replacing %@%@ with CK item %@", + ckme ? @"" : @"non-onboarded", olditem, item); if(replace) { *replace = CFRetainSafe(item); moddate = (__bridge NSDate*) CFDictionaryGetValue(item->attributes, kSecAttrModificationDate); } // delete olditem if UUID differs (same UUID is the normal update case) if (compare != kCFCompareEqualTo) { - oqe = [CKKSOutgoingQueueEntry withItem:olditem action:SecCKKSActionDelete ckks:ckks error:&error]; + oqe = [CKKSOutgoingQueueEntry withItem:olditem action:SecCKKSActionDelete zoneID:self.deps.zoneID error:&error]; [oqe saveToDatabase: &error]; self.newOutgoingEntries = true; } @@ -580,34 +695,32 @@ return replaceok; }); - CFReleaseNull(item); - if(cferror) { - ckkserror("ckksincoming", ckks, "couldn't process item from IncomingQueue: %@", cferror); + ckkserror("ckksincoming", self.deps.zoneID, "couldn't process item from IncomingQueue: %@", cferror); SecTranslateError(&error, cferror); self.error = error; iqe.state = SecCKKSStateError; [iqe saveToDatabase:&error]; if(error) { - ckkserror("ckksincoming", ckks, "Couldn't save errored IQE to database: %@", error); + ckkserror("ckksincoming", self.deps.zoneID, "Couldn't save errored IQE to database: %@", error); self.error = error; } return; } if(error) { - ckkserror("ckksincoming", ckks, "Couldn't handle IQE, but why?: %@", error); + ckkserror("ckksincoming", self.deps.zoneID, "Couldn't handle IQE, but why?: %@", error); self.error = error; return; } if(ok) { - ckksinfo("ckksincoming", ckks, "Correctly processed an IQE; deleting"); + ckksinfo("ckksincoming", self.deps.zoneID, "Correctly processed an IQE; deleting"); [iqe deleteFromDatabase: &error]; if(error) { - ckkserror("ckksincoming", ckks, "couldn't delete CKKSIncomingQueueEntry: %@", error); + ckkserror("ckksincoming", self.deps.zoneID, "couldn't delete CKKSIncomingQueueEntry: %@", error); self.error = error; self.errorItemsProcessed += 1; } else { @@ -617,20 +730,20 @@ if(moddate) { // Log the number of ms it took to propagate this change uint64_t delayInMS = [[NSDate date] timeIntervalSinceDate:moddate] * 1000; - [SecCoreAnalytics sendEvent:@"com.apple.ckks.item.propagation" event:@{ + [SecCoreAnalytics sendEvent:@"com.apple.self.deps.item.propagation" event:@{ @"time" : @(delayInMS) }]; } } else { - ckksnotice("ckksincoming", ckks, "IQE not correctly processed, but why? %@ %@", error, cferror); + ckksnotice("ckksincoming", self.deps.zoneID, "IQE not correctly processed, but why? %@ %@", error, cferror); self.error = error; iqe.state = SecCKKSStateError; [iqe saveToDatabase:&error]; if(error) { - ckkserror("ckksincoming", ckks, "Couldn't save errored IQE to database: %@", error); + ckkserror("ckksincoming", self.deps.zoneID, "Couldn't save errored IQE to database: %@", error); self.error = error; } @@ -639,25 +752,18 @@ } - (void)_onqueueHandleIQEDelete: (CKKSIncomingQueueEntry*) iqe class:(const SecDbClass *)classP { - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksincoming", ckks, "no CKKS object"); - return; - } - - dispatch_assert_queue(ckks.queue); - bool ok = false; __block CFErrorRef cferror = NULL; NSError* error = NULL; NSDictionary* queryAttributes = @{(__bridge NSString*) kSecClass: (__bridge NSString*) classP->name, (__bridge NSString*) kSecAttrUUID: iqe.uuid, (__bridge NSString*) kSecAttrSynchronizable: @(YES)}; - ckksnotice("ckksincoming", ckks, "trying to delete with query: %@", queryAttributes); - Query *q = query_create_with_limit( (__bridge CFDictionaryRef) queryAttributes, NULL, kSecMatchUnlimited, &cferror); + ckksnotice("ckksincoming", self.deps.zoneID, "trying to delete with query: %@", queryAttributes); + Query *q = query_create_with_limit( (__bridge CFDictionaryRef) queryAttributes, NULL, kSecMatchUnlimited, NULL, &cferror); + q->q_tombstone_use_mdat_from_item = true; if(cferror) { - ckkserror("ckksincoming", ckks, "couldn't create query: %@", cferror); + ckkserror("ckksincoming", self.deps.zoneID, "couldn't create query: %@", cferror); SecTranslateError(&error, cferror); self.error = error; return; @@ -669,11 +775,11 @@ if(cferror) { if(CFErrorGetCode(cferror) == errSecItemNotFound) { - ckkserror("ckksincoming", ckks, "couldn't delete item (as it's already gone); this is okay: %@", cferror); + ckkserror("ckksincoming", self.deps.zoneID, "couldn't delete item (as it's already gone); this is okay: %@", cferror); ok = true; CFReleaseNull(cferror); } else { - ckkserror("ckksincoming", ckks, "couldn't delete item: %@", cferror); + ckkserror("ckksincoming", self.deps.zoneID, "couldn't delete item: %@", cferror); SecTranslateError(&error, cferror); self.error = error; query_destroy(q, NULL); @@ -685,25 +791,25 @@ ok = query_notify_and_destroy(q, ok, &cferror); if(cferror) { - ckkserror("ckksincoming", ckks, "couldn't delete query: %@", cferror); + ckkserror("ckksincoming", self.deps.zoneID, "couldn't delete query: %@", cferror); SecTranslateError(&error, cferror); self.error = error; return; } if(ok) { - ckksnotice("ckksincoming", ckks, "Correctly processed an IQE; deleting"); + ckksnotice("ckksincoming", self.deps.zoneID, "Correctly processed an IQE; deleting"); [iqe deleteFromDatabase: &error]; if(error) { - ckkserror("ckksincoming", ckks, "couldn't delete CKKSIncomingQueueEntry: %@", error); + ckkserror("ckksincoming", self.deps.zoneID, "couldn't delete CKKSIncomingQueueEntry: %@", error); self.error = error; self.errorItemsProcessed += 1; } else { self.successfulItemsProcessed += 1; } } else { - ckkserror("ckksincoming", ckks, "IQE not correctly processed, but why? %@ %@", error, cferror); + ckkserror("ckksincoming", self.deps.zoneID, "IQE not correctly processed, but why? %@ %@", error, cferror); self.error = error; self.errorItemsProcessed += 1; } diff --git a/keychain/ckks/CKKSItem.m b/keychain/ckks/CKKSItem.m index 445d4898..688d7eca 100644 --- a/keychain/ckks/CKKSItem.m +++ b/keychain/ckks/CKKSItem.m @@ -178,7 +178,17 @@ plaintextPCSServiceIdentifier: (NSNumber*) pcsServiceIdentifier _uuid = [[record recordID] recordName]; self.parentKeyUUID = [record[SecCKRecordParentKeyRefKey] recordID].recordName; self.encitem = record[SecCKRecordDataKey]; - self.wrappedkey = [[CKKSWrappedAESSIVKey alloc] initWithBase64: record[SecCKRecordWrappedKeyKey]]; + + // If wrapped key is nil, this is a bad record. We've seen this at least once, though, and so need to be resilient to it. + // Passing nil here will cause a crash, so pass all zeroes. + NSString* wrappedKey = record[SecCKRecordWrappedKeyKey]; + if(wrappedKey) { + self.wrappedkey = [[CKKSWrappedAESSIVKey alloc] initWithBase64:wrappedKey]; + } else { + ckkserror("ckksitem", record.recordID.zoneID, "Corrupt item recieved with no wrapped key"); + self.wrappedkey = [CKKSWrappedAESSIVKey zeroedKey]; + } + self.generationCount = [record[SecCKRecordGenerationCountKey] unsignedIntegerValue]; self.encver = [record[SecCKRecordEncryptionVersionKey] unsignedIntegerValue]; @@ -228,27 +238,27 @@ plaintextPCSServiceIdentifier: (NSNumber*) pcsServiceIdentifier // Note that since all of those things are included as authenticated data into the AES-SIV ciphertext, we could just // compare that. However, check 'em all. if(![record.recordID.recordName isEqualToString: self.uuid]) { - secinfo("ckksitem", "UUID does not match"); + ckksinfo_global("ckksitem", "UUID does not match"); return false; } if(![[record[SecCKRecordParentKeyRefKey] recordID].recordName isEqualToString: self.parentKeyUUID]) { - secinfo("ckksitem", "wrapping key reference does not match"); + ckksinfo_global("ckksitem", "wrapping key reference does not match"); return false; } if(![record[SecCKRecordGenerationCountKey] isEqual: [NSNumber numberWithInteger:self.generationCount]]) { - secinfo("ckksitem", "SecCKRecordGenerationCountKey does not match"); + ckksinfo_global("ckksitem", "SecCKRecordGenerationCountKey does not match"); return false; } if(![record[SecCKRecordWrappedKeyKey] isEqual: [self.wrappedkey base64WrappedKey]]) { - secinfo("ckksitem", "SecCKRecordWrappedKeyKey does not match"); + ckksinfo_global("ckksitem", "SecCKRecordWrappedKeyKey does not match"); return false; } if(![record[SecCKRecordDataKey] isEqual: self.encitem]) { - secinfo("ckksitem", "SecCKRecordDataKey does not match"); + ckksinfo_global("ckksitem", "SecCKRecordDataKey does not match"); return false; } @@ -256,19 +266,19 @@ plaintextPCSServiceIdentifier: (NSNumber*) pcsServiceIdentifier // Why is obj-c nullable equality so difficult? if(!((record[SecCKRecordPCSServiceIdentifier] == nil && self.plaintextPCSServiceIdentifier == nil) || [record[SecCKRecordPCSServiceIdentifier] isEqual: self.plaintextPCSServiceIdentifier])) { - secinfo("ckksitem", "SecCKRecordPCSServiceIdentifier does not match"); + ckksinfo_global("ckksitem", "SecCKRecordPCSServiceIdentifier does not match"); return false; } if(!((record[SecCKRecordPCSPublicKey] == nil && self.plaintextPCSPublicKey == nil) || [record[SecCKRecordPCSPublicKey] isEqual: self.plaintextPCSPublicKey])) { - secinfo("ckksitem", "SecCKRecordPCSPublicKey does not match"); + ckksinfo_global("ckksitem", "SecCKRecordPCSPublicKey does not match"); return false; } if(!((record[SecCKRecordPCSPublicIdentity] == nil && self.plaintextPCSPublicIdentity == nil) || [record[SecCKRecordPCSPublicIdentity] isEqual: self.plaintextPCSPublicIdentity])) { - secinfo("ckksitem", "SecCKRecordPCSPublicIdentity does not match"); + ckksinfo_global("ckksitem", "SecCKRecordPCSPublicIdentity does not match"); return false; } diff --git a/keychain/ckks/CKKSItemEncrypter.m b/keychain/ckks/CKKSItemEncrypter.m index 90810cef..a487b2b9 100644 --- a/keychain/ckks/CKKSItemEncrypter.m +++ b/keychain/ckks/CKKSItemEncrypter.m @@ -88,7 +88,7 @@ if(olditem) { NSMutableDictionary* oldDictionary = [[CKKSItemEncrypter decryptItemToDictionary: olditem error:error] mutableCopy]; if(!oldDictionary) { - secerror("Couldn't decrypt old CKMirror entry: %@", (error ? *error : @"null error passed in")); + ckkserror("ckme", olditem.zoneID, "Couldn't decrypt old CKMirror entry: %@", (error ? *error : @"null error passed in")); return nil; } @@ -159,7 +159,7 @@ NSDictionary* result = [self decryptDictionary: item.encitem key:itemkey authenticatedData:authenticatedData error:error]; if(!result) { - secwarning("ckks: couldn't decrypt item %@", *error); + ckkserror("item", item.zoneID, "ckks: couldn't decrypt item %@", *error); } return result; } @@ -177,7 +177,7 @@ code:1 userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Unrecognized encryption version: %lu", (unsigned long)item.encver]}]; - secerror("decryptItemToDictionary %@", localError); + ckkserror("item", item.zoneID, "decryptItemToDictionary failed: %@", localError); if (error) { *error = localError; } diff --git a/keychain/ckks/CKKSKey.h b/keychain/ckks/CKKSKey.h index 766e5479..a651da13 100644 --- a/keychain/ckks/CKKSKey.h +++ b/keychain/ckks/CKKSKey.h @@ -34,6 +34,8 @@ NS_ASSUME_NONNULL_BEGIN +@class CKKSPeerProviderState; + @interface CKKSKey : CKKSCKRecordHolder @property CKKSKeychainBackedKey* keycore; @@ -47,6 +49,8 @@ NS_ASSUME_NONNULL_BEGIN @property (copy) CKKSProcessedState* state; @property bool currentkey; +@property (readonly) NSString* zoneName; + // Fetches and attempts to unwrap this key for use + (instancetype _Nullable)loadKeyWithUUID:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; @@ -78,7 +82,19 @@ NS_ASSUME_NONNULL_BEGIN error:(NSError* __autoreleasing*)error; +// Returns false if this key is not a valid TLK for any reason. +- (BOOL)validTLK:(NSError**)error; + +// First, attempts to load the key from the keychain. If it isn't present, this will +// load the TLKShares for this key from the database, then attempts to use them to unwrap this key. +// If no TLKShares are trusted, returns an error. +- (BOOL)tlkMaterialPresentOrRecoverableViaTLKShare:(NSArray*)trustStates + error:(NSError**)error; + + (instancetype _Nullable)fromDatabase:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; ++ (instancetype _Nullable)fromDatabaseAnyState:(NSString*)uuid + zoneID:(CKRecordZoneID*)zoneID + error:(NSError* __autoreleasing*)error; + (instancetype _Nullable)tryFromDatabase:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (instancetype _Nullable)tryFromDatabaseAnyState:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; diff --git a/keychain/ckks/CKKSKey.m b/keychain/ckks/CKKSKey.m index 4f497ee0..fe5b22c8 100644 --- a/keychain/ckks/CKKSKey.m +++ b/keychain/ckks/CKKSKey.m @@ -27,6 +27,7 @@ #import "CKKSKeychainView.h" #import "CKKSCurrentKeyPointer.h" #import "CKKSKey.h" +#import "keychain/ckks/CKKSPeerProvider.h" #import "keychain/categories/NSError+UsefulConstructors.h" #include "keychain/securityd/SecItemSchema.h" #include @@ -41,7 +42,8 @@ @implementation CKKSKey - (instancetype)init { - self = [super init]; + if ((self = [super init])) { + } return self; } @@ -155,6 +157,11 @@ return self.keycore.uuid; } +- (NSString*)zoneName +{ + return self.keycore.zoneID.zoneName; +} + - (void)setUuid:(NSString *)uuid { self.keycore.uuid = uuid; @@ -265,9 +272,11 @@ // Check for circular references. if([seenUUID containsObject:key.uuid]) { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSCircularKeyReference - description:@"Circular reference in key hierarchy"]; + if (error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSCircularKeyReference + description:@"Circular reference in key hierarchy"]; + } return nil; } @@ -302,7 +311,7 @@ // Attempt to save this new key, but don't error if it fails NSError* resaveError = nil; if(![self saveKeyMaterialToKeychain:&resaveError] || resaveError) { - secerror("ckkskey: Resaving missing key failed, continuing: %@", resaveError); + ckkserror("ckkskey", self.zoneID, "Resaving missing key failed, continuing: %@", resaveError); } return self.aessivkey; @@ -352,6 +361,130 @@ return self.aessivkey; } +- (BOOL)unwrapViaTLKSharesTrustedBy:(NSArray*)trustStates + error:(NSError**)error +{ + NSError* localerror = nil; + + if(trustStates.count == 0u) { + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSLackingTrust + description:@"No current trust states; can't unwrap TLK"]; + } + return NO; + } + + NSArray* possibleShares = [CKKSTLKShareRecord allForUUID:self.uuid + zoneID:self.zoneID + error:&localerror]; + + if(!possibleShares || localerror) { + ckkserror("ckksshare", self, "Unable to load TLK shares for TLK(%@): %@", self, localerror); + if(error) { + *error = localerror; + } + return NO; + } + + NSError* lastTrustStateError = nil; + for(CKKSPeerProviderState* trustState in trustStates) { + BOOL extracted = [trustState unwrapKey:self + fromShares:possibleShares + error:&localerror]; + + if(!extracted || localerror) { + ckkserror("ckksshare", self, "Failed to recover tlk (%@) from trust state (%@): %@", self.uuid, trustState, localerror); + lastTrustStateError = localerror; + localerror = nil; + } else { + ckkserror("ckksshare", self, "Recovered tlk (%@) from trust state (%@)", self.uuid, trustState); + return YES; + } + } + + // Because there's at least one trustState, then either we returned the TLK above, or we filled in lastTrustStateError. + if(error) { + *error = lastTrustStateError; + } + + return NO; +} + +- (BOOL)validTLK:(NSError**)error +{ + if(![self wrapsSelf]) { + NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSKeyNotSelfWrapped + description:[NSString stringWithFormat:@"Potential TLK %@ doesn't wrap itself: %@", + self, + self.parentKeyUUID] + underlying:NULL]; + ckkserror("ckksshare", self, "Error with TLK: %@", localerror); + if (error) { + *error = localerror; + } + return NO; + } + + return YES; +} + +- (BOOL)tlkMaterialPresentOrRecoverableViaTLKShare:(NSArray*)trustStates + error:(NSError**)error +{ + // If we have the key material, then this TLK is considered valid. + NSError* loadError = nil; + CKKSAESSIVKey* loadedKey = [self ensureKeyLoaded:&loadError]; + if(!loadedKey || loadError) { + if(loadError.code == errSecInteractionNotAllowed) { + ckkserror("ckksshare", self, "Unable to load key due to lock state: %@", loadError); + if(error) { + *error = loadError; + } + + return NO; + } + + ckkserror("ckksshare", self, "Do not yet have this key in the keychain: %@", loadError); + // Fall through to attempt to recover the TLK via shares below + } else { + bool result = [self trySelfWrappedKeyCandidate:loadedKey error:&loadError]; + if(result) { + // We have a key, and it can decrypt itself. + return YES; + } else { + ckkserror("ckksshare", self, "Some key is present, but the key is not self-wrapped: %@", loadError); + // Key seems broken. Fall through. + } + } + + NSError* localerror = nil; + BOOL success = [self unwrapViaTLKSharesTrustedBy:trustStates + error:&localerror]; + + if(!success || localerror) { + ckkserror("ckksshare", self, "Failed to unwrap tlk(%@) via shares: %@", self.uuid, localerror); + if(error) { + *error = localerror; + } + return NO; + } + + success = [self saveKeyMaterialToKeychain:true error:&localerror]; + + if(!success || localerror) { + ckkserror("ckksshare", self, "Errored saving TLK to keychain: %@", localerror); + + if(error) { + *error = localerror; + return NO; + } + } + + return YES; +} + - (bool)trySelfWrappedKeyCandidate:(CKKSAESSIVKey*)candidate error:(NSError * __autoreleasing *) error { return [self.keycore trySelfWrappedKeyCandidate:candidate error:error]; } @@ -592,31 +725,31 @@ } if(![record.recordID.recordName isEqualToString: self.uuid]) { - secinfo("ckkskey", "UUID does not match"); + ckksinfo_global("ckkskey", "UUID does not match"); return false; } // For the parent key ref, ensure that if it's nil, we wrap ourself if(record[SecCKRecordParentKeyRefKey] == nil) { if(![self wrapsSelf]) { - secinfo("ckkskey", "wrapping key reference (self-wrapped) does not match"); + ckksinfo_global("ckkskey", "wrapping key reference (self-wrapped) does not match"); return false; } } else { if(![[[record[SecCKRecordParentKeyRefKey] recordID] recordName] isEqualToString: self.parentKeyUUID]) { - secinfo("ckkskey", "wrapping key reference (non-self-wrapped) does not match"); + ckksinfo_global("ckkskey", "wrapping key reference (non-self-wrapped) does not match"); return false; } } if(![record[SecCKRecordKeyClassKey] isEqual: self.keyclass]) { - secinfo("ckkskey", "key class does not match"); + ckksinfo_global("ckkskey", "key class does not match"); return false; } if(![record[SecCKRecordWrappedKeyKey] isEqual: [self.wrappedkey base64WrappedKey]]) { - secinfo("ckkskey", "wrapped key does not match"); + ckksinfo_global("ckkskey", "wrapped key does not match"); return false; } diff --git a/keychain/ckks/CKKSKeychainBackedKey.m b/keychain/ckks/CKKSKeychainBackedKey.m index 8552ee42..eca829c6 100644 --- a/keychain/ckks/CKKSKeychainBackedKey.m +++ b/keychain/ckks/CKKSKeychainBackedKey.m @@ -31,7 +31,7 @@ NSError* error = nil; [self wrapUnder:self error:&error]; if(error != nil) { - secerror("CKKSKeychainBackedKey: Couldn't self-wrap key: %@", error); + ckkserror_global("ckkskey", "Couldn't self-wrap key: %@", error); return nil; } } @@ -55,7 +55,7 @@ NSError* error = nil; [self wrapUnder:wrappingKey error:&error]; if(error != nil) { - secerror("CKKSKeychainBackedKey: Couldn't wrap key with key: %@", error); + ckkserror_global("ckkskey", "Couldn't wrap key with key: %@", error); return nil; } } @@ -118,16 +118,18 @@ error:(NSError* __autoreleasing*)error { NSError* localError = nil; - self.wrappedkey = [wrappingKey wrapAESKey:self.aessivkey error:&localError]; - if(self.wrappedkey == nil) { - secerror("CKKSKeychainBackedKey: couldn't wrap key: %@", localError); + CKKSWrappedAESSIVKey* wrappedKey = [wrappingKey wrapAESKey:self.aessivkey error:&localError]; + if (wrappedKey == nil) { + ckkserror_global("ckkskey", "couldn't wrap key: %@", localError); if(error) { *error = localError; } + return false; } else { + self.wrappedkey = wrappedKey; self.parentKeyUUID = wrappingKey.uuid; } - return (self.wrappedkey != nil); + return true; } - (bool)unwrapSelfWithAESKey:(CKKSAESSIVKey*)unwrappingKey @@ -335,7 +337,7 @@ [CKKSKeychainBackedKey setKeyMaterialInKeychain:query error:&localError]; if(stashError) { - secerror("CKKSKeychainBackedKey: Couldn't stash %@ to keychain: %@", self, stashError); + ckkserror_global("ckkskey", "Couldn't stash %@ to keychain: %@", self, stashError); } } @@ -481,7 +483,7 @@ result = [self queryKeyMaterialInKeychain:query error:&localError]; if(localError == nil) { - secnotice("CKKSKeychainBackedKey", "loaded a piggy TLK (%@)", key.uuid); + ckksnotice_global("ckkskey", "loaded a piggy TLK (%@)", key.uuid); if(resavePtr) { *resavePtr = true; @@ -527,7 +529,7 @@ result = [self queryKeyMaterialInKeychain:query error:&localError]; if(localError == nil) { - secnotice("CKKSKeychainBackedKey", "loaded a stashed TLK (%@)", key.uuid); + ckksnotice_global("ckkskey", "loaded a stashed TLK (%@)", key.uuid); if(resavePtr) { *resavePtr = true; @@ -579,7 +581,7 @@ NSMutableData* keymaterial = [[NSMutableData alloc] initWithBase64EncodedData:b64keymaterial options:0]; if(!keymaterial) { - secnotice("CKKSKeychainBackedKey", "Unable to unbase64 key: %@", self); + ckkserror_global("ckkskey", "Unable to unbase64 key: %@", self); if(error) { *error = [NSError errorWithDomain:CKKSErrorDomain @@ -595,11 +597,11 @@ self.aessivkey = key; if(resave) { - secnotice("CKKSKeychainBackedKey", "Resaving %@ as per request", self); + ckksnotice_global("ckkskey", "Resaving %@ as per request", self); NSError* resaveError = nil; [self saveKeyMaterialToKeychain:&resaveError]; if(resaveError) { - secnotice("CKKSKeychainBackedKey", "Resaving %@ failed: %@", self, resaveError); + ckksnotice_global("ckkskey", "Resaving %@ failed: %@", self, resaveError); } } @@ -727,8 +729,7 @@ - (nullable instancetype)initWithCoder:(nonnull NSCoder*)decoder { - self = [super init]; - if(self) { + if ((self = [super init])) { _uuid = [decoder decodeObjectOfClass:[NSString class] forKey:@"uuid"]; _parentKeyUUID = [decoder decodeObjectOfClass:[NSString class] forKey:@"parentKeyUUID"]; @@ -786,8 +787,7 @@ - (nullable instancetype)initWithCoder:(nonnull NSCoder*)decoder { - self = [super init]; - if(self) { + if ((self = [super init])) { _tlk = [decoder decodeObjectOfClass:[CKKSKeychainBackedKey class] forKey:@"tlk"]; _classA = [decoder decodeObjectOfClass:[CKKSKeychainBackedKey class] forKey:@"classA"]; _classC = [decoder decodeObjectOfClass:[CKKSKeychainBackedKey class] forKey:@"classC"]; diff --git a/keychain/ckks/CKKSKeychainView.h b/keychain/ckks/CKKSKeychainView.h index 5e090e1b..7ed70543 100644 --- a/keychain/ckks/CKKSKeychainView.h +++ b/keychain/ckks/CKKSKeychainView.h @@ -31,6 +31,9 @@ #import "keychain/ckks/CKKSReachabilityTracker.h" #import "keychain/ckks/CloudKitDependencies.h" +#import "keychain/ot/OctagonFlags.h" +#import "keychain/ot/OctagonStateMachine.h" + #include "keychain/securityd/SecDbItem.h" #include @@ -49,12 +52,13 @@ #import "keychain/ckks/CKKSScanLocalItemsOperation.h" #import "keychain/ckks/CKKSTLKShareRecord.h" #import "keychain/ckks/CKKSUpdateDeviceStateOperation.h" -#import "keychain/ckks/CKKSZone.h" #import "keychain/ckks/CKKSZoneModifier.h" #import "keychain/ckks/CKKSZoneChangeFetcher.h" #import "keychain/ckks/CKKSSynchronizeOperation.h" #import "keychain/ckks/CKKSLocalSynchronizeOperation.h" #import "keychain/ckks/CKKSProvideKeySetOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h" #include "CKKS.h" @@ -64,34 +68,41 @@ NS_ASSUME_NONNULL_BEGIN @class CKKSAESSIVKey; @class CKKSSynchronizeOperation; @class CKKSRateLimiter; -@class CKKSManifest; -@class CKKSEgoManifest; @class CKKSOutgoingQueueEntry; @class CKKSZoneChangeFetcher; @class CKKSCurrentKeySet; -@interface CKKSKeychainView : CKKSZone -{ - CKKSZoneKeyState* _keyHierarchyState; -} + CKKSPeerUpdateListener, + CKKSDatabaseProviderProtocol, + OctagonStateMachineEngine> + +@property (readonly) NSString* zoneName; +@property CKKSAccountStatus accountStatus; +@property (readonly) CKContainer* container; +@property (readonly) CKDatabase* database; +@property (weak) CKKSAccountStateTracker* accountTracker; +@property (weak) CKKSReachabilityTracker* reachabilityTracker; +@property (readonly) CKKSCloudKitClassDependencies* cloudKitClassDependencies; +@property (readonly) dispatch_queue_t queue; + +@property (readonly) CKRecordZoneID* zoneID; @property CKKSCondition* loggedIn; @property CKKSCondition* loggedOut; @property CKKSCondition* accountStateKnown; @property CKKSAccountStatus trustStatus; -@property (nullable) CKKSResultOperation* trustDependency; @property (nullable) CKKSLaunchSequence *launch; @property CKKSLockStateTracker* lockStateTracker; -@property CKKSZoneKeyState* keyHierarchyState; -@property (nullable) NSError* keyHierarchyError; -@property (nullable) CKOperationGroup* keyHierarchyOperationGroup; -@property (nullable) NSOperation* keyStateMachineOperation; +// Is this view currently syncing keychain modifications? +@property (readonly) BOOL itemSyncingEnabled; + +@property (readonly) OctagonStateMachine* stateMachine; // If the key hierarchy isn't coming together, it might be because we're out of sync with cloudkit. // Use this to track if we've completed a full refetch, so fix-up operations can be done. @@ -100,27 +111,15 @@ NS_ASSUME_NONNULL_BEGIN // Set this to request a key state refetch (tests only) @property bool keyStateFullRefetchRequested; -@property (nullable) CKKSEgoManifest* egoManifest; -@property (nullable) CKKSManifest* latestManifest; @property (nullable) CKKSResultOperation* keyStateReadyDependency; -// Wait for the key state to become 'nontransient': no pending operation is expected to advance it (at least until intervention) -@property (nullable) CKKSResultOperation* keyStateNonTransientDependency; - -// True if we believe there's any items in the keychain which haven't been brought up in CKKS yet -@property bool droppedItems; - -@property (readonly) NSString* lastActiveTLKUUID; - // Full of condition variables, if you'd like to try to wait until the key hierarchy is in some state -@property NSMutableDictionary* keyHierarchyConditions; +@property (readonly) NSDictionary* keyHierarchyConditions; @property CKKSZoneChangeFetcher* zoneChangeFetcher; -@property (weak) CKKSNearFutureScheduler* savedTLKNotifier; - @property (nullable) CKKSNearFutureScheduler* suggestTLKUpload; - +@property (nullable) CKKSNearFutureScheduler* requestPolicyCheck; /* Used for debugging: just what happened last time we ran this? */ @property CKKSIncomingQueueOperation* lastIncomingQueueOperation; @@ -128,7 +127,6 @@ NS_ASSUME_NONNULL_BEGIN @property CKKSOutgoingQueueOperation* lastOutgoingQueueOperation; @property CKKSProcessReceivedKeysOperation* lastProcessReceivedKeysOperation; @property CKKSReencryptOutgoingItemsOperation* lastReencryptOutgoingItemsOperation; -@property CKKSScanLocalItemsOperation* lastScanLocalItemsOperation; @property CKKSSynchronizeOperation* lastSynchronizeOperation; @property CKKSResultOperation* lastFixupOperation; @@ -139,23 +137,16 @@ NS_ASSUME_NONNULL_BEGIN @property NSOperation* holdLocalSynchronizeOperation; @property CKKSResultOperation* holdFixupOperation; +/* Used for testing */ +@property BOOL initiatedLocalScan; + /* Trigger this to tell the whole machine that this view has changed */ @property CKKSNearFutureScheduler* notifyViewChangedScheduler; /* Trigger this to tell the whole machine that this view is more ready then before */ @property CKKSNearFutureScheduler* notifyViewReadyScheduler; -/* trigger this to request key state machine poking */ -@property CKKSNearFutureScheduler* pokeKeyStateMachineScheduler; - -// The current list of peer providers. If empty, CKKS will consider itself untrusted, and halt operation -@property (readonly) NSArray>* currentPeerProviders; - -// These are available when you're in a dispatchSyncWithAccountKeys call, but at no other time -// These must be pre-fetched before you get on the CKKS queue, otherwise we end up with CKKS<->SQLite<->SOSAccountQueue deadlocks - -// They will be in a parallel array with currentPeerProviders above -@property (readonly) NSArray* currentTrustStates; +@property (readonly) CKKSOperationDependencies* operationDependencies; - (instancetype)initWithContainer:(CKContainer*)container zoneName:(NSString*)zoneName @@ -168,10 +159,29 @@ NS_ASSUME_NONNULL_BEGIN cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies; /* Trust state management */ + +// suggestTLKUpload and requestPolicyCheck are essentially callbacks to request certain procedures from the view owner. +// When suggestTLKUpload is triggered, the CKKS view believes it has some new TLKs that need uploading, and Octagon should take care of them. +// When requestPolicyCheck is triggered, the CKKS view would like Octagon to perform a live check on which syncing policy is in effect, +// successfully retrieving all peer's opinions, and would like -setCurrentSyncingPolicy to be called with the updated policy (even if it is +// unchanged.) - (void)beginTrustedOperation:(NSArray>*)peerProviders - suggestTLKUpload:(CKKSNearFutureScheduler*)suggestTLKUpload; + suggestTLKUpload:(CKKSNearFutureScheduler*)suggestTLKUpload + requestPolicyCheck:(CKKSNearFutureScheduler*)requestPolicyCheck; + - (void)endTrustedOperation; +/* CloudKit account management */ + +- (void)beginCloudKitOperation; + +// If this policy indicates that this view should not sync, this view will no longer sync keychain items, +// but it will continue to particpate in TLK sharing. +// If policyIsFresh is set, any items discovered that do not match this policy will be moved. +- (void)setCurrentSyncingPolicy:(TPSyncingPolicy*)syncingPolicy policyIsFresh:(BOOL)policyIsFresh; + +- (void)receivedItemForWrongView; + /* Synchronous operations */ - (void)handleKeychainEventDbConnection:(SecDbConnectionRef)dbconn @@ -195,27 +205,23 @@ NS_ASSUME_NONNULL_BEGIN - (bool)outgoingQueueEmpty:(NSError* __autoreleasing*)error; -- (CKKSResultOperation*)findKeySet; +- (CKKSResultOperation*)findKeySet:(BOOL)refetchBeforeReturningKeySet; - (void)receiveTLKUploadRecords:(NSArray*)records; -- (CKKSResultOperation*)waitForFetchAndIncomingQueueProcessing; +// Returns true if this zone would like a new TLK to be uploaded +- (BOOL)requiresTLKUpload; + - (void)waitForKeyHierarchyReadiness; - (void)cancelAllOperations; -- (CKKSKey* _Nullable)keyForItem:(SecDbItemRef)item error:(NSError* __autoreleasing*)error; - -- (bool)_onqueueWithAccountKeysCheckTLK:(CKKSKey*)proposedTLK error:(NSError* __autoreleasing*)error; - -- (BOOL)otherDevicesReportHavingTLKs:(CKKSCurrentKeySet*)keyset; - /* Asynchronous kickoffs */ - (CKKSOutgoingQueueOperation*)processOutgoingQueue:(CKOperationGroup* _Nullable)ckoperationGroup; - (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup; -- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation*)after +- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after requiredDelay:(uint64_t)requiredDelay - ckoperationGroup:(CKOperationGroup*)ckoperationGroup; + ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup; - (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA; - (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA after:(CKKSResultOperation* _Nullable)after; @@ -237,8 +243,6 @@ NS_ASSUME_NONNULL_BEGIN - (CKKSSynchronizeOperation*)resyncWithCloud; - (CKKSLocalSynchronizeOperation*)resyncLocal; -- (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because; - - (CKKSResultOperation*)resetLocalData; - (CKKSResultOperation*)resetCloudKitZone:(CKOperationGroup*)operationGroup; @@ -248,20 +252,11 @@ NS_ASSUME_NONNULL_BEGIN // For our serial queue to work with how handleKeychainEventDbConnection is called from the main thread, // every block on our queue must have a SecDBConnectionRef available to it before it begins on the queue. // Use these helper methods to make sure those exist. -- (void)dispatchSync:(bool (^)(void))block; -- (void)dispatchSyncWithAccountKeys:(bool (^)(void))block; +- (void)dispatchSyncWithSQLTransaction:(CKKSDatabaseTransactionResult (^)(void))block; +- (void)dispatchSyncWithReadOnlySQLTransaction:(void (^)(void))block; /* Synchronous operations which must be called from inside a dispatchAsyncWithAccountKeys or dispatchSync block */ -// Call this to request the key hierarchy state machine to fetch new updates -- (void)_onqueueKeyStateMachineRequestFetch; - -// Call this to request the key hierarchy state machine to reprocess -- (void)_onqueueKeyStateMachineRequestProcess; - -// Call this from a key hierarchy operation to move the state machine, and record the results of the last move. -- (void)_onqueueAdvanceKeyStateMachineToState:(CKKSZoneKeyState* _Nullable)state withError:(NSError* _Nullable)error; - // Since we might have people interested in the state transitions of objects, please do those transitions via these methods - (bool)_onqueueChangeOutgoingQueueEntry:(CKKSOutgoingQueueEntry*)oqe toState:(NSString*)state @@ -279,24 +274,6 @@ NS_ASSUME_NONNULL_BEGIN - (bool)_onqueueCKRecordChanged:(CKRecord*)record resync:(bool)resync; - (bool)_onqueueCKRecordDeleted:(CKRecordID*)recordID recordType:(NSString*)recordType resync:(bool)resync; -// For this key, who doesn't yet have a CKKSTLKShare for it, shared to their current Octagon keys? -// Note that we really want a record sharing the TLK to ourselves, so this function might return -// a non-empty set even if all peers have the TLK: it wants us to make a record for ourself. -// If you pass in a non-empty set in afterUploading, those records will be included in the calculation. -- (NSSet>*)_onqueueFindPeers:(CKKSPeerProviderState*)trustState - missingShare:(CKKSKey*)key - afterUploading:(NSSet* _Nullable)newShares - error:(NSError* __autoreleasing*)error; - -- (BOOL)_onqueueAreNewSharesSufficient:(NSSet*)newShares - currentTLK:(CKKSKey*)key - error:(NSError* __autoreleasing*)error; - -// For this key, share it to all trusted peers who don't have it yet -- (NSSet* _Nullable)_onqueueCreateMissingKeyShares:(CKKSKey*)key error:(NSError* __autoreleasing*)error; - -- (bool)_onqueueUpdateLatestManifestWithError:(NSError**)error; - - (CKKSDeviceStateEntry* _Nullable)_onqueueCurrentDeviceStateEntry:(NSError* __autoreleasing*)error; // Please don't use these unless you're an Operation in this package @@ -304,11 +281,34 @@ NS_ASSUME_NONNULL_BEGIN @property NSHashTable* outgoingQueueOperations; @property NSHashTable* scanLocalItemsOperations; -@property CKKSScanLocalItemsOperation* initialScanOperation; // Returns the current state of this view, fastStatus is the same, but as name promise, no expensive calculations - (NSDictionary*)status; - (NSDictionary*)fastStatus; + +- (void)xpc24HrNotification; + +// NSOperation Helpers +- (void)scheduleOperation:(NSOperation*)op; +@end + +@interface CKKSKeychainView (Testing) + +// Call this to just nudge the state machine (without a request) +// This is used internally, but you should only call it if you're a test. +- (void)_onqueuePokeKeyStateMachine; + +/* NSOperation helpers */ +- (void)cancelAllOperations; +- (void)waitUntilAllOperationsAreFinished; +- (void)waitForOperationsOfClass:(Class)operationClass; + +- (void)waitForFetchAndIncomingQueueProcessing; + +- (void)halt; + +- (void)handleCKLogout; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSKeychainView.m b/keychain/ckks/CKKSKeychainView.m index 6a9589a1..16be35cf 100644 --- a/keychain/ckks/CKKSKeychainView.m +++ b/keychain/ckks/CKKSKeychainView.m @@ -32,6 +32,7 @@ #endif #import "CKKS.h" +#import "keychain/ckks/CKKSStates.h" #import "OctagonAPSReceiver.h" #import "CKKSIncomingQueueEntry.h" #import "CKKSOutgoingQueueEntry.h" @@ -43,9 +44,8 @@ #import "CKKSIncomingQueueOperation.h" #import "CKKSNewTLKOperation.h" #import "CKKSProcessReceivedKeysOperation.h" -#import "CKKSZone.h" #import "CKKSFetchAllRecordZoneChangesOperation.h" -#import "CKKSHealKeyHierarchyOperation.h" +#import "keychain/ckks/CKKSHealKeyHierarchyOperation.h" #import "CKKSReencryptOutgoingItemsOperation.h" #import "CKKSScanLocalItemsOperation.h" #import "CKKSSynchronizeOperation.h" @@ -59,6 +59,8 @@ #import "keychain/ckks/CKKSDeviceStateEntry.h" #import "keychain/ckks/CKKSNearFutureScheduler.h" #import "keychain/ckks/CKKSCurrentItemPointer.h" +#import "keychain/ckks/CKKSCreateCKZoneOperation.h" +#import "keychain/ckks/CKKSDeleteCKZoneOperation.h" #import "keychain/ckks/CKKSUpdateCurrentItemPointerOperation.h" #import "keychain/ckks/CKKSUpdateDeviceStateOperation.h" #import "keychain/ckks/CKKSNotifier.h" @@ -67,8 +69,12 @@ #import "keychain/ckks/CKKSHealTLKSharesOperation.h" #import "keychain/ckks/CKKSLocalSynchronizeOperation.h" #import "keychain/ckks/CKKSPeerProvider.h" +#import "keychain/ckks/CKKSCheckKeyHierarchyOperation.h" +#import "keychain/ckks/CKKSViewManager.h" #import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKSLocalResetOperation.h" + #import "keychain/ot/OTConstants.h" #import "keychain/ot/OTDefines.h" #import "keychain/ot/OctagonCKKSPeerAdapter.h" @@ -81,31 +87,17 @@ #include "keychain/securityd/SecItemDb.h" #include "keychain/securityd/SecItemSchema.h" #include "keychain/securityd/SecItemServer.h" -#include #include #include "keychain/SecureObjectSync/SOSAccountTransaction.h" -#include #include #include +#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h" +#import + #if OCTAGON @interface CKKSKeychainView() -@property bool keyStateFetchRequested; -@property bool keyStateProcessRequested; -@property bool trustedPeersSetChanged; - -@property bool keyStateCloudKitDeleteRequested; -@property NSHashTable* cloudkitDeleteZoneOperations; - -@property bool keyStateLocalResetRequested; -@property NSHashTable* localResetOperations; - -@property bool tlkCreationRequested; -@property NSHashTable*>* keysetProviderOperations; - - -@property (atomic) NSString *activeTLK; @property (readonly) Class notifierClass; @@ -121,10 +113,16 @@ // Scratch space for resyncs @property (nullable) NSMutableSet* resyncRecordsSeen; + + +@property NSOperationQueue* operationQueue; +@property CKKSResultOperation* accountLoggedInDependency; +@property BOOL halted; + // Make these readwrite -@property NSArray>* currentPeerProviders; @property NSArray* currentTrustStates; +@property NSMutableSet* currentFetchReasons; @end #endif @@ -142,31 +140,43 @@ cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies { - if(self = [super initWithContainer:container - zoneName:zoneName - accountTracker:accountTracker - reachabilityTracker:reachabilityTracker - zoneModifier:zoneModifier - cloudKitClassDependencies:cloudKitClassDependencies]) { + if((self = [super init])) { WEAKIFY(self); + _container = container; + _zoneName = zoneName; + _accountTracker = accountTracker; + _reachabilityTracker = reachabilityTracker; + _cloudKitClassDependencies = cloudKitClassDependencies; + + _halted = NO; + + _database = [_container privateCloudDatabase]; + _zoneID = [[CKRecordZoneID alloc] initWithZoneName:zoneName ownerName:CKCurrentUserDefaultName]; + + _accountStatus = CKKSAccountStatusUnknown; + _accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in."]; + + _queue = dispatch_queue_create([[NSString stringWithFormat:@"CKKSQueue.%@.zone.%@", container.containerIdentifier, zoneName] UTF8String], DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + _operationQueue = [[NSOperationQueue alloc] init]; + + _loggedIn = [[CKKSCondition alloc] init]; _loggedOut = [[CKKSCondition alloc] init]; _accountStateKnown = [[CKKSCondition alloc] init]; + _initiatedLocalScan = NO; + _trustStatus = CKKSAccountStatusUnknown; - _trustDependency = [CKKSResultOperation named:@"wait-for-trust" withBlock:^{}]; _incomingQueueOperations = [NSHashTable weakObjectsHashTable]; _outgoingQueueOperations = [NSHashTable weakObjectsHashTable]; _scanLocalItemsOperations = [NSHashTable weakObjectsHashTable]; - _cloudkitDeleteZoneOperations = [NSHashTable weakObjectsHashTable]; - _localResetOperations = [NSHashTable weakObjectsHashTable]; - _keysetProviderOperations = [NSHashTable weakObjectsHashTable]; - _currentPeerProviders = @[]; _currentTrustStates = @[]; + _currentFetchReasons = [NSMutableSet set]; + _launch = [[CKKSLaunchSequence alloc] initWithRocketName:@"com.apple.security.ckks.launch"]; [_launch addAttribute:@"view" value:zoneName]; @@ -184,6 +194,8 @@ block:^{ STRONGIFY(self); [self.notifierClass post:[NSString stringWithFormat:@"com.apple.security.view-change.%@", self.zoneName]]; + [self.notifierClass post:[NSString stringWithUTF8String:kSecServerKeychainChangedNotification]]; + // Ugly, but: the Manatee and Engram views need to send a fake 'PCS' view change. // TODO: make this data-driven somehow @@ -213,29 +225,20 @@ _lockStateTracker = lockStateTracker; - _savedTLKNotifier = savedTLKNotifier; - - _keyHierarchyConditions = [[NSMutableDictionary alloc] init]; - [CKKSZoneKeyStateMap() enumerateKeysAndObjectsUsingBlock:^(CKKSZoneKeyState * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) { - [self.keyHierarchyConditions setObject: [[CKKSCondition alloc] init] forKey:key]; - }]; - - // Use the keyHierarchyState setter to modify the zone key state map - self.keyHierarchyState = SecCKKSZoneKeyStateLoggedOut; - _keyHierarchyError = nil; - _keyHierarchyOperationGroup = nil; - _keyStateMachineOperation = nil; - _keyStateFetchRequested = false; - _keyStateProcessRequested = false; - _tlkCreationRequested = false; + _stateMachine = [[OctagonStateMachine alloc] initWithName:[NSString stringWithFormat:@"ckks-%@", self.zoneName] + states:[NSSet setWithArray:[CKKSZoneKeyStateMap() allKeys]] + flags:CKKSAllStateFlags() + initialState:SecCKKSZoneKeyStateWaitForCloudKitAccountStatus + queue:self.queue + stateEngine:self + lockStateTracker:lockStateTracker]; + [_stateMachine startOperation]; _waitingQueue = [[NSOperationQueue alloc] init]; _waitingQueue.maxConcurrentOperationCount = 5; - _keyStateReadyDependency = [self createKeyStateReadyDependency: @"Key state has become ready for the first time." ckoperationGroup:[CKOperationGroup CKKSGroupWithName:@"initial-key-state-ready-scan"]]; - - _keyStateNonTransientDependency = [self createKeyStateNontransientDependency]; + _keyStateReadyDependency = [self createKeyStateReadyDependency: @"Key state has become ready for the first time."]; dispatch_time_t initialOutgoingQueueDelay = SecCKKSReduceRateLimiting() ? NSEC_PER_MSEC * 200 : NSEC_PER_SEC * 1; dispatch_time_t continuingOutgoingQueueDelay = SecCKKSReduceRateLimiting() ? NSEC_PER_MSEC * 200 : NSEC_PER_SEC * 30; @@ -246,23 +249,17 @@ dependencyDescriptionCode:CKKSResultDescriptionPendingOutgoingQueueScheduling block:^{}]; - - dispatch_time_t initialKeyHierachyPokeDelay = SecCKKSReduceRateLimiting() ? NSEC_PER_MSEC * 100 : NSEC_PER_MSEC * 500; - dispatch_time_t continuingKeyHierachyPokeDelay = SecCKKSReduceRateLimiting() ? NSEC_PER_MSEC * 200 : NSEC_PER_SEC * 5; - _pokeKeyStateMachineScheduler = [[CKKSNearFutureScheduler alloc] initWithName:[NSString stringWithFormat: @"%@-reprocess-scheduler", self.zoneName] - initialDelay:initialKeyHierachyPokeDelay - continuingDelay:continuingKeyHierachyPokeDelay - keepProcessAlive:true - dependencyDescriptionCode:CKKSResultDescriptionPendingKeyHierachyPokeScheduling - block:^{ - STRONGIFY(self); - [self dispatchSyncWithAccountKeys: ^bool{ - STRONGIFY(self); - - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; - }]; - }]; + _operationDependencies = [[CKKSOperationDependencies alloc] initWithZoneID:self.zoneID + zoneModifier:zoneModifier + ckoperationGroup:nil + flagHandler:_stateMachine + launchSequence:_launch + lockStateTracker:_lockStateTracker + reachabilityTracker:reachabilityTracker + peerProviders:@[] + databaseProvider:self + notifyViewChangedScheduler:_notifyViewChangedScheduler + savedTLKNotifier:savedTLKNotifier]; } return self; } @@ -276,427 +273,201 @@ } - (CKKSZoneKeyState*)keyHierarchyState { - return _keyHierarchyState; -} - -- (void)setKeyHierarchyState:(CKKSZoneKeyState *)keyHierarchyState { - if((keyHierarchyState == nil && _keyHierarchyState == nil) || ([keyHierarchyState isEqualToString:_keyHierarchyState])) { - // No change, do nothing. - } else { - // Fixup the condition variables as part of setting this state - if(_keyHierarchyState) { - self.keyHierarchyConditions[_keyHierarchyState] = [[CKKSCondition alloc] init]; - } - - _keyHierarchyState = keyHierarchyState; - - if(keyHierarchyState) { - [self.keyHierarchyConditions[keyHierarchyState] fulfill]; - } - } + return self.stateMachine.currentState; } -- (NSString *)lastActiveTLKUUID +- (NSMutableDictionary*)keyHierarchyConditions { - return self.activeTLK; -} - -- (void)_onqueueResetSetup:(CKKSZoneKeyState*)newState resetMessage:(NSString*)resetMessage ckoperationGroup:(CKOperationGroup*)group { - [super resetSetup]; - - self.keyHierarchyState = newState; - self.keyHierarchyError = nil; - - [self.keyStateMachineOperation cancel]; - self.keyStateMachineOperation = nil; - - self.keyStateFetchRequested = false; - self.keyStateProcessRequested = false; - - self.keyHierarchyOperationGroup = group; - - [self ensureKeyStateReadyDependency:resetMessage]; - - NSOperation* oldKSNTD = self.keyStateNonTransientDependency; - self.keyStateNonTransientDependency = [self createKeyStateNontransientDependency]; - if(oldKSNTD) { - [oldKSNTD addDependency:self.keyStateNonTransientDependency]; - [self.waitingQueue addOperation:oldKSNTD]; - } + return self.stateMachine.stateConditions; } - (void)ensureKeyStateReadyDependency:(NSString*)resetMessage { NSOperation* oldKSRD = self.keyStateReadyDependency; - self.keyStateReadyDependency = [self createKeyStateReadyDependency:resetMessage ckoperationGroup:self.keyHierarchyOperationGroup]; + self.keyStateReadyDependency = [self createKeyStateReadyDependency:resetMessage]; if(oldKSRD) { [oldKSRD addDependency:self.keyStateReadyDependency]; [self.waitingQueue addOperation:oldKSRD]; } } -- (CKKSResultOperation*)createPendingInitializationOperation { - +- (CKKSResultOperation*)performInitializedOperation +{ WEAKIFY(self); - CKKSResultOperation* initializationOp = [CKKSGroupOperation named:@"view-initialization" withBlockTakingSelf:^(CKKSGroupOperation * _Nonnull strongOp) { + return [OctagonStateTransitionOperation named:@"ckks-initialized-operation" + intending:SecCKKSZoneKeyStateBecomeReady + errorState:SecCKKSZoneKeyStateError + withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { STRONGIFY(self); + [self dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + CKKSOutgoingQueueOperation* outgoingOperation = nil; + CKKSIncomingQueueOperation* initialProcess = nil; + CKKSScanLocalItemsOperation* initialScan = nil; - __block CKKSResultOperation* zoneCreationOperation = nil; - [self dispatchSync:^bool { - CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state: self.zoneName]; - zoneCreationOperation = [self handleCKLogin:ckse.ckzonecreated zoneSubscribed:ckse.ckzonesubscribed]; - return true; - }]; - - CKKSResultOperation* viewInitializationOperation = [CKKSResultOperation named:@"view-initialization" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull strongInternalOp) { - STRONGIFY(self); - if(!self) { - ckkserror("ckks", self, "received callback for released object"); - return; - } - - [self dispatchSyncWithAccountKeys: ^bool { - ckksnotice("ckks", self, "Zone setup progress: %@ %d %@ %d %@", - [CKKSAccountStateTracker stringFromAccountStatus:self.accountStatus], - self.zoneCreated, self.zoneCreatedError, self.zoneSubscribed, self.zoneSubscribedError); - - NSError* error = nil; - CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state: self.zoneName]; - ckse.ckzonecreated = self.zoneCreated; - ckse.ckzonesubscribed = self.zoneSubscribed; - - // Although, if the zone subscribed error says there's no zone, mark down that there's no zone - if(self.zoneSubscribedError && - [self.zoneSubscribedError.domain isEqualToString:CKErrorDomain] && self.zoneSubscribedError.code == CKErrorPartialFailure) { - NSError* subscriptionError = self.zoneSubscribedError.userInfo[CKPartialErrorsByItemIDKey][self.zoneID]; - if(subscriptionError && [subscriptionError.domain isEqualToString:CKErrorDomain] && subscriptionError.code == CKErrorZoneNotFound) { - - ckkserror("ckks", self, "zone subscription error appears to say the zone doesn't exist, fixing status: %@", self.zoneSubscribedError); - ckse.ckzonecreated = false; - } - } - - [ckse saveToDatabase: &error]; - if(error) { - ckkserror("ckks", self, "couldn't save zone creation status for %@: %@", self.zoneName, error); - } - - if(!self.zoneCreated || !self.zoneSubscribed) { - // Go into 'zonecreationfailed' - strongInternalOp.error = self.zoneCreatedError ? self.zoneCreatedError : self.zoneSubscribedError; - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateZoneCreationFailed withError:strongInternalOp.error]; - - return true; - } else { - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateInitialized withError:nil]; - } + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.zoneName]; - return true; - }]; - }]; + // Check if we believe we've synced this zone before. + if(ckse.changeToken == nil) { + self.operationDependencies.ckoperationGroup = [CKOperationGroup CKKSGroupWithName:@"initial-setup"]; - [viewInitializationOperation addDependency:zoneCreationOperation]; - [strongOp runBeforeGroupFinished:viewInitializationOperation]; - }]; + ckksnotice("ckks", self, "No existing change token; going to try to match local items with CloudKit ones."); - return initializationOp; -} + // Onboard this keychain: there's likely items in it that we haven't synced yet. + // But, there might be items in The Cloud that correspond to these items, with UUIDs that we don't know yet. + // First, fetch all remote items. -- (void)_onqueuePerformKeyStateInitialized:(CKKSZoneStateEntry*)ckse { - CKKSOutgoingQueueOperation* outgoingOperation = nil; - NSOperation* initialProcess = nil; + [self.currentFetchReasons addObject:CKKSFetchBecauseInitialStart]; + op.nextState = SecCKKSZoneKeyStateBeginFetch; - // Check if we believe we've synced this zone before. - if(ckse.changeToken == nil) { - self.keyHierarchyOperationGroup = [CKOperationGroup CKKSGroupWithName:@"initial-setup"]; + // Next, try to process them (replacing local entries). This will wait for the key state to be ready. + initialProcess = [self processIncomingQueue:true after:nil]; - ckksnotice("ckks", self, "No existing change token; going to try to match local items with CloudKit ones."); + // If all that succeeds, iterate through all keychain items and find the ones which need to be uploaded + initialScan = [self scanLocalItems:@"initial-scan-operation" + ckoperationGroup:self.operationDependencies.ckoperationGroup + after:initialProcess]; - // Onboard this keychain: there's likely items in it that we haven't synced yet. - // But, there might be items in The Cloud that correspond to these items, with UUIDs that we don't know yet. - // First, fetch all remote items. - CKKSResultOperation* fetch = [self.zoneChangeFetcher requestSuccessfulFetch:CKKSFetchBecauseInitialStart]; - fetch.name = @"initial-fetch"; + } else { + // Likely a restart of securityd! + + // Are there any fixups to run first? + self.lastFixupOperation = [CKKSFixups fixup:ckse.lastFixup for:self]; + if(self.lastFixupOperation) { + ckksnotice("ckksfixup", self, "We have a fixup to perform: %@", self.lastFixupOperation); + [self scheduleOperation:self.lastFixupOperation]; + op.nextState = SecCKKSZoneKeyStateWaitForFixupOperation; + return CKKSDatabaseTransactionCommit; + } - // Next, try to process them (replacing local entries) - initialProcess = [self processIncomingQueue:true after:fetch]; - initialProcess.name = @"initial-process-incoming-queue"; + // First off, are there any in-flight queue entries? If so, put them back into New. + // If they're truly in-flight, we'll "conflict" with ourselves, but that should be fine. + NSError* error = nil; + [self _onqueueResetAllInflightOQE:&error]; + if(error) { + ckkserror("ckks", self, "Couldn't reset in-flight OQEs, bad behavior ahead: %@", error); + } - // If all that succeeds, iterate through all keychain items and find the ones which need to be uploaded - self.initialScanOperation = [self scanLocalItems:@"initial-scan-operation" - ckoperationGroup:self.keyHierarchyOperationGroup - after:initialProcess]; + // Are there any entries waiting for reencryption? If so, set the flag. + error = nil; + NSArray* reencryptOQEs = [CKKSOutgoingQueueEntry allInState:SecCKKSStateReencrypt + zoneID:self.zoneID + error:&error]; + if(error) { + ckkserror("ckks", self, "Couldn't load reencrypt OQEs, bad behavior ahead: %@", error); + } + if(reencryptOQEs.count > 0) { + [self.stateMachine _onqueueHandleFlag:CKKSFlagItemReencryptionNeeded]; + } - } else { - // Likely a restart of securityd! + self.operationDependencies.ckoperationGroup = [CKOperationGroup CKKSGroupWithName:@"restart-setup"]; - // First off, are there any in-flight queue entries? If so, put them back into New. - // If they're truly in-flight, we'll "conflict" with ourselves, but that should be fine. - NSError* error = nil; - [self _onqueueResetAllInflightOQE:&error]; - if(error) { - ckkserror("ckks", self, "Couldn't reset in-flight OQEs, bad behavior ahead: %@", error); - } + // If it's been more than 24 hours since the last fetch, fetch and process everything. + // Or, if we think we were interrupted in the middle of fetching, fetch some more. + // Otherwise, just kick off the local queue processing. - // Are there any fixups to run first? - self.lastFixupOperation = [CKKSFixups fixup:ckse.lastFixup for:self]; - if(self.lastFixupOperation) { - ckksnotice("ckksfixup", self, "We have a fixup to perform: %@", self.lastFixupOperation); - [self scheduleOperation:self.lastFixupOperation]; - } + NSDate* now = [NSDate date]; + NSDateComponents* offset = [[NSDateComponents alloc] init]; + [offset setHour:-24]; + NSDate* deadline = [[NSCalendar currentCalendar] dateByAddingComponents:offset toDate:now options:0]; - self.keyHierarchyOperationGroup = [CKOperationGroup CKKSGroupWithName:@"restart-setup"]; + if(ckse.lastFetchTime == nil || + [ckse.lastFetchTime compare: deadline] == NSOrderedAscending || + ckse.moreRecordsInCloudKit) { - if ([CKKSManifest shouldSyncManifests]) { - self.egoManifest = [CKKSEgoManifest tryCurrentEgoManifestForZone:self.zoneName]; - } + op.nextState = SecCKKSZoneKeyStateBeginFetch; - // If it's been more than 24 hours since the last fetch, fetch and process everything. - // Or, if we think we were interrupted in the middle of fetching, fetch some more. - // Otherwise, just kick off the local queue processing. + } else { + // Check if we have an existing key hierarchy in keyset + CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; + if(keyset.error && !([keyset.error.domain isEqual: @"securityd"] && keyset.error.code == errSecItemNotFound)) { + ckkserror("ckkskey", self, "Error examining existing key hierarchy: %@", keyset.error); + } - NSDate* now = [NSDate date]; - NSDateComponents* offset = [[NSDateComponents alloc] init]; - [offset setHour:-24]; - NSDate* deadline = [[NSCalendar currentCalendar] dateByAddingComponents:offset toDate:now options:0]; + if(keyset.tlk && keyset.classA && keyset.classC && !keyset.error) { + // This is likely a restart of securityd, and we think we're ready. Double check. + op.nextState = SecCKKSZoneKeyStateBecomeReady; - if(ckse.lastFetchTime == nil || - [ckse.lastFetchTime compare: deadline] == NSOrderedAscending || - ckse.moreRecordsInCloudKit) { - initialProcess = [self fetchAndProcessCKChanges:CKKSFetchBecauseSecuritydRestart after:self.lastFixupOperation]; + } else { + ckksnotice("ckkskey", self, "No existing key hierarchy for %@. Check if there's one in CloudKit...", self.zoneID.zoneName); + op.nextState = SecCKKSZoneKeyStateBeginFetch; + } + } - // Also, kick off a scan local items: it'll find any out-of-sync issues in the local keychain - self.initialScanOperation = [self scanLocalItems:@"24-hr-scan-operation" - ckoperationGroup:self.keyHierarchyOperationGroup - after:initialProcess]; - } else { - initialProcess = [self processIncomingQueue:false after:self.lastFixupOperation]; - } + if(ckse.lastLocalKeychainScanTime == nil || [ckse.lastLocalKeychainScanTime compare:deadline] == NSOrderedAscending) { + // TODO handle with a state flow + ckksnotice("ckksscan", self, "CKKS scan last occurred at %@; beginning a new one", ckse.lastLocalKeychainScanTime); + initialScan = [self scanLocalItems:ckse.lastLocalKeychainScanTime == nil ? @"initial-scan-operation" : @"24-hr-scan-operation" + ckoperationGroup:self.operationDependencies.ckoperationGroup + after:nil]; + } - if([CKKSManifest shouldSyncManifests]) { - if (!self.egoManifest && !self.initialScanOperation) { - ckksnotice("ckksmanifest", self, "No ego manifest on restart; rescanning"); - self.initialScanOperation = [self scanLocalItems:@"initial-scan-operation" - ckoperationGroup:self.keyHierarchyOperationGroup - after:initialProcess]; + // Process outgoing queue after re-start + outgoingOperation = [self processOutgoingQueueAfter:nil ckoperationGroup:self.operationDependencies.ckoperationGroup]; } - } - - // Process outgoing queue after re-start - outgoingOperation = [self processOutgoingQueueAfter:self.lastFixupOperation ckoperationGroup:self.keyHierarchyOperationGroup]; - } - - /* - * Launch time is determined by when the zone have: - * 1. keystate have become ready - * 2. scan local items (if needed) - * 3. processed all outgoing item (if needed) - */ - - WEAKIFY(self); - NSBlockOperation *seemReady = [NSBlockOperation named:[NSString stringWithFormat:@"seemsReadyForSyncing-%@", self.zoneName] withBlock:^void{ - STRONGIFY(self); - NSError *error = nil; - ckksnotice("launch", self, "Launch complete"); - NSNumber *zoneSize = [CKKSMirrorEntry counts:self.zoneID error:&error]; - if (zoneSize) { - zoneSize = @(SecBucket1Significant([zoneSize longValue])); - [self.launch addAttribute:@"zonesize" value:zoneSize]; - } - [self.launch launch]; - - /* - * Since we think we are ready, signal to CK that its to check for PCS identities again, and create the - * since before we completed this operation, we would probably have failed with a timeout because - * we where busy downloading items from CloudKit and then processing them. - */ - [self.notifyViewReadyScheduler trigger]; - }]; - - [seemReady addNullableDependency:self.keyStateReadyDependency]; - [seemReady addNullableDependency:outgoingOperation]; - [seemReady addNullableDependency:self.initialScanOperation]; - [seemReady addNullableDependency:initialProcess]; - - [self scheduleOperation: seemReady]; -} - -- (bool)_onqueueResetLocalData: (NSError * __autoreleasing *) error { - dispatch_assert_queue(self.queue); - - NSError* localerror = nil; - bool setError = false; // Ugly, but this is the only way to return the first error given - - CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state: self.zoneName]; - ckse.ckzonecreated = false; - ckse.ckzonesubscribed = false; // I'm actually not sure about this: can you be subscribed to a non-existent zone? - ckse.changeToken = NULL; - [ckse saveToDatabase: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't reset zone status for %@: %@", self.zoneName, localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSMirrorEntry deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSMirrorEntry: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSOutgoingQueueEntry deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSOutgoingQueueEntry: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSIncomingQueueEntry deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSIncomingQueueEntry: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSKey deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSKey: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - [CKKSTLKShareRecord deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSTLKShare: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSCurrentKeyPointer deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSCurrentKeyPointer: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSCurrentItemPointer deleteAll:self.zoneID error: &localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSCurrentItemPointer: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - [CKKSDeviceStateEntry deleteAll:self.zoneID error:&localerror]; - if(localerror) { - ckkserror("ckks", self, "couldn't delete all CKKSDeviceStateEntry: %@", localerror); - if(error && !setError) { - *error = localerror; setError = true; - } - } - - return (localerror == nil && !setError); -} + /* + * Launch time is determined by when the zone have: + * 1. keystate have become ready + * 2. scan local items (if needed) + * 3. processed all outgoing item (if needed) + * TODO: this should move, once queue processing becomes part of the state machine + */ -- (CKKSResultOperation*)createPendingResetLocalDataOperation { - @synchronized(self.localResetOperations) { - CKKSResultOperation* pendingResetLocalOperation = (CKKSResultOperation*) [self findFirstPendingOperation:self.localResetOperations]; - if(!pendingResetLocalOperation) { WEAKIFY(self); - pendingResetLocalOperation = [CKKSResultOperation named:@"reset-local" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull strongOp) { + NSBlockOperation *seemReady = [NSBlockOperation named:[NSString stringWithFormat:@"seemsReadyForSyncing-%@", self.zoneName] withBlock:^void{ STRONGIFY(self); - __block NSError* error = nil; - - [self dispatchSync: ^bool{ - [self _onqueueResetLocalData: &error]; - return true; - }]; - - strongOp.error = error; - }]; - [pendingResetLocalOperation linearDependencies:self.localResetOperations]; - } - return pendingResetLocalOperation; - } -} - -- (CKKSResultOperation*)resetLocalData { - // Not overly thread-safe, but a single read is okay - CKKSAccountStatus accountStatus = self.accountStatus; - ckksnotice("ckksreset", self, "Requesting local data reset"); - - // If we're currently signed in, the reset operation will be handled by the CKKS key state machine, and a reset should end up in 'ready' - if(accountStatus == CKKSAccountStatusAvailable) { - WEAKIFY(self); - CKKSGroupOperation* resetOperationGroup = [CKKSGroupOperation named:@"local-reset" withBlockTakingSelf:^(CKKSGroupOperation *strongOp) { - STRONGIFY(self); - - __block CKKSResultOperation* resetOperation = nil; - - [self dispatchSyncWithAccountKeys:^bool { - self.keyStateLocalResetRequested = true; - resetOperation = [self createPendingResetLocalDataOperation]; - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; + NSError *error = nil; + ckksnotice("launch", self, "Launch complete"); + NSNumber *zoneSize = [CKKSMirrorEntry counts:self.zoneID error:&error]; + if (zoneSize) { + zoneSize = @(SecBucket1Significant([zoneSize longValue])); + [self.launch addAttribute:@"zonesize" value:zoneSize]; + } + [self.launch launch]; + + /* + * Since we think we are ready, signal to CK that its to check for PCS identities again, and create the + * since before we completed this operation, we would probably have failed with a timeout because + * we where busy downloading items from CloudKit and then processing them. + */ + [self.notifyViewReadyScheduler trigger]; }]; - [strongOp dependOnBeforeGroupFinished:resetOperation]; - }]; - [self scheduleOperationWithoutDependencies:resetOperationGroup]; - - CKKSGroupOperation* viewReset = [CKKSGroupOperation named:@"local-data-reset" withBlockTakingSelf:^(CKKSGroupOperation *strongOp) { - STRONGIFY(self); - // Now that the local reset finished, wait for the key hierarchy state machine to churn - ckksnotice("ckksreset", self, "waiting for key hierarchy to become nontransient (after local reset)"); - CKKSResultOperation* waitOp = [CKKSResultOperation named:@"waiting-for-local-reset" withBlock:^{}]; - [waitOp timeout: 60*NSEC_PER_SEC]; - [waitOp addNullableDependency:self.keyStateNonTransientDependency]; - - [strongOp runBeforeGroupFinished:waitOp]; - }]; - [viewReset addSuccessDependency:resetOperationGroup]; - - [self scheduleOperationWithoutDependencies:viewReset]; - return viewReset; - } else { - // Since we're logged out, we must run the reset ourselves - WEAKIFY(self); - CKKSResultOperation* pendingResetLocalOperation = [CKKSResultOperation named:@"reset-local" - withBlockTakingSelf:^(CKKSResultOperation * _Nonnull strongOp) { - STRONGIFY(self); - __block NSError* error = nil; - - [self dispatchSync: ^bool{ - [self _onqueueResetLocalData: &error]; - return true; - }]; + [seemReady addNullableDependency:self.keyStateReadyDependency]; + [seemReady addNullableDependency:outgoingOperation]; + [seemReady addNullableDependency:initialScan]; + [seemReady addNullableDependency:initialProcess]; + [self scheduleOperation:seemReady]; - strongOp.error = error; + return CKKSDatabaseTransactionCommit; }]; - [self scheduleOperationWithoutDependencies:pendingResetLocalOperation]; - return pendingResetLocalOperation; - } + }]; } -- (CKKSResultOperation*)createPendingDeleteZoneOperation:(CKOperationGroup*)operationGroup { - @synchronized(self.cloudkitDeleteZoneOperations) { - CKKSResultOperation* pendingDeleteOperation = (CKKSResultOperation*) [self findFirstPendingOperation:self.cloudkitDeleteZoneOperations]; - if(!pendingDeleteOperation) { - pendingDeleteOperation = [self deleteCloudKitZoneOperation:operationGroup]; - [pendingDeleteOperation linearDependencies:self.cloudkitDeleteZoneOperations]; - } - return pendingDeleteOperation; - } -} +- (CKKSResultOperation*)resetLocalData { + ckksnotice("ckksreset", self, "Requesting local data reset"); -- (CKKSResultOperation*)resetCloudKitZone:(CKOperationGroup*)operationGroup { + return [self.stateMachine doWatchedStateMachineRPC:@"ckks-local-reset" + sourceStates:[NSSet setWithArray:@[ + // TODO: possibly every state? + SecCKKSZoneKeyStateReady, + SecCKKSZoneKeyStateWaitForTLK, + SecCKKSZoneKeyStateWaitForTrust, + SecCKKSZoneKeyStateWaitForTLKUpload, + SecCKKSZoneKeyStateLoggedOut, + ]] + path:[OctagonStateTransitionPath pathFromDictionary:@{ + SecCKKSZoneKeyStateResettingLocalData: @{ + SecCKKSZoneKeyStateInitializing: @{ + SecCKKSZoneKeyStateInitialized: [OctagonStateTransitionPathStep success], + SecCKKSZoneKeyStateLoggedOut: [OctagonStateTransitionPathStep success], + } + } + }] + reply:^(NSError * _Nonnull error) {}]; +} + +- (CKKSResultOperation*)resetCloudKitZone:(CKOperationGroup*)operationGroup +{ [self.accountStateKnown wait:(SecCKKSTestsEnabled() ? 1*NSEC_PER_SEC : 10*NSEC_PER_SEC)]; // Not overly thread-safe, but a single read is okay @@ -713,781 +484,633 @@ return errorOp; } - // Actually running the delete operation will be handled by the CKKS key state machine ckksnotice("ckksreset", self, "Requesting reset of CK zone (logged in)"); - - __block CKKSResultOperation* deleteOperation = nil; - [self dispatchSyncWithAccountKeys:^bool { - self.keyStateCloudKitDeleteRequested = true; - deleteOperation = [self createPendingDeleteZoneOperation:operationGroup]; - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; - }]; - - WEAKIFY(self); - CKKSGroupOperation* viewReset = [CKKSGroupOperation named:[NSString stringWithFormat:@"cloudkit-view-reset-%@", self.zoneName] - withBlockTakingSelf:^(CKKSGroupOperation *strongOp) { - STRONGIFY(self); - // Now that the delete finished, wait for the key hierarchy state machine - ckksnotice("ckksreset", self, "waiting for key hierarchy to become nontransient (after cloudkit reset)"); - CKKSResultOperation* waitOp = [CKKSResultOperation named:@"waiting-for-reset" withBlock:^{}]; - [waitOp timeout: 60*NSEC_PER_SEC]; - [waitOp addNullableDependency:self.keyStateNonTransientDependency]; - - [strongOp runBeforeGroupFinished:waitOp]; - }]; - - [viewReset timeout:30*NSEC_PER_SEC]; - [viewReset addDependency:deleteOperation]; - [self.waitingQueue addOperation:viewReset]; - - return viewReset; -} -- (void)_onqueueKeyStateMachineRequestFetch { - dispatch_assert_queue(self.queue); - - // We're going to set this flag, then nudge the key state machine. - // If it was idle, then it should launch a fetch. If there was an active process, this flag will stay high - // and the fetch will be launched later. - - self.keyStateFetchRequested = true; - [self _onqueueAdvanceKeyStateMachineToState: nil withError: nil]; + NSDictionary* localResetPath = @{ + SecCKKSZoneKeyStateInitializing: @{ + SecCKKSZoneKeyStateInitialized: [OctagonStateTransitionPathStep success], + SecCKKSZoneKeyStateLoggedOut: [OctagonStateTransitionPathStep success], + }, + }; + + // If the zone delete doesn't work, try it up to two more times + + return [self.stateMachine doWatchedStateMachineRPC:@"ckks-cloud-reset" + sourceStates:[NSSet setWithArray:@[ + // TODO: possibly every state? + SecCKKSZoneKeyStateReady, + SecCKKSZoneKeyStateInitialized, + SecCKKSZoneKeyStateFetchComplete, + SecCKKSZoneKeyStateWaitForTLK, + SecCKKSZoneKeyStateWaitForTrust, + SecCKKSZoneKeyStateWaitForTLKUpload, + SecCKKSZoneKeyStateLoggedOut, + ]] + path:[OctagonStateTransitionPath pathFromDictionary:@{ + SecCKKSZoneKeyStateResettingZone: @{ + SecCKKSZoneKeyStateResettingLocalData: localResetPath, + SecCKKSZoneKeyStateResettingZone: @{ + SecCKKSZoneKeyStateResettingLocalData: localResetPath, + SecCKKSZoneKeyStateResettingZone: @{ + SecCKKSZoneKeyStateResettingLocalData: localResetPath, + } + } + } + }] + reply:^(NSError * _Nonnull error) {}]; } - (void)keyStateMachineRequestProcess { - // Since bools are atomic, we don't need to get on-queue here - // Just set the flag high and hope - self.keyStateProcessRequested = true; - [self.pokeKeyStateMachineScheduler trigger]; -} - -- (void)_onqueueKeyStateMachineRequestProcess { - dispatch_assert_queue(self.queue); - - // Set the request flag, then nudge the key state machine. - // If it was idle, then it should launch a process. If there was an active process, this flag will stay high - // and the process will be launched later. - - self.keyStateProcessRequested = true; - [self _onqueueAdvanceKeyStateMachineToState: nil withError: nil]; + [self.stateMachine handleFlag:CKKSFlagKeyStateProcessRequested]; } -- (CKKSResultOperation*)createKeyStateReadyDependency:(NSString*)message ckoperationGroup:(CKOperationGroup*)group { +- (CKKSResultOperation*)createKeyStateReadyDependency:(NSString*)message { WEAKIFY(self); CKKSResultOperation* keyStateReadyDependency = [CKKSResultOperation operationWithBlock:^{ STRONGIFY(self); - if(!self) { - return; - } - ckksnotice("ckkskey", self, "%@", message); - - [self dispatchSync:^bool { - if(self.droppedItems) { - // While we weren't in 'ready', keychain modifications might have come in and were dropped on the floor. Find them! - ckksnotice("ckkskey", self, "Launching scan operation for missed items"); - [self scanLocalItems:@"ready-again-scan" ckoperationGroup:group after:nil]; - } - return true; - }]; + ckksnotice("ckkskey", self, "CKKS became ready: %@", message); }]; keyStateReadyDependency.name = [NSString stringWithFormat: @"%@-key-state-ready", self.zoneName]; keyStateReadyDependency.descriptionErrorCode = CKKSResultDescriptionPendingKeyReady; return keyStateReadyDependency; } -- (CKKSResultOperation*)createKeyStateNontransientDependency { - WEAKIFY(self); - return [CKKSResultOperation named:[NSString stringWithFormat: @"%@-key-state-nontransient", self.zoneName] withBlock:^{ - STRONGIFY(self); - ckksnotice("ckkskey", self, "Key state is now non-transient"); - }]; +- (void)_onqueuePokeKeyStateMachine +{ + dispatch_assert_queue(self.queue); + [self.stateMachine _onqueuePokeStateMachine]; } -// The operations suggested by this state machine should call _onqueueAdvanceKeyStateMachineToState once they are complete. -// At no other time should keyHierarchyState be modified. - -// Note that this function cannot rely on doing any database work; it might get rolled back, especially in an error state -- (void)_onqueueAdvanceKeyStateMachineToState: (CKKSZoneKeyState*) state withError: (NSError*) error { +- (CKKSResultOperation* _Nullable)_onqueueNextStateMachineTransition:(OctagonState*)currentState + flags:(OctagonFlags*)flags + pendingFlags:(id)pendingFlagHandler +{ dispatch_assert_queue(self.queue); - WEAKIFY(self); // Resetting back to 'loggedout' takes all precedence. - if([state isEqual:SecCKKSZoneKeyStateLoggedOut]) { - ckksnotice("ckkskey", self, "Resetting the key hierarchy state machine back to '%@'", state); + if([flags _onqueueContains:CKKSFlagCloudKitLoggedOut]) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedOut]; + ckksnotice("ckkskey", self, "CK account is not present"); - [self _onqueueResetSetup:SecCKKSZoneKeyStateLoggedOut - resetMessage:@"Key state has become ready for the first time (after reset)." - ckoperationGroup:[CKOperationGroup CKKSGroupWithName:@"key-state-after-logout"]]; + [self ensureKeyStateReadyDependency:@"cloudkit-account-not-present"]; + return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateLoggedOut + errorState:SecCKKSZoneKeyStateError]; + } - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - self.launch = nil; - return; + if([flags _onqueueContains:CKKSFlagCloudKitZoneMissing]) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitZoneMissing]; + + [self ensureKeyStateReadyDependency:@"cloudkit-zone-missing"]; + // The zone is gone! Let's reset our local state, which will feed into recreating the zone + return [OctagonStateTransitionOperation named:@"ck-zone-missing" + entering:SecCKKSZoneKeyStateResettingLocalData]; } - [self.launch addEvent:state]; + if([flags _onqueueContains:CKKSFlagChangeTokenExpired]) { + [flags _onqueueRemoveFlag:CKKSFlagChangeTokenExpired]; - // Resetting back to 'initialized' also takes precedence - if([state isEqual:SecCKKSZoneKeyStateInitializing]) { - ckksnotice("ckkskey", self, "Resetting the key hierarchy state machine back to '%@'", state); + [self ensureKeyStateReadyDependency:@"cloudkit-change-token-expired"]; + // Our change token is invalid! We'll have to refetch the world, so let's delete everything locally. + return [OctagonStateTransitionOperation named:@"ck-token-expired" + entering:SecCKKSZoneKeyStateResettingLocalData]; + } - [self _onqueueResetSetup:SecCKKSZoneKeyStateInitializing - resetMessage:@"Key state has become ready for the first time (after re-initializing)." - ckoperationGroup:[CKOperationGroup CKKSGroupWithName:@"key-state-reset-to-initializing"]]; + if([currentState isEqualToString:SecCKKSZoneKeyStateLoggedOut]) { + if([flags _onqueueContains:CKKSFlagCloudKitLoggedIn] || self.accountStatus == CKKSAccountStatusAvailable) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedIn]; - // Begin initialization, but rate-limit it - self.keyStateMachineOperation = [self createPendingInitializationOperation]; - [self.keyStateMachineOperation addNullableDependency:self.zoneModifier.cloudkitRetryAfter.operationDependency]; - [self.zoneModifier.cloudkitRetryAfter trigger]; - [self scheduleOperation:self.keyStateMachineOperation]; + ckksnotice("ckkskey", self, "CloudKit account now present"); + return [OctagonStateTransitionOperation named:@"ck-sign-in" + entering:SecCKKSZoneKeyStateInitializing]; + } - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; + if([flags _onqueueContains:CKKSFlag24hrNotification]) { + [flags _onqueueRemoveFlag:CKKSFlag24hrNotification]; + } + return nil; } - // Resetting to 'waitfortrust' also takes precedence - if([state isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) { - if([self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateLoggedOut]) { - ckksnotice("ckks", self, "Asked to waitfortrust, but we're already in loggedout. Ignoring..."); - return; + if([currentState isEqualToString: SecCKKSZoneKeyStateWaitForCloudKitAccountStatus]) { + if([flags _onqueueContains:CKKSFlagCloudKitLoggedIn] || self.accountStatus == CKKSAccountStatusAvailable) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedIn]; + + ckksnotice("ckkskey", self, "CloudKit account now present"); + return [OctagonStateTransitionOperation named:@"ck-sign-in" + entering:SecCKKSZoneKeyStateInitializing]; } - ckksnotice("ckks", self, "Entering waitfortrust"); - self.keyHierarchyState = SecCKKSZoneKeyStateWaitForTrust; - self.keyHierarchyError = nil; - self.keyStateMachineOperation = nil; + if([flags _onqueueContains:CKKSFlagCloudKitLoggedOut]) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedOut]; + ckksnotice("ckkskey", self, "No account available"); - [self ensureKeyStateReadyDependency:@"Key state has become ready for the first time (after lacking trust)."]; + return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateLoggedOut + errorState:SecCKKSZoneKeyStateError]; + } + return nil; + } - if(self.trustStatus == CKKSAccountStatusAvailable) { - // Note: we go to initialized here, since to enter waitfortrust CKKS has already gone through initializing - // initialized should refetch only if needed. - ckksnotice("ckks", self, "CKKS is trusted, moving to initialized"); - self.keyStateMachineOperation = [self operationToEnterState:SecCKKSZoneKeyStateInitialized - keyStateError:nil - named:@"re-enter initialized"]; - [self scheduleOperation:self.keyStateMachineOperation]; + [self.launch addEvent:currentState]; + + if([currentState isEqual:SecCKKSZoneKeyStateInitializing]) { + if(self.accountStatus == CKKSAccountStatusNoAccount) { + ckksnotice("ckkskey", self, "CloudKit account is missing. Departing!"); + return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateLoggedOut + errorState:SecCKKSZoneKeyStateError]; } - // In wait for trust, we might have a keyset. Who knows! - CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - [self _onqueueHandleKeyStateNonTransientDependency:keyset]; + // Begin zone creation, but rate-limit it + CKKSCreateCKZoneOperation* pendingInitializeOp = [[CKKSCreateCKZoneOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateInitialized + errorState:SecCKKSZoneKeyStateZoneCreationFailed]; + [pendingInitializeOp addNullableDependency:self.operationDependencies.zoneModifier.cloudkitRetryAfter.operationDependency]; + [self.operationDependencies.zoneModifier.cloudkitRetryAfter trigger]; - return; + return pendingInitializeOp; } - // Cancels and error states take precedence - if([self.keyHierarchyState isEqualToString: SecCKKSZoneKeyStateError] || - [self.keyHierarchyState isEqualToString: SecCKKSZoneKeyStateCancelled] || - self.keyHierarchyError != nil) { - // Error state: nowhere to go. Early-exit. - ckkserror("ckkskey", self, "Asked to advance state machine from non-exit state %@ (to %@): %@", self.keyHierarchyState, state, self.keyHierarchyError); - return; + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForFixupOperation]) { + // TODO: fixup operations should become part of the state machine + ckksnotice("ckkskey", self, "Waiting for the fixup operation: %@", self.lastFixupOperation); + OctagonStateTransitionOperation* op = [OctagonStateTransitionOperation named:@"wait-for-fixup" entering:SecCKKSZoneKeyStateInitialized]; + [op addNullableDependency:self.lastFixupOperation]; + return op; } - if([state isEqual: SecCKKSZoneKeyStateError]) { - // But wait! Is this a "we're locked" error? - if(error && [self.lockStateTracker isLockedError:error]) { - ckkserror("ckkskey", self, "advised of 'keychain locked' error, ignoring: coming from state (%@): %@", self.keyHierarchyState, error); - // After the next unlock, fake that we received the last zone transition - CKKSZoneKeyState* lastState = self.keyHierarchyState; - self.keyStateMachineOperation = [NSBlockOperation named:@"key-state-after-unlock" withBlock:^{ - STRONGIFY(self); - if(!self) { - return; - } - [self dispatchSyncWithAccountKeys:^bool{ - [self _onqueueAdvanceKeyStateMachineToState:lastState withError:nil]; - return true; - }]; - }]; - state = nil; - - self.keyHierarchyState = SecCKKSZoneKeyStateWaitForUnlock; + if([currentState isEqualToString:SecCKKSZoneKeyStateInitialized]) { + // We're initialized and CloudKit is ready. If we're trusted, see what needs done. Otherwise, wait. + return [self performInitializedOperation]; + } - [self.keyStateMachineOperation addNullableDependency:self.lockStateTracker.unlockDependency]; - [self scheduleOperation:self.keyStateMachineOperation]; + // In error? You probably aren't getting out. + if([currentState isEqualToString:SecCKKSZoneKeyStateError]) { + if([flags _onqueueContains:CKKSFlagCloudKitLoggedIn]) { + [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedIn]; - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; + // Worth one last shot. Reset everything locally, and try again. + return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateInitializing + errorState:SecCKKSZoneKeyStateError]; + } - } else { - // Error state: record the error and exit early - ckkserror("ckkskey", self, "advised of error: coming from state (%@): %@", self.keyHierarchyState, error); + ckkserror("ckkskey", self, "Staying in error state %@", currentState); + return nil; + } - [[CKKSAnalytics logger] logUnrecoverableError:error - forEvent:CKKSEventStateError - inView:self - withAttributes:@{ @"previousKeyHierarchyState" : self.keyHierarchyState }]; + if([currentState isEqualToString:SecCKKSZoneKeyStateResettingZone]) { + ckksnotice("ckkskey", self, "Deleting the CloudKit Zone"); + [self ensureKeyStateReadyDependency:@"ck-zone-reset"]; + return [[CKKSDeleteCKZoneOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateResettingLocalData + errorState:SecCKKSZoneKeyStateResettingZone]; + } - self.keyHierarchyState = SecCKKSZoneKeyStateError; - self.keyHierarchyError = error; + if([currentState isEqualToString:SecCKKSZoneKeyStateResettingLocalData]) { + ckksnotice("ckkskey", self, "Resetting local data"); - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; - } + [self ensureKeyStateReadyDependency:@"local-data-reset"]; + return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateInitializing + errorState:SecCKKSZoneKeyStateError]; } - if([state isEqual: SecCKKSZoneKeyStateCancelled]) { - ckkserror("ckkskey", self, "advised of cancel: coming from state (%@): %@", self.keyHierarchyState, error); - self.keyHierarchyState = SecCKKSZoneKeyStateCancelled; - self.keyHierarchyError = error; + if([currentState isEqualToString:SecCKKSZoneKeyStateZoneCreationFailed]) { + //Prepare to go back into initializing, as soon as the cloudkitRetryAfter is happy + OctagonStateTransitionOperation* op = [OctagonStateTransitionOperation named:@"recover-from-cloudkit-failure" entering:SecCKKSZoneKeyStateInitializing]; - // Cancel the key ready dependency. Strictly Speaking, this will cause errors down the line, but we're in a cancel state: those operations should be canceled anyway. - self.keyHierarchyOperationGroup = nil; - [self.keyStateReadyDependency cancel]; - self.keyStateReadyDependency = nil; + [op addNullableDependency:self.operationDependencies.zoneModifier.cloudkitRetryAfter.operationDependency]; + [self.operationDependencies.zoneModifier.cloudkitRetryAfter trigger]; - [self.keyStateNonTransientDependency cancel]; - self.keyStateNonTransientDependency = nil; - return; + return op; } - // Now that the current or new state isn't an error or a cancel, proceed. - if(self.keyStateMachineOperation && ![self.keyStateMachineOperation isFinished]) { - if(state == nil) { - // we started this operation to move the state machine. Since you aren't asking for a state transition, and there's an active operation, no need to do anything - ckksnotice("ckkskey", self, "Not advancing state machine: waiting for %@", self.keyStateMachineOperation); - return; + if([currentState isEqualToString:SecCKKSZoneKeyStateLoseTrust]) { + if([flags _onqueueContains:CKKSFlagBeginTrustedOperation]) { + [flags _onqueueRemoveFlag:CKKSFlagBeginTrustedOperation]; + // This was likely a race between some operation and the beginTrustedOperation call! Skip changing state and try again. + return [OctagonStateTransitionOperation named:@"begin-trusted-operation" entering:SecCKKSZoneKeyStateInitialized]; + } + + // If our current state is "trusted", fall out + if(self.trustStatus == CKKSAccountStatusAvailable) { + self.trustStatus = CKKSAccountStatusUnknown; } + return [OctagonStateTransitionOperation named:@"trust-loss" entering:SecCKKSZoneKeyStateWaitForTrust]; } - if(state) { - ckksnotice("ckkskey", self, "Preparing to advance key hierarchy state machine from %@ to %@", self.keyHierarchyState, state); - self.keyStateMachineOperation = nil; - } else { - ckksnotice("ckkskey", self, "Key hierarchy state machine is being poked; currently %@", self.keyHierarchyState); - state = self.keyHierarchyState; - } - -#if DEBUG - // During testing, keep the developer honest: this function should always have the self identities, unless the account has lost trust - // But, beginTrustedOperation is currently racy: if it acquires the queue and sets the trust bit between fetching the trust states and getting on the queue, - // this will fire. So, release SecCKKSZoneKeyStateInitialized from this check. - if(self.trustStatus == CKKSAccountStatusAvailable - && ![state isEqualToString:SecCKKSZoneKeyStateLoggedOut] - && ![state isEqualToString:SecCKKSZoneKeyStateInitialized]) { - bool hasSelfIdentities = false; - NSAssert(self.currentTrustStates.count > 0, @"Should have at least one trust state"); - for(CKKSPeerProviderState* state in self.currentTrustStates) { - if(state.currentSelfPeersError == nil || state.currentSelfPeersError.code != CKKSNoPeersAvailable) { - hasSelfIdentities = true; - } + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) { + if(self.trustStatus == CKKSAccountStatusAvailable) { + ckksnotice("ckkskey", self, "Beginning trusted state machine operation"); + return [OctagonStateTransitionOperation named:@"begin-trusted-operation" entering:SecCKKSZoneKeyStateInitialized]; } - NSAssert(hasSelfIdentities, @"Must have viable (or errored) self peers to advance key state"); + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; + return [OctagonStateTransitionOperation named:@"begin-trusted-operation" entering:SecCKKSZoneKeyStateProcess]; + } + + if([flags _onqueueContains:CKKSFlag24hrNotification]) { + [flags _onqueueRemoveFlag:CKKSFlag24hrNotification]; + } + + return nil; } -#endif - // Do any of these state transitions below want to change which state we're in? - CKKSZoneKeyState* nextState = nil; - NSError* nextError = nil; + if([currentState isEqualToString:SecCKKSZoneKeyStateBecomeReady]) { + return [[CKKSCheckKeyHierarchyOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateError]; + } - // Any state that wants should fill this in; it'll be used at the end of this function as well - CKKSCurrentKeySet* keyset = nil; + if([currentState isEqualToString:SecCKKSZoneKeyStateReady]) { + // If we're ready, we can ignore the begin trusted flag + [flags _onqueueRemoveFlag:CKKSFlagBeginTrustedOperation]; -#if !defined(NDEBUG) - { - NSError* localerror = nil; - NSError* allKeysError = nil; - NSArray* allKeys = [CKKSKey allKeys:self.zoneID error:&allKeysError]; + if(self.keyStateFullRefetchRequested) { + // In ready, but something has requested a full refetch. + ckksnotice("ckkskey", self, "Kicking off a full key refetch based on request:%d", self.keyStateFullRefetchRequested); + [self ensureKeyStateReadyDependency:@"key-state-full-refetch"]; + return [OctagonStateTransitionOperation named:@"full-refetch" entering:SecCKKSZoneKeyStateNeedFullRefetch]; + } - if(localerror) { - ckkserror("ckkskey", self, "couldn't fetch all keys from local database, entering error state: %@", allKeysError); + if([flags _onqueueContains:CKKSFlagFetchRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagFetchRequested]; + ckksnotice("ckkskey", self, "Kicking off a key refetch based on request"); + [self ensureKeyStateReadyDependency:@"key-state-fetch"]; + return [OctagonStateTransitionOperation named:@"fetch-requested" entering:SecCKKSZoneKeyStateBeginFetch]; } - ckksdebug("ckkskey", self, "All keys: %@", allKeys); - } -#endif - NSError* hierarchyError = nil; + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; + ckksnotice("ckkskey", self, "Kicking off a key reprocess based on request"); + [self ensureKeyStateReadyDependency:@"key-state-process"]; + return [OctagonStateTransitionOperation named:@"key-process" entering:SecCKKSZoneKeyStateProcess]; + } - if(self.keyStateCloudKitDeleteRequested || [state isEqualToString:SecCKKSZoneKeyStateResettingZone]) { - // CloudKit reset requests take precedence over all other state transitions - ckksnotice("ckkskey", self, "Deleting the CloudKit Zone"); - CKKSGroupOperation* op = [[CKKSGroupOperation alloc] init]; + if(self.trustStatus != CKKSAccountStatusAvailable) { + ckksnotice("ckkskey", self, "In ready, but there's no trust; going into waitfortrust"); + [self ensureKeyStateReadyDependency:@"trust loss"]; + return [OctagonStateTransitionOperation named:@"trust-gone" entering:SecCKKSZoneKeyStateLoseTrust]; + } - CKKSResultOperation* deleteOp = [self createPendingDeleteZoneOperation:self.keyHierarchyOperationGroup]; - [op runBeforeGroupFinished: deleteOp]; + if([flags _onqueueContains:CKKSFlagTrustedPeersSetChanged]) { + [flags _onqueueRemoveFlag:CKKSFlagTrustedPeersSetChanged]; + ckksnotice("ckkskey", self, "Received a nudge that the trusted peers set might have changed! Reprocessing."); + [self ensureKeyStateReadyDependency:@"Peer set changed"]; + return [OctagonStateTransitionOperation named:@"trusted-peers-changed" entering:SecCKKSZoneKeyStateProcess]; + } - NSOperation* nextStateOp = [CKKSResultOperation named:@"inspect-zone-delete" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull op) { - STRONGIFY(self); - [self dispatchSyncWithAccountKeys:^bool { - // Did the delete op succeed? - if(deleteOp.error == nil) { - ckksnotice("ckkskey", self, "Zone deletion operation complete! Proceeding to reset local data"); - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateResettingLocalData withError:nil]; - return true; - } + if([flags _onqueueContains:CKKSFlag24hrNotification]) { + [flags _onqueueRemoveFlag:CKKSFlag24hrNotification]; - ckksnotice("ckkskey", self, "Zone deletion operation failed, will retry: %@", deleteOp.error); - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateResettingZone withError:nil]; + // We'd like to trigger our 24-hr backup fetch and scan. + // That's currently part of the Initialized state, so head that way + return [OctagonStateTransitionOperation named:@"24-hr-check" entering:SecCKKSZoneKeyStateInitialized]; + } - return true; - }]; - }]; + if([flags _onqueueContains:CKKSFlagItemReencryptionNeeded]) { + [flags _onqueueRemoveFlag:CKKSFlagItemReencryptionNeeded]; - [nextStateOp addDependency:deleteOp]; - [op runBeforeGroupFinished:nextStateOp]; + // TODO: this should be part of the state machine + CKKSReencryptOutgoingItemsOperation* op = [[CKKSReencryptOutgoingItemsOperation alloc] initWithDependencies:self.operationDependencies + ckks:self + intendedState:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateError]; + [self scheduleOperation:op]; + // fall through. + } - self.keyStateMachineOperation = op; - self.keyStateCloudKitDeleteRequested = false; + if([flags _onqueueContains:CKKSFlagProcessIncomingQueue]) { + [flags _onqueueRemoveFlag:CKKSFlagProcessIncomingQueue]; + // TODO: this should be part of the state machine - // Also, pending operations should be cancelled - [self cancelPendingOperations]; + [self processIncomingQueue:true]; + //return [OctagonStateTransitionOperation named:@"process-outgoing" entering:SecCKKSZoneKeyStateProcessIncomingQueue]; + } - } else if(self.keyStateLocalResetRequested || [state isEqualToString:SecCKKSZoneKeyStateResettingLocalData]) { - // Local reset requests take precedence over all other state transitions - ckksnotice("ckkskey", self, "Resetting local data"); - CKKSGroupOperation* op = [[CKKSGroupOperation alloc] init]; + if([flags _onqueueContains:CKKSFlagScanLocalItems]) { + [flags _onqueueRemoveFlag:CKKSFlagScanLocalItems]; + ckksnotice("ckkskey", self, "Launching a scan operation to find dropped items"); - CKKSResultOperation* resetOp = [self createPendingResetLocalDataOperation]; - [op runBeforeGroupFinished: resetOp]; + // TODO: this should be a state flow + [self scanLocalItems:@"per-request"]; + // fall through + } - NSOperation* nextStateOp = [self operationToEnterState:SecCKKSZoneKeyStateInitializing keyStateError:nil named:@"state-resetting-initialize"]; - [nextStateOp addDependency:resetOp]; - [op runBeforeGroupFinished:nextStateOp]; + if([flags _onqueueContains:CKKSFlagProcessOutgoingQueue]) { + [flags _onqueueRemoveFlag:CKKSFlagProcessOutgoingQueue]; - self.keyStateMachineOperation = op; - self.keyStateLocalResetRequested = false; + [self processOutgoingQueue:nil]; + // TODO: this should be a state flow. + //return [OctagonStateTransitionOperation named:@"process-outgoing" entering:SecCKKSZoneKeyStateProcessOutgoingQueue]; + // fall through + } - } else if([state isEqualToString:SecCKKSZoneKeyStateZoneCreationFailed]) { - //Prepare to go back into initializing, as soon as the cloudkitRetryAfter is happy - self.keyStateMachineOperation = [self operationToEnterState:SecCKKSZoneKeyStateInitializing keyStateError:nil named:@"recover-from-cloudkit-failure"]; - [self.keyStateMachineOperation addNullableDependency:self.zoneModifier.cloudkitRetryAfter.operationDependency]; - [self.zoneModifier.cloudkitRetryAfter trigger]; + // TODO: kick off a key roll if one has been requested - } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) { - // Actually entering this state should have been handled above, so let's check if we can exit it here... - if(self.trustStatus == CKKSAccountStatusAvailable) { - ckksnotice("ckkskey", self, "Beginning trusted state machine operation"); - nextState = SecCKKSZoneKeyStateInitialized; - } else if (self.tlkCreationRequested) { - ckksnotice("ckkskey", self, "No trust, but TLK creation is requested. Moving to fetchcomplete."); - nextState = SecCKKSZoneKeyStateFetchComplete; + // If we reach this point, we're in ready, and will stay there. + // Tell the launch and the viewReadyScheduler about that. - } else { - ckksnotice("ckkskey", self, "Remaining in 'waitfortrust'"); + [self.launch launch]; + + [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastKeystateReady zoneName:self.zoneName]; + if(self.keyStateReadyDependency) { + [self scheduleOperation:self.keyStateReadyDependency]; + self.keyStateReadyDependency = nil; } - } else if([state isEqualToString: SecCKKSZoneKeyStateReady]) { - NSError* localerror = nil; - NSArray* remoteKeys = [CKKSKey remoteKeys:self.zoneID error: &localerror]; + return nil; + } - if(remoteKeys == nil || localerror) { - ckkserror("ckkskey", self, "couldn't fetch keys from local database, entering error state: %@", localerror); - self.keyHierarchyState = SecCKKSZoneKeyStateError; - self.keyHierarchyError = localerror; - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; + if([currentState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]) { + if([flags _onqueueContains:CKKSFlagDeviceUnlocked]) { + [flags _onqueueRemoveFlag:CKKSFlagDeviceUnlocked]; + [self ensureKeyStateReadyDependency:@"Device unlocked"]; + return [OctagonStateTransitionOperation named:@"key-state-ready-after-unlock" entering:SecCKKSZoneKeyStateBecomeReady]; } - if(self.keyStateProcessRequested || [remoteKeys count] > 0) { - // We've either received some remote keys from the last fetch, or someone has requested a reprocess. - ckksnotice("ckkskey", self, "Kicking off a key reprocess based on request:%d and remote key count %lu", self.keyStateProcessRequested, (unsigned long)[remoteKeys count]); - nextState = SecCKKSZoneKeyStateProcess; - - } else if(self.keyStateFullRefetchRequested) { - // In ready, but someone has requested a full fetch. Kick it off. - ckksnotice("ckkskey", self, "Kicking off a full key refetch based on request:%d", self.keyStateFullRefetchRequested); - nextState = SecCKKSZoneKeyStateNeedFullRefetch; - - } else if(self.keyStateFetchRequested) { - // In ready, but someone has requested a fetch. Kick it off. - ckksnotice("ckkskey", self, "Kicking off a key refetch based on request:%d", self.keyStateFetchRequested); - nextState = SecCKKSZoneKeyStateFetch; // Don't go to 'ready', go to 'initialized', since we want to fetch again - } else if (self.trustStatus != CKKSAccountStatusAvailable) { - ckksnotice("ckkskey", self, "Asked to go into ready, but there's no trust; going into waitfortrust"); - nextState = SecCKKSZoneKeyStateWaitForTrust; - } else if (self.trustedPeersSetChanged) { - ckksnotice("ckkskey", self, "Received a nudge that the trusted peers set might have changed! Reprocessing."); - nextState = SecCKKSZoneKeyStateProcess; - self.trustedPeersSetChanged = false; + if([flags _onqueueContains:CKKSFlagProcessOutgoingQueue]) { + [flags _onqueueRemoveFlag:CKKSFlagProcessOutgoingQueue]; + [self processOutgoingQueue:nil]; + // TODO: this should become part of the key state hierarchy } - // TODO: kick off a key roll if one has been requested + // Ready enough! - if(!self.keyStateMachineOperation && !nextState) { - // We think we're ready. Double check. - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - CKKSZoneKeyState* checkedstate = [self _onqueueEnsureKeyHierarchyHealth:keyset error:&hierarchyError]; - if(![checkedstate isEqualToString:SecCKKSZoneKeyStateReady] || hierarchyError) { - // Things is bad. Kick off a heal to fix things up. - ckksnotice("ckkskey", self, "Thought we were ready, but the key hierarchy is %@: %@", checkedstate, hierarchyError); - nextState = checkedstate; - if([nextState isEqualToString:SecCKKSZoneKeyStateError]) { - nextError = hierarchyError; - } - } + [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastKeystateReady zoneName:self.zoneName]; + if(self.keyStateReadyDependency) { + [self scheduleOperation:self.keyStateReadyDependency]; + self.keyStateReadyDependency = nil; } - } else if([state isEqualToString: SecCKKSZoneKeyStateInitialized]) { - // We're initialized and CloudKit is ready. If we're trusted, see what needs done. Otherwise, wait. + OctagonPendingFlag* unlocked = [[OctagonPendingFlag alloc] initWithFlag:CKKSFlagDeviceUnlocked + conditions:OctagonPendingConditionsDeviceUnlocked]; + [pendingFlagHandler _onqueueHandlePendingFlag:unlocked]; + return nil; + } - // Note: we might be still 'untrusted' at this point. The state machine is responsible for not entering 'ready' until - // we are trusted. - // This is acceptable only if the key state machine does not make new TLKs without being trusted! + if([currentState isEqualToString:SecCKKSZoneKeyStateBeginFetch]) { + ckksnotice("ckkskey", self, "Starting a key hierarchy fetch"); + [flags _onqueueRemoveFlag:CKKSFlagFetchComplete]; - // Set this state, for test use - self.keyHierarchyState = SecCKKSZoneKeyStateInitialized; + WEAKIFY(self); - CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.zoneName]; - [self _onqueuePerformKeyStateInitialized:ckse]; - - // We need to either: - // Wait for the fixup operation to occur - // Go into 'ready' - // Or start a key state fetch - if(self.lastFixupOperation && ![self.lastFixupOperation isFinished]) { - nextState = SecCKKSZoneKeyStateWaitForFixupOperation; - } else { - // Check if we have an existing key hierarchy in keyset - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - if(keyset.error && !([keyset.error.domain isEqual: @"securityd"] && keyset.error.code == errSecItemNotFound)) { - ckkserror("ckkskey", self, "Error examining existing key hierarchy: %@", error); - } + NSSet* fetchReasons = self.currentFetchReasons ? + [self.currentFetchReasons setByAddingObject:CKKSFetchBecauseKeyHierarchy] : + [NSSet setWithObject:CKKSFetchBecauseKeyHierarchy]; - if(keyset.tlk && keyset.classA && keyset.classC && !keyset.error) { - // This is likely a restart of securityd, and we think we're ready. Double check. + CKKSResultOperation* fetchOp = [self.zoneChangeFetcher requestSuccessfulFetchForManyReasons:fetchReasons]; + CKKSResultOperation* flagOp = [CKKSResultOperation named:@"post-fetch" + withBlock:^{ + STRONGIFY(self); + [self.stateMachine handleFlag:CKKSFlagFetchComplete]; + }]; + [flagOp addDependency:fetchOp]; + [self scheduleOperation:flagOp]; - CKKSZoneKeyState* checkedstate = [self _onqueueEnsureKeyHierarchyHealth:keyset error:&hierarchyError]; - if([checkedstate isEqualToString:SecCKKSZoneKeyStateReady] && !hierarchyError) { - ckksnotice("ckkskey", self, "Already have existing key hierarchy for %@; using it.", self.zoneID.zoneName); - } else { - ckksnotice("ckkskey", self, "Initial scan shows key hierarchy is %@: %@", checkedstate, hierarchyError); - } - nextState = checkedstate; + return [OctagonStateTransitionOperation named:@"waiting-for-fetch" entering:SecCKKSZoneKeyStateFetch]; + } - } else { - // We have no local key hierarchy. One might exist in CloudKit, or it might not. - ckksnotice("ckkskey", self, "No existing key hierarchy for %@. Check if there's one in CloudKit...", self.zoneID.zoneName); - nextState = SecCKKSZoneKeyStateFetch; - } + if([currentState isEqualToString:SecCKKSZoneKeyStateFetch]) { + if([flags _onqueueContains:CKKSFlagFetchComplete]) { + [flags _onqueueRemoveFlag:CKKSFlagFetchComplete]; + return [OctagonStateTransitionOperation named:@"fetch-complete" entering:SecCKKSZoneKeyStateFetchComplete]; } - } else if([state isEqualToString:SecCKKSZoneKeyStateFetch]) { - ckksnotice("ckkskey", self, "Starting a key hierarchy fetch"); - [self _onqueueKeyHierarchyFetch]; + // The flags CKKSFlagCloudKitZoneMissing and CKKSFlagChangeTokenOutdated are both handled at the top of this function + // So, we don't need to handle them here. - } else if([state isEqualToString: SecCKKSZoneKeyStateNeedFullRefetch]) { - ckksnotice("ckkskey", self, "Starting a key hierarchy full refetch"); - [self _onqueueKeyHierarchyFetchForReasons:[NSSet setWithObjects:CKKSFetchBecauseKeyHierarchy, CKKSFetchBecauseResync, nil]]; - self.keyStateMachineRefetched = true; - self.keyStateFullRefetchRequested = false; + return nil; + } - } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForFixupOperation]) { - // We should enter 'initialized' when the fixup operation completes - ckksnotice("ckkskey", self, "Waiting for the fixup operation: %@", self.lastFixupOperation); + if([currentState isEqualToString:SecCKKSZoneKeyStateNeedFullRefetch]) { + ckksnotice("ckkskey", self, "Starting a key hierarchy full refetch"); - self.keyStateMachineOperation = [NSBlockOperation named:@"key-state-after-fixup" withBlock:^{ - STRONGIFY(self); - [self dispatchSyncWithAccountKeys:^bool{ - ckksnotice("ckkskey", self, "Fixup operation complete! Restarting key hierarchy machinery"); - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateInitialized withError:nil]; - return true; - }]; - }]; - [self.keyStateMachineOperation addNullableDependency:self.lastFixupOperation]; + //TODO use states here instead of flags + self.keyStateMachineRefetched = true; + self.keyStateFullRefetchRequested = false; - } else if([state isEqualToString: SecCKKSZoneKeyStateFetchComplete]) { - // We've just completed a fetch of everything. Are there any remote keys? - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; + return [OctagonStateTransitionOperation named:@"fetch-complete" entering:SecCKKSZoneKeyStateResettingLocalData]; + } - NSError* localerror = nil; + if([currentState isEqualToString:SecCKKSZoneKeyStateFetchComplete]) { + [self.launch addEvent:@"fetch-complete"]; + [self.currentFetchReasons removeAllObjects]; - NSArray* localKeys = [CKKSKey localKeys:self.zoneID error:&localerror]; - NSArray* remoteKeys = [CKKSKey remoteKeys:self.zoneID error: &localerror]; + return [OctagonStateTransitionOperation named:@"post-fetch-process" entering:SecCKKSZoneKeyStateProcess]; + } - if(localKeys == nil || remoteKeys == nil || localerror) { - ckkserror("ckkskey", self, "couldn't fetch keys from local database, entering error state: %@", localerror); - self.keyHierarchyState = SecCKKSZoneKeyStateError; - self.keyHierarchyError = localerror; - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; - } + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation]) { + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; + ckksnotice("ckkskey", self, "We believe we need to create TLKs but we also received a key nudge; moving to key state Process."); + return [OctagonStateTransitionOperation named:@"wait-for-tlk-creation-process" entering:SecCKKSZoneKeyStateProcess]; - if(remoteKeys.count > 0u) { - // Process the keys we received. - self.keyStateMachineOperation = [[CKKSProcessReceivedKeysStateMachineOperation alloc] initWithCKKSKeychainView: self]; - } else if( (keyset.currentTLKPointer || keyset.currentClassAPointer || keyset.currentClassCPointer) && - !(keyset.tlk && keyset.classA && keyset.classC)) { - // Huh. We appear to have current key pointers, but the keys themselves don't exist. That's weird. - // Transfer to the "unhealthy" state to request a fix - ckksnotice("ckkskey", self, "We appear to have current key pointers but no keys to match them: %@ Moving to 'unhealthy'", keyset); - nextState = SecCKKSZoneKeyStateUnhealthy; - } else { - // No remote keys, and the pointers look sane? Do we have an existing key hierarchy? - CKKSZoneKeyState* checkedstate = [self _onqueueEnsureKeyHierarchyHealth:keyset error:&hierarchyError]; - if([checkedstate isEqualToString:SecCKKSZoneKeyStateReady] && !hierarchyError) { - ckksnotice("ckkskey", self, "After fetch, everything looks good."); - nextState = checkedstate; - - } else if(localKeys.count == 0 && remoteKeys.count == 0) { - ckksnotice("ckkskey", self, "After fetch, we don't have any key hierarchy. Entering a waiting state: %@", hierarchyError ?: @"no error"); - nextState = SecCKKSZoneKeyStateWaitForTLKCreation; - } else { - ckksnotice("ckkskey", self, "After fetch, we have a possibly unhealthy key hierarchy. Moving to %@: %@", checkedstate, hierarchyError ?: @"no error"); - nextState = checkedstate; - } - } + } else if([flags _onqueueContains:CKKSFlagFetchRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagFetchRequested]; + return [OctagonStateTransitionOperation named:@"fetch-requested" entering:SecCKKSZoneKeyStateBeginFetch]; - } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation]) { + } else if([flags _onqueueContains:CKKSFlagTLKCreationRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagTLKCreationRequested]; - if(self.tlkCreationRequested) { - self.tlkCreationRequested = false; - ckksnotice("ckkskey", self, "TLK creation requested; kicking off operation"); - self.keyStateMachineOperation = [[CKKSNewTLKOperation alloc] initWithCKKSKeychainView: self ckoperationGroup:self.keyHierarchyOperationGroup]; + // It's very likely that we're already untrusted at this point. But, sometimes we will be trusted right now, and can lose trust while waiting for the upload. + // This probably should be handled by a state increase. + [flags _onqueueRemoveFlag:CKKSFlagEndTrustedOperation]; - } else if(self.keyStateProcessRequested) { - ckksnotice("ckkskey", self, "We believe we need to create TLKs but we also received a key nudge; moving to key state Process."); - nextState = SecCKKSZoneKeyStateProcess; + ckksnotice("ckkskey", self, "TLK creation requested; kicking off operation"); + return [[CKKSNewTLKOperation alloc] initWithDependencies:self.operationDependencies + ckks:self]; + } else if(self.lastNewTLKOperation.keyset) { + // This means that we _have_ created new TLKs, and should wait for them to be uploaded. This is ugly and should probably be done with more states. + return [OctagonStateTransitionOperation named:@"" entering:SecCKKSZoneKeyStateWaitForTLKUpload]; } else { ckksnotice("ckkskey", self, "We believe we need to create TLKs; waiting for Octagon (via %@)", self.suggestTLKUpload); [self.suggestTLKUpload trigger]; } + } - - } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload]) { ckksnotice("ckkskey", self, "We believe we have TLKs that need uploading"); + if([flags _onqueueContains:CKKSFlagFetchRequested]) { + ckksnotice("ckkskey", self, "Received a nudge to refetch CKKS"); + return [OctagonStateTransitionOperation named:@"tlk-upload-refetch" entering:SecCKKSZoneKeyStateBeginFetch]; + } - if(self.keyStateProcessRequested) { - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - if(keyset.currentTLKPointer.currentKeyUUID) { - ckksnotice("ckkskey", self, "Received a nudge that our TLK records might be here (and there's some current TLK pointer)"); - nextState = SecCKKSZoneKeyStateProcess; - } else { - ckksnotice("ckkskey", self, "Received a nudge that our TLK records might be here, but there's no TLK pointer. Staying in WaitForTLKUpload."); - self.keyStateProcessRequested = false; - } + if([flags _onqueueContains:CKKSFlagKeyStateTLKsUploaded]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateTLKsUploaded]; + + return [OctagonStateTransitionOperation named:@"wait-for-tlk-upload-process" entering:SecCKKSZoneKeyStateProcess]; } - if(nextState == nil) { - ckksnotice("ckkskey", self, "Alerting any listener of our proposed keyset: %@", self.lastNewTLKOperation.keyset); - [self _onqueueRunKeysetProviderOperations:self.lastNewTLKOperation.keyset]; + if([flags _onqueueContains:CKKSFlagEndTrustedOperation]) { + [flags _onqueueRemoveFlag:CKKSFlagEndTrustedOperation]; - ckksnotice("ckkskey", self, "Notifying Octagon again, just in case"); - [self.suggestTLKUpload trigger]; + return [OctagonStateTransitionOperation named:@"trust-loss" entering:SecCKKSZoneKeyStateLoseTrust]; } - } else if([state isEqualToString: SecCKKSZoneKeyStateWaitForTLK]) { + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + return [OctagonStateTransitionOperation named:@"wait-for-tlk-fetch-process" entering:SecCKKSZoneKeyStateProcess]; + } + + // This is quite the hack, but it'll do for now. + [self.operationDependencies provideKeySet:self.lastNewTLKOperation.keyset]; + + ckksnotice("ckkskey", self, "Notifying Octagon again, just in case"); + [self.suggestTLKUpload trigger]; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateTLKMissing]) { + return [self tlkMissingOperation:SecCKKSZoneKeyStateWaitForTLK]; + } + + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForTLK]) { // We're in a hold state: waiting for the TLK bytes to arrive. - if(self.keyStateProcessRequested) { + if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; // Someone has requsted a reprocess! Go to the correct state. ckksnotice("ckkskey", self, "Received a nudge that our TLK might be here! Reprocessing."); - nextState = SecCKKSZoneKeyStateProcess; + return [OctagonStateTransitionOperation named:@"wait-for-tlk-process" entering:SecCKKSZoneKeyStateProcess]; + + } else if([flags _onqueueContains:CKKSFlagTrustedPeersSetChanged]) { + [flags _onqueueRemoveFlag:CKKSFlagTrustedPeersSetChanged]; - } else if(self.trustedPeersSetChanged) { // Hmm, maybe this trust set change will cause us to recover this TLK (due to a previously-untrusted share becoming trusted). Worth a shot! ckksnotice("ckkskey", self, "Received a nudge that the trusted peers set might have changed! Reprocessing."); - nextState = SecCKKSZoneKeyStateProcess; - self.trustedPeersSetChanged = false; + return [OctagonStateTransitionOperation named:@"wait-for-tlk-peers" entering:SecCKKSZoneKeyStateProcess]; + } - } else { - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; + return nil; + } - // Should we nuke this zone? - if(self.trustStatus == CKKSAccountStatusAvailable) { - if([self _onqueueOtherDevicesReportHavingTLKs:keyset]) { - ckksnotice("ckkskey", self, "Other devices report having TLK(%@). Entering a waiting state", keyset.currentTLKPointer); - } else { - ckksnotice("ckkskey", self, "No other devices have TLK(%@). Beginning zone reset...", keyset.currentTLKPointer); - self.keyHierarchyOperationGroup = [CKOperationGroup CKKSGroupWithName:@"tlk-missing"]; - nextState = SecCKKSZoneKeyStateResettingZone; - } - } else { - ckksnotice("ckkskey", self, "This device isn't trusted, so don't modify the existing TLK(%@)", keyset.currentTLKPointer); - nextState = SecCKKSZoneKeyStateWaitForTrust; - } + if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForUnlock]) { + ckksnotice("ckkskey", self, "Requested to enter waitforunlock"); + + if([flags _onqueueContains:CKKSFlagDeviceUnlocked ]) { + [flags _onqueueRemoveFlag:CKKSFlagDeviceUnlocked]; + return [OctagonStateTransitionOperation named:@"key-state-after-unlock" entering:SecCKKSZoneKeyStateInitialized]; } - } else if([state isEqualToString: SecCKKSZoneKeyStateWaitForUnlock]) { - ckksnotice("ckkskey", self, "Requested to enter waitforunlock"); - self.keyStateMachineOperation = [self operationToEnterState:SecCKKSZoneKeyStateInitialized keyStateError:nil named:@"key-state-after-unlock"]; - [self.keyStateMachineOperation addNullableDependency: self.lockStateTracker.unlockDependency]; + OctagonPendingFlag* unlocked = [[OctagonPendingFlag alloc] initWithFlag:CKKSFlagDeviceUnlocked + conditions:OctagonPendingConditionsDeviceUnlocked]; + [pendingFlagHandler _onqueueHandlePendingFlag:unlocked]; - } else if([state isEqualToString: SecCKKSZoneKeyStateReadyPendingUnlock]) { - ckksnotice("ckkskey", self, "Believe we're ready, but rechecking after unlock"); - self.keyStateMachineOperation = [self operationToEnterState:SecCKKSZoneKeyStateInitialized keyStateError:nil named:@"key-state-after-unlock"]; - [self.keyStateMachineOperation addNullableDependency: self.lockStateTracker.unlockDependency]; + return nil; + } - } else if([state isEqualToString: SecCKKSZoneKeyStateBadCurrentPointers]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateBadCurrentPointers]) { // The current key pointers are broken, but we're not sure why. ckksnotice("ckkskey", self, "Our current key pointers are reported broken. Attempting a fix!"); - self.keyStateMachineOperation = [[CKKSHealKeyHierarchyOperation alloc] initWithCKKSKeychainView: self ckoperationGroup:self.keyHierarchyOperationGroup]; + return [[CKKSHealKeyHierarchyOperation alloc] initWithDependencies:self.operationDependencies + ckks:self + intending:SecCKKSZoneKeyStateBecomeReady + errorState:SecCKKSZoneKeyStateError]; + } - } else if([state isEqualToString: SecCKKSZoneKeyStateNewTLKsFailed]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateNewTLKsFailed]) { ckksnotice("ckkskey", self, "Creating new TLKs didn't work. Attempting to refetch!"); - [self _onqueueKeyHierarchyFetch]; + return [OctagonStateTransitionOperation named:@"new-tlks-failed" entering:SecCKKSZoneKeyStateBeginFetch]; + } - } else if([state isEqualToString: SecCKKSZoneKeyStateHealTLKSharesFailed]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateHealTLKSharesFailed]) { ckksnotice("ckkskey", self, "Creating new TLK shares didn't work. Attempting to refetch!"); - [self _onqueueKeyHierarchyFetch]; + return [OctagonStateTransitionOperation named:@"heal-tlks-failed" entering:SecCKKSZoneKeyStateBeginFetch]; + } - } else if([state isEqualToString:SecCKKSZoneKeyStateUnhealthy]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateUnhealthy]) { if(self.trustStatus != CKKSAccountStatusAvailable) { ckksnotice("ckkskey", self, "Looks like the key hierarchy is unhealthy, but we're untrusted."); - nextState = SecCKKSZoneKeyStateWaitForTrust; + return [OctagonStateTransitionOperation named:@"unhealthy-lacking-trust" entering:SecCKKSZoneKeyStateLoseTrust]; } else { ckksnotice("ckkskey", self, "Looks like the key hierarchy is unhealthy. Launching fix."); - self.keyStateMachineOperation = [[CKKSHealKeyHierarchyOperation alloc] initWithCKKSKeychainView:self ckoperationGroup:self.keyHierarchyOperationGroup]; + return [[CKKSHealKeyHierarchyOperation alloc] initWithDependencies:self.operationDependencies + ckks:self + intending:SecCKKSZoneKeyStateBecomeReady + errorState:SecCKKSZoneKeyStateError]; } + } - } else if([state isEqualToString:SecCKKSZoneKeyStateHealTLKShares]) { + if([currentState isEqualToString:SecCKKSZoneKeyStateHealTLKShares]) { ckksnotice("ckksshare", self, "Key hierarchy is okay, but not shared appropriately. Launching fix."); - self.keyStateMachineOperation = [[CKKSHealTLKSharesOperation alloc] initWithCKKSKeychainView:self - ckoperationGroup:self.keyHierarchyOperationGroup]; - - } else if([state isEqualToString:SecCKKSZoneKeyStateProcess]) { - ckksnotice("ckksshare", self, "Launching key state process"); - self.keyStateMachineOperation = [[CKKSProcessReceivedKeysStateMachineOperation alloc] initWithCKKSKeychainView: self]; - - // Since we're starting a reprocess, this is answering all previous requests. - self.keyStateProcessRequested = false; - - } else { - ckkserror("ckks", self, "asked to advance state machine to unknown state: %@", state); - self.keyHierarchyState = state; - - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - [self _onqueueHandleKeyStateNonTransientDependency:keyset]; - return; + return [[CKKSHealTLKSharesOperation alloc] initWithOperationDependencies:self.operationDependencies + ckks:self]; } - // Handle the key state ready dependency - // If we're in ready and not entering a non-ready state, we should activate the ready dependency. Otherwise, we should create it. - if(([state isEqualToString:SecCKKSZoneKeyStateReady] || [state isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]) && - (nextState == nil || [nextState isEqualToString:SecCKKSZoneKeyStateReady] || [nextState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock])) { + if([currentState isEqualToString:SecCKKSZoneKeyStateProcess]) { + [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested]; - // Ready enough! - [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastKeystateReady inView:self]; - - if(self.keyStateReadyDependency) { - [self scheduleOperation: self.keyStateReadyDependency]; - self.keyStateReadyDependency = nil; - } - - // If there are any OQEs waiting to be encrypted, launch an op to fix them - NSError* localerror = nil; - NSInteger outdatedOQEs = [CKKSOutgoingQueueEntry countByState:SecCKKSStateReencrypt zone:self.zoneID error:&localerror]; - - if(localerror) { - ckkserror("ckkskey", self, "couldn't fetch OQEs from local database, entering error state: %@", localerror); - self.keyHierarchyState = SecCKKSZoneKeyStateError; - self.keyHierarchyError = localerror; - [self _onqueueHandleKeyStateNonTransientDependency:nil]; - return; - } - - if(outdatedOQEs > 0) { - ckksnotice("ckksreencrypt", self, "Reencrypting outgoing items as the key hierarchy is ready"); - CKKSReencryptOutgoingItemsOperation* op = [[CKKSReencryptOutgoingItemsOperation alloc] initWithCKKSKeychainView:self ckoperationGroup:self.keyHierarchyOperationGroup]; - [self scheduleOperation:op]; - } - } else { - // Not in ready: we need a key state ready dependency - if(self.keyStateReadyDependency == nil || [self.keyStateReadyDependency isFinished]) { - self.keyHierarchyOperationGroup = [CKOperationGroup CKKSGroupWithName:@"key-state-broken"]; - self.keyStateReadyDependency = [self createKeyStateReadyDependency:@"Key state has become ready again." ckoperationGroup:self.keyHierarchyOperationGroup]; - } + ckksnotice("ckksshare", self, "Launching key state process"); + return [[CKKSProcessReceivedKeysOperation alloc] initWithDependencies:self.operationDependencies + intendedState:SecCKKSZoneKeyStateBecomeReady + errorState:SecCKKSZoneKeyStateError]; } - NSAssert(!((self.keyStateMachineOperation != nil) && - (nextState != nil)), - @"Should have a machine operation or a next state, not both"); - - // Start any operations, or log that we aren't - if(self.keyStateMachineOperation) { - [self scheduleOperation: self.keyStateMachineOperation]; - ckksnotice("ckkskey", self, "Now in key state: %@", state); - self.keyHierarchyState = state; + return nil; +} - } else if([state isEqualToString:SecCKKSZoneKeyStateError]) { - ckksnotice("ckkskey", self, "Entering key state 'error'"); - self.keyHierarchyState = state; +- (OctagonStateTransitionOperation*)tlkMissingOperation:(CKKSZoneKeyState*)newState +{ + WEAKIFY(self); + return [OctagonStateTransitionOperation named:@"tlk-missing" + intending:newState + errorState:SecCKKSZoneKeyStateError + withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { + STRONGIFY(self); - } else if(nextState == nil) { - ckksnotice("ckkskey", self, "Entering key state: %@", state); - self.keyHierarchyState = state; + NSArray* trustStates = self.operationDependencies.currentTrustStates; - } else if(![state isEqualToString: nextState]) { - ckksnotice("ckkskey", self, "Staying in state %@, but proceeding to %@ as soon as possible", self.keyHierarchyState, nextState); - self.keyStateMachineOperation = [self operationToEnterState:nextState keyStateError:nextError named:[NSString stringWithFormat:@"next-key-state-%@", nextState]]; - [self scheduleOperation: self.keyStateMachineOperation]; + [self.operationDependencies.databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{ + CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - } else { - // Nothing to do and not in a waiting state? This is likely a bug, but, hey: pretend to be in ready! - if(!([state isEqualToString:SecCKKSZoneKeyStateReady] || [state isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock])) { - ckkserror("ckkskey", self, "No action to take in state %@; BUG, but: maybe we're ready?", state); - nextState = SecCKKSZoneKeyStateReady; - self.keyStateMachineOperation = [self operationToEnterState:nextState keyStateError:nil named:@"next-key-state"]; - [self scheduleOperation: self.keyStateMachineOperation]; - } - } + if(keyset.error) { + ckkserror("ckkskey", self, "Unable to load keyset: %@", keyset.error); + op.nextState = newState; - // If the keystate is non-transient, ensure we've loaded the keyset, and provide it to any waiters - // If it is transient, just call the handler anyway: it needs to set up the dependency - if(!CKKSKeyStateTransient(self.keyHierarchyState) && keyset == nil) { - keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - } - [self _onqueueHandleKeyStateNonTransientDependency:keyset]; -} + [self.operationDependencies provideKeySet:keyset]; + return; + } -- (void)_onqueueHandleKeyStateNonTransientDependency:(CKKSCurrentKeySet* _Nullable)keyset { - dispatch_assert_queue(self.queue); + if(!keyset.currentTLKPointer.currentKeyUUID) { + // In this case, there's no current TLK at all. Go into "wait for tlkcreation"; + op.nextState = SecCKKSZoneKeyStateWaitForTLKCreation; + [self.operationDependencies provideKeySet:keyset]; + return; + } - if(CKKSKeyStateTransient(self.keyHierarchyState)) { - if(self.keyStateNonTransientDependency == nil || [self.keyStateNonTransientDependency isFinished]) { - self.keyStateNonTransientDependency = [self createKeyStateNontransientDependency]; - } - } else { - // Nontransient: go for it - if(self.keyStateNonTransientDependency) { - [self scheduleOperation: self.keyStateNonTransientDependency]; - self.keyStateNonTransientDependency = nil; - } + if(self.trustStatus != CKKSAccountStatusAvailable) { + ckksnotice("ckkskey", self, "TLK is missing, but no trust is present."); + op.nextState = SecCKKSZoneKeyStateLoseTrust; - if(keyset && keyset.currentTLKPointer.currentKeyUUID) { - [self _onqueueRunKeysetProviderOperations:keyset]; - } else { - ckksnotice("ckkskey", self, "State machine is nontransient, but no keyset..."); - } - } -} + [self.operationDependencies provideKeySet:keyset]; + return; + } -- (NSOperation*)operationToEnterState:(CKKSZoneKeyState*)state keyStateError:(NSError* _Nullable)keyStateError named:(NSString*)name { - WEAKIFY(self); + bool otherDevicesPresent = [self _onqueueOtherDevicesReportHavingTLKs:keyset + trustStates:trustStates]; + if(otherDevicesPresent) { + // We expect this keyset to continue to exist. Send it to our listeners. + [self.operationDependencies provideKeySet:keyset]; - return [NSBlockOperation named:name withBlock:^{ - STRONGIFY(self); - if(!self) { + op.nextState = newState; + } else { + ckksnotice("ckkskey", self, "No other devices claim to have the TLK. Resetting zone..."); + op.nextState = SecCKKSZoneKeyStateResettingZone; + } return; - } - [self dispatchSyncWithAccountKeys:^bool{ - [self _onqueueAdvanceKeyStateMachineToState:state withError:keyStateError]; - return true; }]; }]; } -- (BOOL)otherDevicesReportHavingTLKs:(CKKSCurrentKeySet*)keyset -{ - __block BOOL report = false; - [self dispatchSync:^bool{ - report = [self _onqueueOtherDevicesReportHavingTLKs:keyset]; - return true; - }]; - return report ? YES : NO; -} - - (bool)_onqueueOtherDevicesReportHavingTLKs:(CKKSCurrentKeySet*)keyset + trustStates:(NSArray*)trustStates { - dispatch_assert_queue(self.queue); - //Has there been any activity indicating that other trusted devices have keys in the past 45 days, or untrusted devices in the past 4? // (We chose 4 as devices attempt to upload their device state every 3 days. If a device is unceremoniously kicked out of circle, we normally won't immediately reset.) NSDate* now = [NSDate date]; @@ -1501,7 +1124,7 @@ NSMutableSet* trustedPeerIDs = [NSMutableSet set]; - for(CKKSPeerProviderState* trustState in self.currentTrustStates) { + for(CKKSPeerProviderState* trustState in trustStates) { for(id peer in trustState.currentTrustedPeers) { [trustedPeerIDs addObject:peer.peerID]; } @@ -1509,7 +1132,7 @@ NSError* localerror = nil; - NSArray* allDeviceStates = [CKKSDeviceStateEntry allInZone:self.zoneID error:&localerror]; + NSArray* allDeviceStates = [CKKSDeviceStateEntry allInZone:keyset.currentTLKPointer.zoneID error:&localerror]; if(localerror) { ckkserror("ckkskey", self, "Error fetching device states: %@", localerror); localerror = nil; @@ -1519,514 +1142,64 @@ // The peerIDs in CDSEs aren't written with the peer prefix. Make sure we match both. NSString* sosPeerID = device.circlePeerID ? [CKKSSOSPeerPrefix stringByAppendingString:device.circlePeerID] : nil; - if([trustedPeerIDs containsObject:device.circlePeerID] || - [trustedPeerIDs containsObject:sosPeerID] || - [trustedPeerIDs containsObject:device.octagonPeerID]) { - // Is this a recent DSE? If it's older than the deadline, skip it - if([device.storedCKRecord.modificationDate compare:trustedDeadline] == NSOrderedAscending) { - ckksnotice("ckkskey", self, "Trusted device state (%@) is too old; ignoring", device); - continue; - } - } else { - // Device is untrusted. How does it fare with the untrustedDeadline? - if([device.storedCKRecord.modificationDate compare:untrustedDeadline] == NSOrderedAscending) { - ckksnotice("ckkskey", self, "Device (%@) is not trusted and from too long ago; ignoring device state (%@)", device.circlePeerID, device); - continue; - } else { - ckksnotice("ckkskey", self, "Device (%@) is not trusted, but very recent. Including in heuristic: %@", device.circlePeerID, device); - } - } - - if([device.keyState isEqualToString:SecCKKSZoneKeyStateReady] || - [device.keyState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]) { - ckksnotice("ckkskey", self, "Other device (%@) has keys; it should send them to us", device); - return true; - } - } - - NSArray* tlkShares = [CKKSTLKShareRecord allForUUID:keyset.currentTLKPointer.currentKeyUUID - zoneID:self.zoneID - error:&localerror]; - if(localerror) { - ckkserror("ckkskey", self, "Error fetching device states: %@", localerror); - localerror = nil; - return false; - } - - for(CKKSTLKShareRecord* tlkShare in tlkShares) { - if([trustedPeerIDs containsObject:tlkShare.senderPeerID] && - [tlkShare.storedCKRecord.modificationDate compare:trustedDeadline] == NSOrderedDescending) { - ckksnotice("ckkskey", self, "Trusted TLK Share (%@) created recently; other devices have keys and should send them to us", tlkShare); - return true; - } - } - - // Okay, how about the untrusted deadline? - for(CKKSTLKShareRecord* tlkShare in tlkShares) { - if([tlkShare.storedCKRecord.modificationDate compare:untrustedDeadline] == NSOrderedDescending) { - ckksnotice("ckkskey", self, "Untrusted TLK Share (%@) created very recently; other devices might have keys and should rejoin the circle (and send them to us)", tlkShare); - return true; - } - } - - return false; -} - -// For this key, who doesn't yet have a valid CKKSTLKShare for it? -// Note that we really want a record sharing the TLK to ourselves, so this function might return -// a non-empty set even if all peers have the TLK: it wants us to make a record for ourself. -- (NSSet>*)_onqueueFindPeers:(CKKSPeerProviderState*)trustState - missingShare:(CKKSKey*)key - afterUploading:(NSSet* _Nullable)newShares - error:(NSError* __autoreleasing*)error -{ - dispatch_assert_queue(self.queue); - - if(!key) { - ckkserror("ckksshare", self, "Attempting to find missing shares for nil key"); - return [NSSet set]; - } - - if(trustState.currentTrustedPeersError) { - ckkserror("ckksshare", self, "Couldn't find missing shares because trusted peers aren't available: %@", trustState.currentTrustedPeersError); - if(error) { - *error = trustState.currentTrustedPeersError; - } - return [NSSet set]; - } - if(trustState.currentSelfPeersError) { - ckkserror("ckksshare", self, "Couldn't find missing shares because self peers aren't available: %@", trustState.currentSelfPeersError); - if(error) { - *error = trustState.currentSelfPeersError; - } - return [NSSet set]; - } - - NSMutableSet>* peersMissingShares = [NSMutableSet set]; - - // Ensure that the 'self peer' is one of the current trusted peers. Otherwise, any TLKShare we create - // won't be considered trusted the next time through... - if(![trustState.currentTrustedPeerIDs containsObject:trustState.currentSelfPeers.currentSelf.peerID]) { - ckkserror("ckksshare", self, "current self peer (%@) is not in the set of trusted peers: %@", - trustState.currentSelfPeers.currentSelf.peerID, - trustState.currentTrustedPeerIDs); - - if(error) { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSLackingTrust - description:[NSString stringWithFormat:@"current self peer (%@) is not in the set of trusted peers", - trustState.currentSelfPeers.currentSelf.peerID]]; - } - - return nil; - } - - for(id peer in trustState.currentTrustedPeers) { - if(![peer shouldHaveView:self.zoneName]) { - ckkserror("ckksshare", self, "Peer (%@) is not supposed to have view, skipping", peer); - continue; - } - - NSError* peerError = nil; - // Find all the shares for this peer for this key - NSArray* currentPeerShares = [CKKSTLKShareRecord allFor:peer.peerID - keyUUID:key.uuid - zoneID:self.zoneID - error:&peerError]; - - if(peerError) { - ckkserror("ckksshare", self, "Couldn't load shares for peer %@: %@", peer, peerError); - if(error) { - *error = peerError; - } - return nil; - } - - // Include the new shares, too.... - NSArray* possiblePeerShares = newShares ? [currentPeerShares arrayByAddingObjectsFromArray:[newShares allObjects]] : currentPeerShares; - - // Determine if we think this peer has enough things shared to them - bool alreadyShared = false; - for(CKKSTLKShareRecord* existingPeerShare in possiblePeerShares) { - // Ensure this share is to this peer... - if(![existingPeerShare.share.receiverPeerID isEqualToString:peer.peerID]) { - continue; - } - - // If an SOS Peer sent this share, is its signature still valid? Or did the signing key change? - if([existingPeerShare.senderPeerID hasPrefix:CKKSSOSPeerPrefix]) { - NSError* signatureError = nil; - if(![existingPeerShare signatureVerifiesWithPeerSet:trustState.currentTrustedPeers error:&signatureError]) { - ckksnotice("ckksshare", self, "Existing TLKShare's signature doesn't verify with current peer set: %@ %@", signatureError, existingPeerShare); - continue; - } - } - - if([existingPeerShare.tlkUUID isEqualToString:key.uuid] && [trustState.currentTrustedPeerIDs containsObject:existingPeerShare.senderPeerID]) { - // Was this shared to us? - if([peer.peerID isEqualToString: trustState.currentSelfPeers.currentSelf.peerID]) { - // We only count this as 'found' if we did the sharing and it's to our current keys - NSData* currentKey = trustState.currentSelfPeers.currentSelf.publicEncryptionKey.keyData; - - if([existingPeerShare.senderPeerID isEqualToString:trustState.currentSelfPeers.currentSelf.peerID] && - [existingPeerShare.share.receiverPublicEncryptionKeySPKI isEqual:currentKey]) { - ckksnotice("ckksshare", self, "Local peer %@ is shared %@ via self: %@", peer, key, existingPeerShare); - alreadyShared = true; - break; - } else { - ckksnotice("ckksshare", self, "Local peer %@ is shared %@ via trusted %@, but that's not good enough", peer, key, existingPeerShare); - } - - } else { - // Was this shared to the remote peer's current keys? - NSData* currentKeySPKI = peer.publicEncryptionKey.keyData; - - if([existingPeerShare.share.receiverPublicEncryptionKeySPKI isEqual:currentKeySPKI]) { - // Some other peer has a trusted share. Cool! - ckksnotice("ckksshare", self, "Peer %@ is shared %@ via trusted %@", peer, key, existingPeerShare); - alreadyShared = true; - break; - } else { - ckksnotice("ckksshare", self, "Peer %@ has a share for %@, but to old keys: %@", peer, key, existingPeerShare); - } - } - } - } - - if(!alreadyShared) { - // Add this peer to our set, if it has an encryption key to receive the share - if(peer.publicEncryptionKey) { - [peersMissingShares addObject:peer]; - } - } - } - - if(peersMissingShares.count > 0u) { - // Log each and every one of the things - ckksnotice("ckksshare", self, "Missing TLK shares for %lu peers: %@", (unsigned long)peersMissingShares.count, peersMissingShares); - ckksnotice("ckksshare", self, "Self peers are (%@) %@", trustState.currentSelfPeersError ?: @"no error", trustState.currentSelfPeers); - ckksnotice("ckksshare", self, "Trusted peers are (%@) %@", trustState.currentTrustedPeersError ?: @"no error", trustState.currentTrustedPeers); - } - - return peersMissingShares; -} - -- (BOOL)_onqueueAreNewSharesSufficient:(NSSet*)newShares - currentTLK:(CKKSKey*)key - error:(NSError* __autoreleasing*)error -{ - dispatch_assert_queue(self.queue); - - for(CKKSPeerProviderState* trustState in self.currentTrustStates) { - NSError* localError = nil; - NSSet>* peersMissingShares = [self _onqueueFindPeers:trustState - missingShare:key - afterUploading:newShares - error:&localError]; - if(peersMissingShares == nil || localError) { - if(trustState.essential) { - if(error) { - *error = localError; - } - return NO; - } else { - ckksnotice("ckksshare", self, "Failed to find peers for nonessential system: %@", trustState); - // Not a hard failure. - } - } - - if(peersMissingShares.count > 0) { - ckksnotice("ckksshare", self, "New share set is missing shares for peers: %@", peersMissingShares); - return NO; - } - } - - return YES; -} - -- (NSSet*)_onqueueCreateMissingKeyShares:(CKKSKey*)key - error:(NSError* __autoreleasing*)error -{ - NSError* localerror = nil; - NSSet* newShares = nil; - - // If any one of our trust states succeed, this function doesn't have an error - for(CKKSPeerProviderState* trustState in self.currentTrustStates) { - NSError* stateError = nil; - - NSSet* newTrustShares = [self _onqueueCreateMissingKeyShares:key - peers:trustState - error:&stateError]; - - - if(newTrustShares && !stateError) { - newShares = newShares ? [newShares setByAddingObjectsFromSet:newTrustShares] : newTrustShares; - } else { - ckksnotice("ckksshare", self, "Unable to create shares for trust set %@: %@", trustState, stateError); - if(localerror == nil) { - localerror = stateError; - } - } - } - - // Only report an error if none of the trust states were able to succeed - if(newShares) { - return newShares; - } else { - if(error && localerror) { - *error = localerror; - } - return nil; - } -} - -- (NSSet*)_onqueueCreateMissingKeyShares:(CKKSKey*)key - peers:(CKKSPeerProviderState*)trustState - error:(NSError* __autoreleasing*)error -{ - dispatch_assert_queue(self.queue); - - if(trustState.currentTrustedPeersError) { - ckkserror("ckksshare", self, "Couldn't create missing shares because trusted peers aren't available: %@", trustState.currentTrustedPeersError); - if(error) { - *error = trustState.currentTrustedPeersError; - } - return nil; - } - if(trustState.currentSelfPeersError) { - ckkserror("ckksshare", self, "Couldn't create missing shares because self peers aren't available: %@", trustState.currentSelfPeersError); - if(error) { - *error = trustState.currentSelfPeersError; - } - return nil; - } - - NSSet>* remainingPeers = [self _onqueueFindPeers:trustState missingShare:key afterUploading:nil error:error]; - NSMutableSet* newShares = [NSMutableSet set]; - - if(!remainingPeers) { - return nil; - } - - NSError* localerror = nil; - - if(![key ensureKeyLoaded:error]) { - return nil; - } - - for(id peer in remainingPeers) { - if(!peer.publicEncryptionKey) { - ckksnotice("ckksshare", self, "No need to make TLK for %@; they don't have any encryption keys", peer); - continue; - } - - // Create a share for this peer. - ckksnotice("ckksshare", self, "Creating share of %@ as %@ for %@", key, trustState.currentSelfPeers.currentSelf, peer); - CKKSTLKShareRecord* newShare = [CKKSTLKShareRecord share:key - as:trustState.currentSelfPeers.currentSelf - to:peer - epoch:-1 - poisoned:0 - error:&localerror]; - - if(localerror) { - ckkserror("ckksshare", self, "Couldn't create new share for %@: %@", peer, localerror); - if(error) { - *error = localerror; - } - return nil; - } - - [newShares addObject: newShare]; - } - - return newShares; -} - -- (CKKSZoneKeyState*)_onqueueEnsureKeyHierarchyHealth:(CKKSCurrentKeySet*)set error:(NSError* __autoreleasing *)error { - dispatch_assert_queue(self.queue); - - if(!set.currentTLKPointer && !set.currentClassAPointer && !set.currentClassCPointer) { - ckkserror("ckkskey", self, "Error examining existing key hierarchy (missing all CKPs, likely no hierarchy exists): %@", set); - return SecCKKSZoneKeyStateWaitForTLKCreation; - } - - // Check keyset - if(!set.tlk || !set.classA || !set.classC) { - ckkserror("ckkskey", self, "Error examining existing key hierarchy (missing at least one key): %@", set); - if(error) { - *error = set.error; - } - return SecCKKSZoneKeyStateUnhealthy; - } - - NSError* localerror = nil; - bool probablyOkIfUnlocked = false; - - // keychain being locked is not a fatal error here - [set.tlk loadKeyMaterialFromKeychain:&localerror]; - if(localerror && !([localerror.domain isEqual: @"securityd"] && localerror.code == errSecInteractionNotAllowed)) { - ckkserror("ckkskey", self, "Error loading TLK(%@): %@", set.tlk, localerror); - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateUnhealthy; - } else if(localerror) { - ckkserror("ckkskey", self, "Soft error loading TLK(%@), maybe locked: %@", set.tlk, localerror); - probablyOkIfUnlocked = true; - } - localerror = nil; - - // keychain being locked is not a fatal error here - [set.classA loadKeyMaterialFromKeychain:&localerror]; - if(localerror && !([localerror.domain isEqual: @"securityd"] && localerror.code == errSecInteractionNotAllowed)) { - ckkserror("ckkskey", self, "Error loading classA key(%@): %@", set.classA, localerror); - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateUnhealthy; - } else if(localerror) { - ckkserror("ckkskey", self, "Soft error loading classA key(%@), maybe locked: %@", set.classA, localerror); - probablyOkIfUnlocked = true; - } - localerror = nil; - - // keychain being locked is a fatal error here, since this is class C - [set.classC loadKeyMaterialFromKeychain:&localerror]; - if(localerror) { - ckkserror("ckkskey", self, "Error loading classC(%@): %@", set.classC, localerror); - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateUnhealthy; - } - - // Check that the classA and classC keys point to the current TLK - if(![set.classA.parentKeyUUID isEqualToString: set.tlk.uuid]) { - localerror = [NSError errorWithDomain:CKKSServerExtensionErrorDomain - code:CKKSServerUnexpectedSyncKeyInChain - userInfo:@{ - NSLocalizedDescriptionKey: @"Current class A key does not wrap to current TLK", - }]; - ckkserror("ckkskey", self, "Key hierarchy unhealthy: %@", localerror); - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateUnhealthy; - } - if(![set.classC.parentKeyUUID isEqualToString: set.tlk.uuid]) { - localerror = [NSError errorWithDomain:CKKSServerExtensionErrorDomain - code:CKKSServerUnexpectedSyncKeyInChain - userInfo:@{ - NSLocalizedDescriptionKey: @"Current class C key does not wrap to current TLK", - }]; - ckkserror("ckkskey", self, "Key hierarchy unhealthy: %@", localerror); - if(error) { - *error = localerror; - } - return SecCKKSZoneKeyStateUnhealthy; - } - - self.activeTLK = [set.tlk uuid]; - - // Now that we're pretty sure we have the keys, are they shared appropriately? - // We need trust in order to proceed here - if(self.currentTrustStates.count == 0u) { - ckkserror("ckkskey", self, "Can't check TLKShares due to missing trust states"); - return SecCKKSZoneKeyStateWaitForTrust; - } - - // Check that every trusted peer has at least one TLK share - // If any trust state check works, don't error out - bool anyTrustStateSucceeded = false; - for(CKKSPeerProviderState* trustState in self.currentTrustStates) { - NSSet>* missingShares = [self _onqueueFindPeers:trustState missingShare:set.tlk afterUploading:nil error:&localerror]; - if(localerror && [self.lockStateTracker isLockedError: localerror]) { - ckkserror("ckkskey", self, "Couldn't find missing TLK shares due to lock state: %@", localerror); - probablyOkIfUnlocked = true; - - } else if(([localerror.domain isEqualToString:TrustedPeersHelperErrorDomain] && localerror.code == TrustedPeersHelperErrorNoPreparedIdentity) || - ([localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSLackingTrust) || - ([localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSNoPeersAvailable)) { - ckkserror("ckkskey", self, "Couldn't find missing TLK shares due some trust issue: %@", localerror); - - if(trustState.essential) { - ckkserror("ckkskey", self, "Trust state is considered essential; entering waitfortrust: %@", trustState); - - // Octagon can reinform us when it thinks we should start again - self.trustStatus = CKKSAccountStatusUnknown; - return SecCKKSZoneKeyStateWaitForTrust; - } else { - ckkserror("ckkskey", self, "Peer provider is considered nonessential; ignoring error: %@", trustState); - continue; - } - - } else if(localerror) { - ckkserror("ckkskey", self, "Error finding missing TLK shares: %@", localerror); - continue; - } - - if(!missingShares || missingShares.count != 0u) { - localerror = [NSError errorWithDomain:CKKSErrorDomain code:CKKSMissingTLKShare - description:[NSString stringWithFormat:@"Missing shares for %lu peers", (unsigned long)missingShares.count]]; - if(error) { - *error = localerror; + if([trustedPeerIDs containsObject:device.circlePeerID] || + [trustedPeerIDs containsObject:sosPeerID] || + [trustedPeerIDs containsObject:device.octagonPeerID]) { + // Is this a recent DSE? If it's older than the deadline, skip it + if([device.storedCKRecord.modificationDate compare:trustedDeadline] == NSOrderedAscending) { + ckksnotice("ckkskey", self, "Trusted device state (%@) is too old; ignoring", device); + continue; } - return SecCKKSZoneKeyStateHealTLKShares; } else { - ckksnotice("ckksshare", self, "TLK (%@) is shared correctly for trust state %@", set.tlk, trustState.peerProviderID); + // Device is untrusted. How does it fare with the untrustedDeadline? + if([device.storedCKRecord.modificationDate compare:untrustedDeadline] == NSOrderedAscending) { + ckksnotice("ckkskey", self, "Device (%@) is not trusted and from too long ago; ignoring device state (%@)", device.circlePeerID, device); + continue; + } else { + ckksnotice("ckkskey", self, "Device (%@) is not trusted, but very recent. Including in heuristic: %@", device.circlePeerID, device); + } } - anyTrustStateSucceeded |= true; - } - - if(!anyTrustStateSucceeded) { - if(error) { - *error = localerror; + if([device.keyState isEqualToString:SecCKKSZoneKeyStateReady] || + [device.keyState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]) { + ckksnotice("ckkskey", self, "Other device (%@) has keys; it should send them to us", device); + return true; } - - return SecCKKSZoneKeyStateError; } - // Got to the bottom? Cool! All keys are present and accounted for. - return probablyOkIfUnlocked ? SecCKKSZoneKeyStateReadyPendingUnlock : SecCKKSZoneKeyStateReady; -} - -- (void)_onqueueKeyHierarchyFetch { - [self _onqueueKeyHierarchyFetchForReasons:[NSSet setWithArray:@[CKKSFetchBecauseKeyHierarchy]]]; -} - -- (void)_onqueueKeyHierarchyFetchForReasons:(NSSet*)reasons -{ - dispatch_assert_queue(self.queue); + NSArray* tlkShares = [CKKSTLKShareRecord allForUUID:keyset.currentTLKPointer.currentKeyUUID + zoneID:keyset.currentTLKPointer.zoneID + error:&localerror]; + if(localerror) { + ckkserror("ckkskey", self, "Error fetching device states: %@", localerror); + localerror = nil; + return false; + } - WEAKIFY(self); - self.keyStateMachineOperation = [NSBlockOperation blockOperationWithBlock: ^{ - STRONGIFY(self); - if(!self) { - ckkserror("ckks", self, "received callback for released object"); - return; + for(CKKSTLKShareRecord* tlkShare in tlkShares) { + if([trustedPeerIDs containsObject:tlkShare.senderPeerID] && + [tlkShare.storedCKRecord.modificationDate compare:trustedDeadline] == NSOrderedDescending) { + ckksnotice("ckkskey", self, "Trusted TLK Share (%@) created recently; other devices have keys and should send them to us", tlkShare); + return true; } - [self.launch addEvent:@"fetch-complete"]; + } - [self dispatchSyncWithAccountKeys: ^bool{ - [self _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateFetchComplete withError: nil]; + // Okay, how about the untrusted deadline? + for(CKKSTLKShareRecord* tlkShare in tlkShares) { + if([tlkShare.storedCKRecord.modificationDate compare:untrustedDeadline] == NSOrderedDescending) { + ckksnotice("ckkskey", self, "Untrusted TLK Share (%@) created very recently; other devices might have keys and should rejoin the circle (and send them to us)", tlkShare); return true; - }]; - }]; - self.keyStateMachineOperation.name = @"waiting-for-fetch"; - - NSOperation* fetchOp = [self.zoneChangeFetcher requestSuccessfulFetchForManyReasons:reasons]; - [self.keyStateMachineOperation addDependency: fetchOp]; + } + } - self.keyStateFetchRequested = false; + return false; } -- (void) handleKeychainEventDbConnection: (SecDbConnectionRef) dbconn - source:(SecDbTransactionSource)txionSource - added: (SecDbItemRef) added - deleted: (SecDbItemRef) deleted - rateLimiter: (CKKSRateLimiter*) rateLimiter +- (void)handleKeychainEventDbConnection:(SecDbConnectionRef) dbconn + source:(SecDbTransactionSource)txionSource + added:(SecDbItemRef) added + deleted:(SecDbItemRef) deleted + rateLimiter:(CKKSRateLimiter*) rateLimiter { if(!SecCKKSIsEnabled()) { ckksnotice("ckks", self, "Skipping handleKeychainEventDbConnection due to disabled CKKS"); @@ -2042,6 +1215,7 @@ bool addedSync = added && SecDbItemIsSyncable(added); bool deletedSync = deleted && SecDbItemIsSyncable(deleted); + bool isTombstoneModification = addedTombstone && deletedTombstone; bool isAdd = ( added && !deleted) || (added && deleted && !addedTombstone && deletedTombstone) || (added && deleted && addedSync && !deletedSync); bool isDelete = (!added && deleted) || (added && deleted && addedTombstone && !deletedTombstone) || (added && deleted && !addedSync && deletedSync); bool isModify = ( added && deleted) && (!isAdd) && (!isDelete); @@ -2065,6 +1239,11 @@ return; } + if(isTombstoneModification) { + ckksnotice("ckks", self, "skipping syncing update of tombstone item (%d, %d)", addedTombstone, deletedTombstone); + return; + } + // It's possible to ask for an item to be deleted without adding a corresponding tombstone. // This is arguably a bug, as it generates an out-of-sync state, but it is in the API contract. // CKKS should ignore these, but log very upset messages. @@ -2083,18 +1262,23 @@ } if(txionSource == kSecDbSOSTransaction) { - ckksnotice("ckks", self, "Received an incoming %@ from SOS", isAdd ? @"addition" : (isModify ? @"modification" : @"deletion")); + NSString* addedUUID = (__bridge NSString*)SecDbItemGetValue(added, &v10itemuuid, NULL); + ckksnotice("ckks", self, "Received an incoming %@ from SOS (%@)", + isAdd ? @"addition" : (isModify ? @"modification" : @"deletion"), + addedUUID); } // Our caller gave us a database connection. We must get on the local queue to ensure atomicity // Note that we're at the mercy of the surrounding db transaction, so don't try to rollback here - [self dispatchSyncWithConnection: dbconn block: ^bool { + [self dispatchSyncWithConnection:dbconn + readWriteTxion:YES + block:^CKKSDatabaseTransactionResult { // Schedule a "view changed" notification [self.notifyViewChangedScheduler trigger]; if(self.accountStatus == CKKSAccountStatusNoAccount) { // No account; CKKS shouldn't attempt anything. - self.droppedItems = true; + [self.stateMachine _onqueueHandleFlag:CKKSFlagScanLocalItems]; ckksnotice("ckks", self, "Dropping sync item modification due to CK account state; will scan to find changes later"); // We're positively not logged into CloudKit, and therefore don't expect this item to be synced anytime particularly soon. @@ -2105,40 +1289,48 @@ [CKKSViewManager callSyncCallbackWithErrorNoAccount: syncCallback]; } - return true; + return CKKSDatabaseTransactionCommit; } CKKSOutgoingQueueEntry* oqe = nil; if (isAdd) { - oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionAdd ckks:self error: &error]; + oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionAdd zoneID:self.zoneID error: &error]; } else if(isDelete) { - oqe = [CKKSOutgoingQueueEntry withItem: deleted action: SecCKKSActionDelete ckks:self error: &error]; + oqe = [CKKSOutgoingQueueEntry withItem: deleted action: SecCKKSActionDelete zoneID:self.zoneID error: &error]; } else if(isModify) { - oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionModify ckks:self error: &error]; + oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionModify zoneID:self.zoneID error: &error]; } else { ckkserror("ckks", self, "processKeychainEventItemAdded given garbage: %@ %@", added, deleted); - return true; + return CKKSDatabaseTransactionCommit; + } + + if(!self.itemSyncingEnabled) { + // Call any callback now; they're not likely to get the sync they wanted + SecBoolNSErrorCallback syncCallback = [[CKKSViewManager manager] claimCallbackForUUID:oqe.uuid]; + if(syncCallback) { + syncCallback(false, [NSError errorWithDomain:CKKSErrorDomain + code:CKKSErrorViewIsPaused + description:@"View is paused; item is not expected to sync"]); + } } - CKOperationGroup* operationGroup = [CKOperationGroup CKKSGroupWithName:@"keychain-api-use"]; + CKOperationGroup* operationGroup = txionSource == kSecDbSOSTransaction + ? [CKOperationGroup CKKSGroupWithName:@"sos-incoming-item"] + : [CKOperationGroup CKKSGroupWithName:@"keychain-api-use"]; if(error) { ckkserror("ckks", self, "Couldn't create outgoing queue entry: %@", error); - self.droppedItems = true; - - // If the problem is 'no UUID', launch a scan operation to find and fix it - // We don't want to fix it up here, in the closing moments of a transaction - if([error.domain isEqualToString:CKKSErrorDomain] && error.code == CKKSNoUUIDOnItem) { - ckksnotice("ckks", self, "Launching scan operation to find UUID"); - [self scanLocalItems:@"uuid-find-scan" ckoperationGroup:operationGroup after:nil]; - } + [self.stateMachine _onqueueHandleFlag:CKKSFlagScanLocalItems]; // If the problem is 'couldn't load key', tell the key hierarchy state machine to fix it if([error.domain isEqualToString:CKKSErrorDomain] && error.code == errSecItemNotFound) { - [self.pokeKeyStateMachineScheduler trigger]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; } - return true; + return CKKSDatabaseTransactionCommit; + } else if(!oqe) { + ckkserror("ckks", self, "Decided that no operation needs to occur for %@", error); + return CKKSDatabaseTransactionCommit; } if(rateLimiter) { @@ -2153,39 +1345,46 @@ [oqe saveToDatabaseWithConnection: dbconn error: &error]; if(error) { ckkserror("ckks", self, "Couldn't save outgoing queue entry to database: %@", error); - return true; + return CKKSDatabaseTransactionCommit; } else { ckksnotice("ckks", self, "Saved %@ to outgoing queue", oqe); } // This update supercedes all other local modifications to this item (_except_ those in-flight). // Delete all items in reencrypt or error. - CKKSOutgoingQueueEntry* reencryptOQE = [CKKSOutgoingQueueEntry tryFromDatabase:oqe.uuid state:SecCKKSStateReencrypt zoneID:self.zoneID error:&error]; + NSArray* siblings = [CKKSOutgoingQueueEntry allWithUUID:oqe.uuid + states:@[SecCKKSStateReencrypt, SecCKKSStateError] + zoneID:self.zoneID + error:&error]; if(error) { - ckkserror("ckks", self, "Couldn't load reencrypt OQE sibling for %@: %@", oqe, error); + ckkserror("ckks", self, "Couldn't load OQE siblings for %@: %@", oqe, error); } - if(reencryptOQE) { - [reencryptOQE deleteFromDatabase:&error]; - if(error) { - ckkserror("ckks", self, "Couldn't delete reencrypt OQE sibling(%@) for %@: %@", reencryptOQE, oqe, error); + + for(CKKSOutgoingQueueEntry* oqeSibling in siblings) { + NSError* deletionError = nil; + [oqeSibling deleteFromDatabase:&deletionError]; + if(deletionError) { + ckkserror("ckks", self, "Couldn't delete OQE sibling(%@) for %@: %@", oqeSibling, oqe.uuid, deletionError); } - error = nil; } - CKKSOutgoingQueueEntry* errorOQE = [CKKSOutgoingQueueEntry tryFromDatabase:oqe.uuid state:SecCKKSStateError zoneID:self.zoneID error:&error]; - if(error) { - ckkserror("ckks", self, "Couldn't load error OQE sibling for %@: %@", oqe, error); - } - if(errorOQE) { - [errorOQE deleteFromDatabase:&error]; - if(error) { - ckkserror("ckks", self, "Couldn't delete error OQE sibling(%@) for %@: %@", reencryptOQE, oqe, error); + // This update also supercedes any remote changes that are pending. + NSError* iqeError = nil; + CKKSIncomingQueueEntry* iqe = [CKKSIncomingQueueEntry tryFromDatabase:oqe.uuid zoneID:self.zoneID error:&iqeError]; + if(iqeError) { + ckkserror("ckks", self, "Couldn't find IQE matching %@: %@", oqe.uuid, error); + } else if(iqe) { + [iqe deleteFromDatabase:&iqeError]; + if(iqeError) { + ckkserror("ckks", self, "Couldn't delete IQE matching %@: %@", oqe.uuid, error); + } else { + ckksnotice("ckks", self, "Deleted IQE matching changed item %@", oqe.uuid); } } [self processOutgoingQueue:operationGroup]; - return true; + return CKKSDatabaseTransactionCommit; }]; } @@ -2295,7 +1494,7 @@ STRONGIFY(self); - [self dispatchSync: ^bool { + [self dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSString* currentIdentifier = [NSString stringWithFormat:@"%@-%@", accessGroup, identifier]; @@ -2304,9 +1503,15 @@ zoneID:self.zoneID error:&error]; if(!cip || error) { - ckkserror("ckkscurrent", self, "No current item pointer for %@", currentIdentifier); + if([error.domain isEqualToString:@"securityd"] && error.code == errSecItemNotFound) { + // This error is common and very, very noisy. Shorten it and don't log here (the framework should log for us) + ckksinfo("ckkscurrent", self, "No current item pointer for %@", currentIdentifier); + error = [NSError errorWithDomain:@"securityd" code:errSecItemNotFound description:[NSString stringWithFormat:@"No current item pointer found for %@", currentIdentifier]]; + } else { + ckkserror("ckkscurrent", self, "No current item pointer for %@", currentIdentifier); + } complete(nil, error); - return false; + return; } if(!cip.currentItemUUID) { @@ -2314,12 +1519,12 @@ complete(nil, [NSError errorWithDomain:CKKSErrorDomain code:errSecInternalError description:@"Current item pointer is empty"]); - return false; + return; } ckksinfo("ckkscurrent", self, "Retrieved current item pointer: %@", cip); complete(cip.currentItemUUID, NULL); - return true; + return; }]; }]; @@ -2327,107 +1532,66 @@ [self scheduleOperation: getCurrentItem]; } -- (CKKSKey*) keyForItem: (SecDbItemRef) item error: (NSError * __autoreleasing *) error { - CKKSKeyClass* class = nil; - - NSString* protection = (__bridge NSString*)SecDbItemGetCachedValueWithName(item, kSecAttrAccessible); - if([protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleWhenUnlocked]) { - class = SecCKKSKeyClassA; - } else if([protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleAlwaysPrivate] || - [protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleAfterFirstUnlock]) { - class = SecCKKSKeyClassC; - } else { - NSError* localError = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSInvalidKeyClass - description:[NSString stringWithFormat:@"can't pick key class for protection %@", protection]]; - ckkserror("ckks", self, "can't pick key class: %@ %@", localError, item); - if(error) { - *error = localError; - } - - return nil; - } - - NSError* currentKeyError = nil; - CKKSKey* key = [CKKSKey currentKeyForClass: class zoneID:self.zoneID error:¤tKeyError]; - if(!key || currentKeyError) { - ckkserror("ckks", self, "Couldn't find current key for %@: %@", class, currentKeyError); - - if(error) { - *error = currentKeyError; - } - return nil; - } - - // and make sure it's unwrapped. - NSError* loadedError = nil; - if(![key ensureKeyLoaded:&loadedError]) { - ckkserror("ckks", self, "Couldn't load key(%@): %@", key, loadedError); - if(error) { - *error = loadedError; - } - return nil; - } - - return key; -} - -- (CKKSResultOperation*)findKeySet +- (CKKSResultOperation*)findKeySet:(BOOL)refetchBeforeReturningKeySet { __block CKKSResultOperation* keysetOp = nil; + __block BOOL moveFromWaitForTrust = NO; - [self dispatchSyncWithAccountKeys:^bool { - CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; - if(keyset.currentTLKPointer.currentKeyUUID && keyset.tlk.uuid) { - ckksnotice("ckks", self, "Already have keyset %@", keyset); - - keysetOp = [[CKKSProvideKeySetOperation alloc] initWithZoneName:self.zoneName keySet:keyset]; - [self scheduleOperationWithoutDependencies:keysetOp]; - return true; - } else if([self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload]) { - CKKSCurrentKeySet* proposedKeySet = self.lastNewTLKOperation.keyset; - ckksnotice("ckks", self, "Already have proposed keyset %@", proposedKeySet); + [self dispatchSyncWithReadOnlySQLTransaction:^{ + keysetOp = (CKKSProvideKeySetOperation*)[self findFirstPendingOperation:self.operationDependencies.keysetProviderOperations]; + if(!keysetOp) { + keysetOp = [[CKKSProvideKeySetOperation alloc] initWithZoneName:self.zoneName]; + [self.operationDependencies.keysetProviderOperations addObject:keysetOp]; - keysetOp = [[CKKSProvideKeySetOperation alloc] initWithZoneName:self.zoneName keySet:proposedKeySet]; + // This is an abuse of operations: they should generally run when added to a queue, not wait, but this allows recipients to set timeouts [self scheduleOperationWithoutDependencies:keysetOp]; - return true; - } else { - // No existing keyset (including keys) exists. - // The state machine will know what to do! - self.tlkCreationRequested = true; + } - ckksnotice("ckks", self, "Received a keyset request; forwarding to state machine"); + if(refetchBeforeReturningKeySet) { + ckksnotice("ckks", self, "Refetch requested before returning key set!"); - keysetOp = (CKKSProvideKeySetOperation*) [self findFirstPendingOperation:self.keysetProviderOperations]; - if(!keysetOp) { - keysetOp = [[CKKSProvideKeySetOperation alloc] initWithZoneName:self.zoneName]; - [self.keysetProviderOperations addObject:keysetOp]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagFetchRequested]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; - // This is an abuse of operations: they should generally run when added to a queue, not wait, but this allows recipients to set timeouts - [self scheduleOperationWithoutDependencies:keysetOp]; + if([self.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) { + moveFromWaitForTrust = YES; } - - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; + return; } - return true; - }]; + CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; + if(keyset.currentTLKPointer.currentKeyUUID && + (keyset.tlk.uuid || + [self.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateWaitForTrust] || + [self.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateWaitForTLK])) { + ckksnotice("ckks", self, "Already have keyset %@", keyset); - return keysetOp; -} + [keysetOp provideKeySet:keyset]; + return; -- (void)_onqueueRunKeysetProviderOperations:(CKKSCurrentKeySet*)keyset -{ - ckksnotice("ckkskey", self, "Providing keyset (%@) to listeners", keyset); + } else if([self.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) { + // No keyset exists, but we're in waitfortrust? Seems like a bug. Move us out of this state... - // We have some keyset; they can ask again if they want a new one - self.tlkCreationRequested = false; + ckksnotice("ckks", self, "Received a keyset request in an odd state; forwarding to state machine"); + [self.stateMachine _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; + moveFromWaitForTrust = YES; - for(CKKSResultOperation* op in self.keysetProviderOperations) { - if([op isPending]) { - [op provideKeySet:keyset]; - } + } else { + // The key state machine will know what to do. + [self.stateMachine _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; + }; + }]; + + if(moveFromWaitForTrust) { + [self.stateMachine handleExternalRequest:[[OctagonStateTransitionRequest alloc] init:@"fix-bug" + sourceStates:[NSSet setWithObject:SecCKKSZoneKeyStateWaitForTrust] + serialQueue:self.queue + timeout:5 * NSEC_PER_SEC + transitionOp:[OctagonStateTransitionOperation named:@"fix-bug" + entering:SecCKKSZoneKeyStateWaitForTLKCreation]]]; } + + return keysetOp; } - (void)receiveTLKUploadRecords:(NSArray*)records @@ -2446,16 +1610,31 @@ return; } - [self dispatchSyncWithAccountKeys:^bool { - + [self dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for(CKRecord* record in zoneRecords) { [self _onqueueCKRecordChanged:record resync:false]; } - return true; + [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateTLKsUploaded]; + + return CKKSDatabaseTransactionCommit; }]; } +- (BOOL)requiresTLKUpload +{ + __block BOOL requiresUpload = NO; + dispatch_sync(self.queue, ^{ + // We want to return true only if we're in a state that immediately requires an upload. + if(([self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload] || + [self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation])) { + requiresUpload = YES; + } + }); + + return requiresUpload; +} + // Use the following method to find the first pending operation in a weak collection - (NSOperation*)findFirstPendingOperation: (NSHashTable*) table { return [self findFirstPendingOperation:table ofClass:nil]; @@ -2473,30 +1652,18 @@ } } -// Use the following method to count the pending operations in a weak collection -- (int64_t)countPendingOperations: (NSHashTable*) table { - @synchronized(table) { - int count = 0; - for(NSOperation* op in table) { - if(op != nil && !([op isExecuting] || [op isFinished])) { - count++; - } - } - return count; - } -} - -- (CKKSOutgoingQueueOperation*)processOutgoingQueue:(CKOperationGroup*)ckoperationGroup { +- (CKKSOutgoingQueueOperation*)processOutgoingQueue:(CKOperationGroup* _Nullable)ckoperationGroup { return [self processOutgoingQueueAfter:nil ckoperationGroup:ckoperationGroup]; } -- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation*)after ckoperationGroup:(CKOperationGroup*)ckoperationGroup { +- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after + ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup { return [self processOutgoingQueueAfter:after requiredDelay:DISPATCH_TIME_FOREVER ckoperationGroup:ckoperationGroup]; } -- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation*)after +- (CKKSOutgoingQueueOperation*)processOutgoingQueueAfter:(CKKSResultOperation* _Nullable)after requiredDelay:(uint64_t)requiredDelay - ckoperationGroup:(CKOperationGroup*)ckoperationGroup + ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup { CKKSOutgoingQueueOperation* outgoingop = (CKKSOutgoingQueueOperation*) [self findFirstPendingOperation:self.outgoingQueueOperations @@ -2513,7 +1680,7 @@ } // Will log any pending dependencies as well - ckksnotice("ckksoutgoing", self, "Returning existing %@", outgoingop); + ckksinfo("ckksoutgoing", self, "Returning existing %@", outgoingop); // Shouldn't be necessary, but can't hurt [self.outgoingQueueOperationScheduler triggerAt:requiredDelay]; @@ -2521,7 +1688,11 @@ } } - CKKSOutgoingQueueOperation* op = [[CKKSOutgoingQueueOperation alloc] initWithCKKSKeychainView:self ckoperationGroup:ckoperationGroup]; + CKKSOutgoingQueueOperation* op = [[CKKSOutgoingQueueOperation alloc] initWithDependencies:self.operationDependencies + ckks:self + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateUnhealthy + ckoperationGroup:ckoperationGroup]; op.name = @"outgoing-queue-operation"; [op addNullableDependency:after]; [op addNullableDependency:self.outgoingQueueOperationScheduler.operationDependency]; @@ -2569,6 +1740,13 @@ } - (CKKSIncomingQueueOperation*) processIncomingQueue:(bool)failOnClassA after: (CKKSResultOperation*) after { + return [self processIncomingQueue:failOnClassA after:after policyConsideredAuthoritative:false]; +} + +- (CKKSIncomingQueueOperation*)processIncomingQueue:(bool)failOnClassA + after:(CKKSResultOperation*)after + policyConsideredAuthoritative:(bool)policyConsideredAuthoritative +{ CKKSIncomingQueueOperation* incomingop = (CKKSIncomingQueueOperation*) [self findFirstPendingOperation:self.incomingQueueOperations]; if(incomingop) { ckksinfo("ckks", self, "Skipping processIncomingQueue due to at least one pending instance"); @@ -2579,11 +1757,17 @@ // check (again) for race condition; if the op has started we need to add another (for the dependency) if([incomingop isPending]) { incomingop.errorOnClassAFailure |= failOnClassA; + incomingop.handleMismatchedViewItems |= policyConsideredAuthoritative; return incomingop; } } - CKKSIncomingQueueOperation* op = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:self errorOnClassAFailure:failOnClassA]; + CKKSIncomingQueueOperation* op = [[CKKSIncomingQueueOperation alloc] initWithDependencies:self.operationDependencies + ckks:self + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateUnhealthy + errorOnClassAFailure:failOnClassA + handleMismatchedViewItems:policyConsideredAuthoritative]; op.name = @"incoming-queue-operation"; if(after != nil) { [op addSuccessDependency: after]; @@ -2592,6 +1776,7 @@ if(self.resultsOfNextIncomingQueueOperationOperation) { [self.resultsOfNextIncomingQueueOperationOperation addSuccessDependency:op]; [self scheduleOperation:self.resultsOfNextIncomingQueueOperationOperation]; + self.resultsOfNextIncomingQueueOperationOperation = nil; } [self scheduleOperation: op]; @@ -2620,7 +1805,11 @@ } } - scanOperation = [[CKKSScanLocalItemsOperation alloc] initWithCKKSKeychainView:self ckoperationGroup:operationGroup]; + scanOperation = [[CKKSScanLocalItemsOperation alloc] initWithDependencies:self.operationDependencies + ckks:self + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateError + ckoperationGroup:operationGroup]; scanOperation.name = operationName; [scanOperation addNullableDependency:self.lastFixupOperation]; @@ -2630,30 +1819,28 @@ [scanOperation linearDependencies:self.scanLocalItemsOperations]; + // This might generate items for upload. Make sure that any uploads wait until the scan is complete, so we know what to upload + [scanOperation linearDependencies:self.outgoingQueueOperations]; + [self scheduleOperation:scanOperation]; + self.initiatedLocalScan = YES; return scanOperation; } - (CKKSUpdateDeviceStateOperation*)updateDeviceState:(bool)rateLimit waitForKeyHierarchyInitialization:(uint64_t)timeout ckoperationGroup:(CKOperationGroup*)ckoperationGroup { - - WEAKIFY(self); - // If securityd just started, the key state might be in some transient early state. Wait a bit. - CKKSResultOperation* waitForKeyReady = [CKKSResultOperation named:@"device-state-wait" withBlock:^{ - STRONGIFY(self); - ckksnotice("ckksdevice", self, "Finished waiting for key hierarchy transient state, currently %@", self.keyHierarchyState); - }]; - - [waitForKeyReady addNullableDependency:self.keyStateNonTransientDependency]; - [waitForKeyReady timeout:timeout]; - [self.waitingQueue addOperation:waitForKeyReady]; + OctagonStateMultiStateArrivalWatcher* waitForTransient = [[OctagonStateMultiStateArrivalWatcher alloc] initNamed:@"rpc-watcher" + serialQueue:self.queue + states:CKKSKeyStateNonTransientStates()]; + [waitForTransient timeout:timeout]; + [self.stateMachine registerMultiStateArrivalWatcher:waitForTransient]; CKKSUpdateDeviceStateOperation* op = [[CKKSUpdateDeviceStateOperation alloc] initWithCKKSKeychainView:self rateLimit:rateLimit ckoperationGroup:ckoperationGroup]; op.name = @"device-state-operation"; - [op addDependency: waitForKeyReady]; + [op addDependency:waitForTransient.result]; // op modifies the CloudKit zone, so it should insert itself into the list of OutgoingQueueOperations. // Then, we won't have simultaneous zone-modifying operations and confuse ourselves. @@ -2666,8 +1853,15 @@ return op; } +- (void)xpc24HrNotification +{ + // Called roughly once every 24hrs + [self.stateMachine handleFlag:CKKSFlag24hrNotification]; +} + // There are some errors which won't be reported but will be reflected in the CDSE; any error coming out of here is fatal - (CKKSDeviceStateEntry*)_onqueueCurrentDeviceStateEntry: (NSError* __autoreleasing*)error { + dispatch_assert_queue(self.queue); NSError* localerror = nil; CKKSAccountStateTracker* accountTracker = self.accountTracker; @@ -2801,40 +1995,17 @@ return op; } -- (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because { - return [self fetchAndProcessCKChanges:because after:nil]; -} - -- (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because after:(CKKSResultOperation*)after { - if(!SecCKKSIsEnabled()) { +- (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because +{ + if(!SecCKKSIsEnabled()) { ckksinfo("ckks", self, "Skipping fetchAndProcessCKChanges due to disabled CKKS"); return nil; } - if(after) { - [self.zoneChangeFetcher holdFetchesUntil:after]; - } - - // We fetched some changes; try to process them! + // We fetched some changes; try to process them! return [self processIncomingQueue:false after:[self.zoneChangeFetcher requestSuccessfulFetch:because]]; } -- (CKKSResultOperation*)fetchAndProcessCKChangesDueToAPNS:(CKRecordZoneNotification*)notification { - if(!SecCKKSIsEnabled()) { - ckksinfo("ckks", self, "Skipping fetchAndProcessCKChanges due to disabled CKKS"); - return nil; - } - - CKKSResultOperation *fetchOp = [self.zoneChangeFetcher requestFetchDueToAPNS:notification]; - if (fetchOp == nil) { - ckksnotice("ckks", self, "Skipping push induced processCKChanges due to zones are not ready"); - return nil; - } - - // We fetched some changes; try to process them! - return [self processIncomingQueue:false after:fetchOp]; -} - // Lets the view know about a failed CloudKit write. If the error is "already have one of these records", it will // store the new records and kick off the new processing // @@ -2896,13 +2067,13 @@ // The server thinks the classA/C synckeys don't wrap directly the to top TLK, but we don't (otherwise, we would have fixed it). // Issue a key hierarchy fetch and see what's what. ckkserror("ckks", self, "CKKS Server extension has told us about %@ for record %@; requesting refetch and reprocess of key hierarchy", thirdLevelError, recordID); - [self _onqueueKeyStateMachineRequestFetch]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagFetchRequested]; } else if(thirdLevelError.code == CKKSServerMissingRecord) { // The server is concerned that there's a missing record somewhere. // Issue a key hierarchy fetch and see what's happening ckkserror("ckks", self, "CKKS Server extension has told us about %@ for record %@; requesting refetch and reprocess of key hierarchy", thirdLevelError, recordID); - [self _onqueueKeyStateMachineRequestFetch]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagFetchRequested]; } else { ckkserror("ckks", self, "CKKS Server extension has told us about %@ for record %@, but we don't currently handle this error", thirdLevelError, recordID); @@ -2920,7 +2091,7 @@ // TODO: resync doesn't really mean much here; what does it mean for a record to be 'deleted' if you're fetching from scratch? if([recordType isEqual: SecCKRecordItemType]) { - ckksinfo("ckks", self, "CloudKit notification: deleted record(%@): %@", recordType, recordID); + ckksnotice("ckks", self, "CloudKit notification: deleted record(%@): %@", recordType, recordID); NSError* error = nil; NSError* iqeerror = nil; CKKSMirrorEntry* ckme = [CKKSMirrorEntry fromDatabase: [recordID recordName] zoneID:self.zoneID error: &error]; @@ -2934,6 +2105,25 @@ if(iqeerror) { ckkserror("ckks", self, "Couldn't save incoming queue entry: %@", iqeerror); } + + // Delete any pending local changes; this delete wins + NSArray* siblings = [CKKSOutgoingQueueEntry allWithUUID:iqe.uuid + states:@[SecCKKSStateNew, + SecCKKSStateReencrypt, + SecCKKSStateError] + zoneID:self.zoneID + error:&error]; + if(error) { + ckkserror("ckks", self, "Couldn't load OQE sibling for %@: %@", iqe.uuid, error); + } + + for(CKKSOutgoingQueueEntry* oqe in siblings) { + NSError* deletionError = nil; + [oqe deleteFromDatabase:&deletionError]; + if(deletionError) { + ckkserror("ckks", self, "Couldn't delete OQE sibling(%@) for %@: %@", oqe, iqe.uuid, deletionError); + } + } } ckksinfo("ckks", self, "CKKSMirrorEntry was deleted: %@ %@ error: %@", recordID, ckme, error); // TODO: actually pass error back up @@ -3065,7 +2255,7 @@ if(ckme) { if([ckme matchesCKRecord:record] && !resync) { // This is almost certainly a record we uploaded; CKFetchChanges sends them back as new records - ckksnotice("ckks", self, "CloudKit has told us of record we already know about; skipping update"); + ckksnotice("ckks", self, "CloudKit has told us of record we already know about for %@; skipping update", ckme.uuid); return; } @@ -3082,7 +2272,7 @@ if(error) { ckkserror("ckks", self, "couldn't save new CKRecord to database: %@ %@", record, error); } else { - ckksdebug("ckks", self, "CKKSMirrorEntry was created: %@", ckme); + ckksinfo("ckks", self, "CKKSMirrorEntry was created: %@", ckme); } NSError* iqeerror = nil; @@ -3093,27 +2283,25 @@ if(iqeerror) { ckkserror("ckks", self, "Couldn't save modified incoming queue entry: %@", iqeerror); } else { - ckksdebug("ckks", self, "CKKSIncomingQueueEntry was created: %@", iqe); + ckksinfo("ckks", self, "CKKSIncomingQueueEntry was created: %@", iqe); } // A remote change has occured for this record. Delete any pending local changes; they will be overwritten. - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase:ckme.uuid state: SecCKKSStateNew zoneID:self.zoneID error: &error]; + NSArray* siblings = [CKKSOutgoingQueueEntry allWithUUID:iqe.uuid + states:@[SecCKKSStateNew, + SecCKKSStateReencrypt, + SecCKKSStateError] + zoneID:self.zoneID + error:&error]; if(error) { - ckkserror("ckks", self, "Couldn't load OutgoingQueueEntry: %@", error); - } - if(oqe) { - [self _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&error]; + ckkserror("ckks", self, "Couldn't load OQE sibling for %@: %@", iqe.uuid, error); } - // Reencryptions are pending changes too - oqe = [CKKSOutgoingQueueEntry tryFromDatabase:ckme.uuid state: SecCKKSStateReencrypt zoneID:self.zoneID error: &error]; - if(error) { - ckkserror("ckks", self, "Couldn't load reencrypted OutgoingQueueEntry: %@", error); - } - if(oqe) { - [oqe deleteFromDatabase:&error]; - if(error) { - ckkserror("ckks", self, "Couldn't delete reencrypted oqe(%@): %@", oqe, error); + for(CKKSOutgoingQueueEntry* oqe in siblings) { + NSError* deletionError = nil; + [oqe deleteFromDatabase:&deletionError]; + if(deletionError) { + ckkserror("ckks", self, "Couldn't delete OQE sibling(%@) for %@: %@", oqe, iqe.uuid, deletionError); } } } @@ -3170,7 +2358,7 @@ } // We've saved a new key in the database; trigger a rekey operation. - [self _onqueueKeyStateMachineRequestProcess]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; } - (void)_onqueueCKRecordTLKShareChanged:(CKRecord*)record resync:(bool)resync { @@ -3188,7 +2376,7 @@ ckkserror("ckksshare", self, "Couldn't save new TLK share to database: %@ %@", share, error); } - [self _onqueueKeyStateMachineRequestProcess]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; } - (void)_onqueueCKRecordCurrentKeyPointerChanged:(CKRecord*)record resync:(bool)resync { @@ -3224,7 +2412,7 @@ ckksnotice("ckkskey", self, "Current key pointer modification doesn't change anything interesting; skipping reprocess: %@", record); } else { // We've saved a new key in the database; trigger a rekey operation. - [self _onqueueKeyStateMachineRequestProcess]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested]; } } @@ -3260,6 +2448,7 @@ - (void)_onqueueCKRecordManifestChanged:(CKRecord*)record resync:(bool)resync { + dispatch_assert_queue(self.queue); NSError* error = nil; CKKSPendingManifest* manifest = [[CKKSPendingManifest alloc] initWithCKRecord:record]; [manifest saveToDatabase:&error]; @@ -3271,6 +2460,7 @@ - (void)_onqueueCKRecordManifestLeafChanged:(CKRecord*)record resync:(bool)resync { + dispatch_assert_queue(self.queue); NSError* error = nil; CKKSManifestLeafRecord* manifestLeaf = [[CKKSManifestPendingLeafRecord alloc] initWithCKRecord:record]; [manifestLeaf saveToDatabase:&error]; @@ -3281,6 +2471,7 @@ } - (void)_onqueueCKRecordDeviceStateChanged:(CKRecord*)record resync:(bool)resync { + dispatch_assert_queue(self.queue); if(resync) { NSError* dserror = nil; CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry tryFromDatabase:record.recordID.recordName zoneID:self.zoneID error:&dserror]; @@ -3306,6 +2497,7 @@ } - (bool)_onqueueResetAllInflightOQE:(NSError**)error { + dispatch_assert_queue(self.queue); NSError* localError = nil; while(true) { @@ -3369,258 +2561,84 @@ if(newOQE) { ckksnotice("ckksoutgoing", self, "New modification has come in behind inflight %@; dropping failed change", oqe); - // recurse for that lovely code reuse - [self _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&localerror]; - if(localerror) { - ckkserror("ckksoutgoing", self, "Couldn't delete in-flight OQE: %@", localerror); - if(error) { - *error = localerror; - } - } - } else { - oqe.state = state; - [oqe saveToDatabase: &localerror]; - if(localerror) { - ckkserror("ckks", self, "Couldn't save %@ as %@: %@", oqe, state, localerror); - } - } - - } else { - oqe.state = state; - [oqe saveToDatabase: &localerror]; - if(localerror) { - ckkserror("ckks", self, "Couldn't save %@ as %@: %@", oqe, state, localerror); - } - } - - if(error && localerror) { - *error = localerror; - } - return localerror == nil; -} - -- (bool)_onqueueErrorOutgoingQueueEntry: (CKKSOutgoingQueueEntry*) oqe itemError: (NSError*) itemError error: (NSError* __autoreleasing*) error { - dispatch_assert_queue(self.queue); - - SecBoolNSErrorCallback callback = [[CKKSViewManager manager] claimCallbackForUUID:oqe.uuid]; - if(callback) { - callback(false, itemError); - } - NSError* localerror = nil; - - // Now, delete the OQE: it's never coming back - [oqe deleteFromDatabase:&localerror]; - if(localerror) { - ckkserror("ckks", self, "Couldn't delete %@ (due to error %@): %@", oqe, itemError, localerror); - } - - if(error && localerror) { - *error = localerror; - } - return localerror == nil; -} - -- (bool)_onqueueUpdateLatestManifestWithError:(NSError**)error -{ - dispatch_assert_queue(self.queue); - CKKSManifest* manifest = [CKKSManifest latestTrustedManifestForZone:self.zoneName error:error]; - if (manifest) { - self.latestManifest = manifest; - return true; - } - else { - return false; - } -} - -- (bool)_onqueueWithAccountKeysCheckTLK:(CKKSKey*)proposedTLK error:(NSError* __autoreleasing *)error { - dispatch_assert_queue(self.queue); - // First, if we have a local identity, check for any TLK shares - NSError* localerror = nil; - - if(![proposedTLK wrapsSelf]) { - localerror = [NSError errorWithDomain:CKKSErrorDomain code:CKKSKeyNotSelfWrapped description:[NSString stringWithFormat:@"Potential TLK %@ doesn't wrap itself: %@", proposedTLK, proposedTLK.parentKeyUUID] underlying:NULL]; - ckkserror("ckksshare", self, "%@", localerror); - if (error) { - *error = localerror; - } - } else { - bool tlkShares = [self _onqueueWithAccountKeysCheckTLKFromShares:proposedTLK error:&localerror]; - // We only want to error out if a positive error occurred. "No shares" is okay. - if(!tlkShares || localerror) { - bool noTrustedTLKShares = [localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSNoTrustedTLKShares; - bool noSelfPeer = [localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSNoEncryptionKey; - bool noTrust = [localerror.domain isEqualToString:CKKSErrorDomain] && localerror.code == CKKSLackingTrust; - - // If this error was something worse than 'couldn't unwrap for reasons including there not being data', report it - if(!(noTrustedTLKShares || noSelfPeer || noTrust)) { + // recurse for that lovely code reuse + [self _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&localerror]; + if(localerror) { + ckkserror("ckksoutgoing", self, "Couldn't delete in-flight OQE: %@", localerror); if(error) { *error = localerror; } - ckkserror("ckksshare", self, "Errored unwrapping TLK with TLKShares: %@", localerror); - return false; - } else { - ckkserror("ckksshare", self, "Non-fatal error unwrapping TLK with TLKShares: %@", localerror); + } + } else { + oqe.state = state; + [oqe saveToDatabase: &localerror]; + if(localerror) { + ckkserror("ckks", self, "Couldn't save %@ as %@: %@", oqe, state, localerror); } } - } - if([proposedTLK loadKeyMaterialFromKeychain:error]) { - // Hurray! - return true; } else { - return false; - } -} - -// This version only examines if this TLK is recoverable from TLK shares -- (bool)_onqueueWithAccountKeysCheckTLKFromShares:(CKKSKey*)proposedTLK error:(NSError* __autoreleasing *)error { - // But being recoverable from any trust set is okay - NSError* localerror = nil; - - if(self.currentTrustStates.count == 0u) { - if(error) { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSLackingTrust - description:@"No current trust states; can't check TLK"]; - } - return false; - } - - for(CKKSPeerProviderState* trustState in self.currentTrustStates) { - ckkserror("ckksshare", self, "Checking TLK from trust state %@", trustState); - bool recovered = [self _onqueueWithAccountKeysWithPeers:trustState - checkTLK:proposedTLK - error:&localerror]; - - if(recovered) { - ckkserror("ckksshare", self, "Recovered the TLK"); - return true; + oqe.state = state; + [oqe saveToDatabase: &localerror]; + if(localerror) { + ckkserror("ckks", self, "Couldn't save %@ as %@: %@", oqe, state, localerror); } - - ckkserror("ckksshare", self, "Unable to recover TLK from trust set: %@", localerror); } - // Only report the last error if(error && localerror) { *error = localerror; } - return false; + return localerror == nil; } -- (bool)_onqueueWithAccountKeysWithPeers:(CKKSPeerProviderState*)trustState - checkTLK:(CKKSKey*)proposedTLK - error:(NSError* __autoreleasing *)error -{ - NSError* localerror = NULL; - if(!trustState.currentSelfPeers.currentSelf || trustState.currentSelfPeersError) { - ckkserror("ckksshare", self, "Don't have self peers for %@: %@", trustState.peerProviderID, trustState.currentSelfPeersError); - if(error) { - if([self.lockStateTracker isLockedError:trustState.currentSelfPeersError]) { - // Locked error should propagate - *error = trustState.currentSelfPeersError; - } else { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoEncryptionKey - description:@"No current self peer" - underlying:trustState.currentSelfPeersError]; - } - } - return false; - } +- (bool)_onqueueErrorOutgoingQueueEntry: (CKKSOutgoingQueueEntry*) oqe itemError: (NSError*) itemError error: (NSError* __autoreleasing*) error { + dispatch_assert_queue(self.queue); - if(!trustState.currentTrustedPeers || trustState.currentTrustedPeersError) { - ckkserror("ckksshare", self, "Don't have trusted peers: %@", trustState.currentTrustedPeersError); - if(error) { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoPeersAvailable - description:@"No trusted peers" - underlying:trustState.currentTrustedPeersError]; - } - return false; + SecBoolNSErrorCallback callback = [[CKKSViewManager manager] claimCallbackForUUID:oqe.uuid]; + if(callback) { + callback(false, itemError); } + NSError* localerror = nil; - NSError* lastShareError = nil; - - for(id selfPeer in trustState.currentSelfPeers.allSelves) { - NSArray* possibleShares = [CKKSTLKShareRecord allFor:selfPeer.peerID - keyUUID:proposedTLK.uuid - zoneID:self.zoneID - error:&localerror]; - if(localerror) { - ckkserror("ckksshare", self, "Error fetching CKKSTLKShares for %@: %@", selfPeer, localerror); - } - - if(possibleShares.count == 0) { - ckksnotice("ckksshare", self, "No CKKSTLKShares to %@ for %@", selfPeer, proposedTLK); - continue; - } - - for(CKKSTLKShareRecord* possibleShare in possibleShares) { - NSError* possibleShareError = nil; - ckksnotice("ckksshare", self, "Checking possible TLK share %@ as %@", possibleShare, selfPeer); - - CKKSKey* possibleKey = [possibleShare recoverTLK:selfPeer - trustedPeers:trustState.currentTrustedPeers - error:&possibleShareError]; - - if(possibleShareError) { - ckkserror("ckksshare", self, "Unable to unwrap TLKShare(%@) as %@: %@", - possibleShare, selfPeer, possibleShareError); - ckkserror("ckksshare", self, "Current trust set: %@", trustState.currentTrustedPeers); - lastShareError = possibleShareError; - continue; - } - - bool result = [proposedTLK trySelfWrappedKeyCandidate:possibleKey.aessivkey error:&possibleShareError]; - if(possibleShareError) { - ckkserror("ckksshare", self, "Unwrapped TLKShare(%@) does not unwrap proposed TLK(%@) as %@: %@", - possibleShare, proposedTLK, trustState.currentSelfPeers.currentSelf, possibleShareError); - lastShareError = possibleShareError; - continue; - } - - if(result) { - ckksnotice("ckksshare", self, "TLKShare(%@) unlocked TLK(%@) as %@", - possibleShare, proposedTLK, selfPeer); - - // The proposed TLK is trusted key material. Persist it as a "trusted" key. - [proposedTLK saveKeyMaterialToKeychain:true error:&possibleShareError]; - if(possibleShareError) { - ckkserror("ckksshare", self, "Couldn't store the new TLK(%@) to the keychain: %@", proposedTLK, possibleShareError); - if(error) { - *error = possibleShareError; - } - return false; - } - - return true; - } - } + // Now, delete the OQE: it's never coming back + [oqe deleteFromDatabase:&localerror]; + if(localerror) { + ckkserror("ckks", self, "Couldn't delete %@ (due to error %@): %@", oqe, itemError, localerror); } - if(error) { - *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoTrustedTLKShares - description:[NSString stringWithFormat:@"No trusted TLKShares for %@", proposedTLK] - underlying:lastShareError]; + if(error && localerror) { + *error = localerror; } - return false; + return localerror == nil; } -- (bool)dispatchSyncWithConnection:(SecDbConnectionRef _Nonnull)dbconn block:(bool (^)(void))block { +- (bool)dispatchSyncWithConnection:(SecDbConnectionRef _Nonnull)dbconn + readWriteTxion:(BOOL)readWriteTxion + block:(CKKSDatabaseTransactionResult (^)(void))block +{ CFErrorRef cferror = NULL; // Take the DB transaction, then get on the local queue. // In the case of exclusive DB transactions, we don't really _need_ the local queue, but, it's here for future use. - bool ret = kc_transaction_type(dbconn, kSecDbExclusiveRemoteCKKSTransactionType, &cferror, ^bool{ - __block bool ok = false; + + SecDbTransactionType txtionType = readWriteTxion ? kSecDbExclusiveRemoteCKKSTransactionType : kSecDbNormalTransactionType; + bool ret = kc_transaction_type(dbconn, txtionType, &cferror, ^bool{ + __block CKKSDatabaseTransactionResult result = CKKSDatabaseTransactionRollback; + + CKKSSQLInTransaction = true; + if(readWriteTxion) { + CKKSSQLInWriteTransaction = true; + } dispatch_sync(self.queue, ^{ - ok = block(); + result = block(); }); - return ok; + if(readWriteTxion) { + CKKSSQLInWriteTransaction = false; + } + CKKSSQLInTransaction = false; + return result == CKKSDatabaseTransactionCommit; }); if(cferror) { @@ -3629,7 +2647,8 @@ return ret; } -- (void)dispatchSync: (bool (^)(void)) block { +- (void)dispatchSyncWithSQLTransaction:(CKKSDatabaseTransactionResult (^)(void))block +{ // important enough to block this thread. Must get a connection first, though! // Please don't jetsam us... @@ -3637,7 +2656,48 @@ CFErrorRef cferror = NULL; kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { - return [self dispatchSyncWithConnection:dbt block:block]; + return [self dispatchSyncWithConnection:dbt + readWriteTxion:YES + block:block]; + + }); + if(cferror) { + ckkserror("ckks", self, "error getting database connection, major problems ahead: %@", cferror); + } + + (void)transaction; +} + +- (void)dispatchSyncWithReadOnlySQLTransaction:(void (^)(void))block +{ + // Please don't jetsam us... + os_transaction_t transaction = os_transaction_create([[NSString stringWithFormat:@"com.apple.securityd.ckks.%@", self.zoneName] UTF8String]); + + CFErrorRef cferror = NULL; + + // Note: we are lying to kc_with_dbt here about whether we're read-and-write or read-only. + // This is because the SOS engine's queue are broken: SOSEngineSetNotifyPhaseBlock attempts + // to take the SOS engine's queue while a SecDb transaction is still ongoing. But, in + // SOSEngineCopyPeerConfirmedDigests, SOS takes the engine queue, then calls dsCopyManifestWithViewNameSet() + // which attempts to get a read-only SecDb connection. + // + // The issue manifests when many CKKS read-only transactions are in-flight, and starve out + // the pool of read-only connections. Then, a deadlock forms. + // + // By claiming to be a read-write connection here, we'll contend on the pool of writer threads, + // and shouldn't starve SOS of its read thread. + // + // But, since we pass NO to readWriteTxion, the SQLite transaction will be of type + // kSecDbNormalTransactionType, which won't block other readers. + + kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { + return [self dispatchSyncWithConnection:dbt + readWriteTxion:NO + block:^CKKSDatabaseTransactionResult { + block(); + return CKKSDatabaseTransactionCommit; + }]; + }); if(cferror) { ckkserror("ckks", self, "error getting database connection, major problems ahead: %@", cferror); @@ -3646,121 +2706,139 @@ (void)transaction; } -- (void)dispatchSyncWithAccountKeys:(bool (^)(void))block +- (BOOL)insideSQLTransaction +{ + return CKKSSQLInTransaction; +} + +#pragma mark - CKKSZone operations + +- (void)beginCloudKitOperation { - [self dispatchSyncWithPeerProviders:self.currentPeerProviders override:false block:block]; + [self.accountTracker registerForNotificationsOfCloudKitAccountStatusChange:self]; } -- (void)dispatchSyncWithPeerProviders:(NSArray>*)peerProviders - override:(bool)overridePeerProviders - block:(bool (^)(void))block +- (CKKSResultOperation*)createAccountLoggedInDependency:(NSString*)message { - NSArray>* actualPeerProviders = overridePeerProviders ? peerProviders : self.currentPeerProviders; - NSMutableArray* trustStates = [NSMutableArray array]; + WEAKIFY(self); + CKKSResultOperation* accountLoggedInDependency = [CKKSResultOperation named:@"account-logged-in-dependency" withBlock:^{ + STRONGIFY(self); + ckksnotice("ckkszone", self, "%@", message); + }]; + accountLoggedInDependency.descriptionErrorCode = CKKSResultDescriptionPendingAccountLoggedIn; + return accountLoggedInDependency; +} + +#pragma mark - CKKSZoneUpdateReceiverProtocol - for(id provider in actualPeerProviders) { - ckksnotice("ckks", self, "Fetching account keys for provider %@", provider); - [trustStates addObject:provider.currentState]; +- (CKKSAccountStatus)accountStatusFromCKAccountInfo:(CKAccountInfo*)info +{ + if(!info) { + return CKKSAccountStatusUnknown; + } + if(info.accountStatus == CKAccountStatusAvailable && + info.hasValidCredentials) { + return CKKSAccountStatusAvailable; + } else { + return CKKSAccountStatusNoAccount; } +} - [self dispatchSync:^bool{ - if(overridePeerProviders) { - self.currentPeerProviders = peerProviders; - } - self.currentTrustStates = trustStates; +- (void)cloudkitAccountStateChange:(CKAccountInfo* _Nullable)oldAccountInfo to:(CKAccountInfo*)currentAccountInfo +{ + ckksnotice("ckkszone", self, "%@ Received notification of CloudKit account status change, moving from %@ to %@", + self.zoneID.zoneName, + oldAccountInfo, + currentAccountInfo); - bool result = block(); + // Filter for device2device encryption and cloudkit grey mode + CKKSAccountStatus oldStatus = [self accountStatusFromCKAccountInfo:oldAccountInfo]; + CKKSAccountStatus currentStatus = [self accountStatusFromCKAccountInfo:currentAccountInfo]; - // Forget the peers; they might have class A key material - NSMutableArray* noTrustStates = [NSMutableArray array]; - for(id provider in peerProviders) { - (void)provider; - [noTrustStates addObject:[CKKSPeerProviderState noPeersState:provider]]; + if(oldStatus == currentStatus) { + ckksnotice("ckkszone", self, "Computed status of new CK account info is same as old status: %@", [CKKSAccountStateTracker stringFromAccountStatus:currentStatus]); + return; + } + + switch(currentStatus) { + case CKKSAccountStatusAvailable: { + ckksnotice("ckkszone", self, "Logged into iCloud."); + [self handleCKLogin]; + + if(self.accountLoggedInDependency) { + [self.operationQueue addOperation:self.accountLoggedInDependency]; + self.accountLoggedInDependency = nil; + }; } - self.currentTrustStates = noTrustStates; + break; - return result; - }]; -} + case CKKSAccountStatusNoAccount: { + ckksnotice("ckkszone", self, "Logging out of iCloud. Shutting down."); + + if(!self.accountLoggedInDependency) { + self.accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in again."]; + } -#pragma mark - CKKSZoneUpdateReceiver + [self handleCKLogout]; + } + break; -- (void)notifyZoneChange: (CKRecordZoneNotification*) notification { - ckksnotice("ckks", self, "received a zone change notification for %@ %@", self, notification); + case CKKSAccountStatusUnknown: { + // We really don't expect to receive this as a notification, but, okay! + ckksnotice("ckkszone", self, "Account status has become undetermined. Pausing for %@", self.zoneID.zoneName); - [self fetchAndProcessCKChangesDueToAPNS:notification]; -} + if(!self.accountLoggedInDependency) { + self.accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in again."]; + } -- (void)superHandleCKLogin { - [super handleCKLogin]; + [self handleCKLogout]; + } + break; + } } -- (void)handleCKLogin { +- (void)handleCKLogin +{ ckksnotice("ckks", self, "received a notification of CK login"); if(!SecCKKSIsEnabled()) { ckksnotice("ckks", self, "Skipping CloudKit initialization due to disabled CKKS"); return; } - WEAKIFY(self); - CKKSResultOperation* login = [CKKSResultOperation named:@"ckks-login" withBlock:^{ - STRONGIFY(self); - - [self dispatchSyncWithAccountKeys:^bool{ - [self superHandleCKLogin]; - - // Reset key hierarchy state machine to initializing - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateInitializing withError:nil]; - return true; - }]; + dispatch_sync(self.queue, ^{ + ckksinfo("ckkszone", self, "received a notification of CK login"); // Change our condition variables to reflect that we think we're logged in + self.accountStatus = CKKSAccountStatusAvailable; self.loggedOut = [[CKKSCondition alloc] initToChain:self.loggedOut]; [self.loggedIn fulfill]; - [self.accountStateKnown fulfill]; - }]; + }); - [self scheduleAccountStatusOperation:login]; -} + [self.stateMachine handleFlag:CKKSFlagCloudKitLoggedIn]; -- (void)superHandleCKLogout { - [super handleCKLogout]; + [self.accountStateKnown fulfill]; } -- (void)handleCKLogout { - WEAKIFY(self); - CKKSResultOperation* logout = [CKKSResultOperation named:@"ckks-logout" withBlock: ^{ - STRONGIFY(self); - if(!self) { - return; - } - [self dispatchSync:^bool { - ckksnotice("ckks", self, "received a notification of CK logout"); - [self superHandleCKLogout]; - - NSError* error = nil; - [self _onqueueResetLocalData: &error]; - if(error) { - ckkserror("ckks", self, "error while resetting local data: %@", error); - } - - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateLoggedOut withError:nil]; +- (void)handleCKLogout +{ + dispatch_sync(self.queue, ^{ + ckksinfo("ckkszone", self, "received a notification of CK logout"); - self.loggedIn = [[CKKSCondition alloc] initToChain: self.loggedIn]; - [self.loggedOut fulfill]; - [self.accountStateKnown fulfill]; + self.accountStatus = CKKSAccountStatusNoAccount; + self.loggedIn = [[CKKSCondition alloc] initToChain:self.loggedIn]; + [self.loggedOut fulfill]; + }); - return true; - }]; - }]; + [self.stateMachine handleFlag:CKKSFlagCloudKitLoggedOut]; - [self scheduleAccountStatusOperation: logout]; + [self.accountStateKnown fulfill]; } #pragma mark - Trust operations - (void)beginTrustedOperation:(NSArray>*)peerProviders suggestTLKUpload:(CKKSNearFutureScheduler*)suggestTLKUpload + requestPolicyCheck:(CKKSNearFutureScheduler*)requestPolicyCheck { for(id peerProvider in peerProviders) { [peerProvider registerForPeerChangeUpdates:self]; @@ -3768,52 +2846,75 @@ [self.launch addEvent:@"beginTrusted"]; - [self dispatchSyncWithPeerProviders:peerProviders override:true block:^bool { + dispatch_sync(self.queue, ^{ ckksnotice("ckkstrust", self, "Beginning trusted operation"); + self.operationDependencies.peerProviders = peerProviders; + CKKSAccountStatus oldTrustStatus = self.trustStatus; self.suggestTLKUpload = suggestTLKUpload; + self.requestPolicyCheck = requestPolicyCheck; self.trustStatus = CKKSAccountStatusAvailable; - if(self.trustDependency) { - [self scheduleOperation: self.trustDependency]; - self.trustDependency = nil; - } - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagBeginTrustedOperation]; if(oldTrustStatus == CKKSAccountStatusNoAccount) { ckksnotice("ckkstrust", self, "Moving from an untrusted status; we need to process incoming queue and scan for any new items"); - // Next, try to process them (replacing local entries) - CKKSIncomingQueueOperation* initialProcess = [self processIncomingQueue:true after:nil]; - initialProcess.name = @"initial-process-incoming-queue"; - - // If all that succeeds, iterate through all keychain items and find the ones which need to be uploaded - self.initialScanOperation = [self scanLocalItems:@"newly-trusted-scan" - ckoperationGroup:nil - after:initialProcess]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagProcessIncomingQueue]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagScanLocalItems]; } - - return true; - }]; + }); } - (void)endTrustedOperation { [self.launch addEvent:@"endTrusted"]; - [self dispatchSyncWithPeerProviders:nil override:true block:^bool { + dispatch_sync(self.queue, ^{ ckksnotice("ckkstrust", self, "Ending trusted operation"); + self.operationDependencies.peerProviders = @[]; + self.suggestTLKUpload = nil; self.trustStatus = CKKSAccountStatusNoAccount; - if(!self.trustDependency) { - self.trustDependency = [CKKSResultOperation named:@"wait-for-trust" withBlock:^{}]; + [self.stateMachine _onqueueHandleFlag:CKKSFlagEndTrustedOperation]; + }); +} + +- (BOOL)itemSyncingEnabled +{ + if(!self.operationDependencies.syncingPolicy) { + ckksnotice("ckks", self, "No syncing policy loaded; item syncing is disabled"); + return NO; + } else { + return [self.operationDependencies.syncingPolicy isSyncingEnabledForView:self.zoneName]; + } +} + +- (void)setCurrentSyncingPolicy:(TPSyncingPolicy*)syncingPolicy policyIsFresh:(BOOL)policyIsFresh +{ + dispatch_sync(self.queue, ^{ + BOOL oldEnabled = [self itemSyncingEnabled]; + + self.operationDependencies.syncingPolicy = syncingPolicy; + + BOOL enabled = [self itemSyncingEnabled]; + if(enabled != oldEnabled) { + ckksnotice("ckks", self, "Syncing for this view is now %@ (policy: %@)", enabled ? @"enabled" : @"paused", self.operationDependencies.syncingPolicy); } - [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; - }]; + + if(enabled) { + CKKSResultOperation* incomingOp = [self processIncomingQueue:false after:nil policyConsideredAuthoritative:policyIsFresh]; + [self processOutgoingQueueAfter:incomingOp ckoperationGroup:nil]; + } + }); +} + +- (void)receivedItemForWrongView +{ + [self.requestPolicyCheck trigger]; } #pragma mark - CKKSChangeFetcherClient @@ -3822,9 +2923,8 @@ { __block BOOL ready = NO; - [self dispatchSync: ^bool { + [self dispatchSyncWithReadOnlySQLTransaction:^{ ready = (bool)[self _onQueueZoneIsReadyForFetching]; - return ready; }]; return ready; @@ -3832,12 +2932,15 @@ - (BOOL)_onQueueZoneIsReadyForFetching { + dispatch_assert_queue(self.queue); if(self.accountStatus != CKKSAccountStatusAvailable) { ckksnotice("ckksfetch", self, "Not participating in fetch: not logged in"); return NO; } - if(!self.zoneCreated) { + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.operationDependencies.zoneID.zoneName]; + + if(!ckse.ckzonecreated) { ckksnotice("ckksfetch", self, "Not participating in fetch: zone not created yet"); return NO; } @@ -3848,10 +2951,10 @@ { __block CKKSCloudKitFetchRequest* request = [[CKKSCloudKitFetchRequest alloc] init]; - [self dispatchSync: ^bool { + [self dispatchSyncWithReadOnlySQLTransaction:^{ if (![self _onQueueZoneIsReadyForFetching]) { ckksnotice("ckksfetch", self, "skipping fetch since zones are not ready"); - return false; + return; } request.participateInFetch = true; @@ -3866,11 +2969,10 @@ CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.zoneName]; if(!ckse) { ckkserror("ckksfetch", self, "couldn't fetch zone change token for %@", self.zoneName); - return false; + return; } request.changeToken = ckse.changeToken; } - return true; }]; if (request.changeToken == nil) { @@ -3890,8 +2992,8 @@ if(changedRecords.count == 0 && deletedRecords.count == 0 && !moreComing && !resync) { // Early-exit, so we don't pick up the account keys or kick off an IncomingQueue operation for no changes - [self dispatchSync:^bool { - ckkserror("ckksfetch", self, "No record changes in this fetch"); + [self dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + ckksinfo("ckksfetch", self, "No record changes in this fetch"); NSError* error = nil; CKKSZoneStateEntry* state = [CKKSZoneStateEntry state:self.zoneName]; @@ -3902,12 +3004,12 @@ if(error) { ckkserror("ckksfetch", self, "Couldn't save new server change token: %@", error); } - return true; + return CKKSDatabaseTransactionCommit; }]; return; } - [self dispatchSyncWithAccountKeys:^bool{ + [self dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for (CKRecord* record in changedRecords) { [self _onqueueCKRecordChanged:record resync:resync]; } @@ -3982,7 +3084,7 @@ ckksnotice("ckksfetch", self, "Finished processing changes for %@", self.zoneID); - return true; + return CKKSDatabaseTransactionCommit; }]; } @@ -4007,30 +3109,7 @@ if(isChangeTokenExpiredError) { ckkserror("ckks", self, "Received notice that our change token is out of date (for %@). Resetting local data...", self.zoneID); - // This is a bit scary: we might confuse some poor key hierarchy state machine operation. But, if a key state machine - // operation is waiting for a successful fetch, we need to do this reset - [self dispatchSyncWithAccountKeys:^bool{ - NSError* error = nil; - [self _onqueueResetLocalData:&error]; - - // We need to rescan the local keychain once we return to a good state - self.droppedItems = true; - - if(error) { - ckksnotice("ckksreset", self, "CloudKit-inspired local reset of %@ ended with error: %@", self.zoneID, error); - } else { - ckksnotice("ckksreset", self, "CloudKit-inspired local reset of %@ ended successfully", self.zoneID); - } - - // If we're in the middle of a fetch for the key state, then the retried fetch (which should succeed) will be sufficient to progress - // Otherwise, we need to poke the key hierarchy state machine: all of its data is gone - if(![self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateFetch]) { - [self _onqueueKeyStateMachineRequestFetch]; - } - - return true; - }]; - + [self.stateMachine handleFlag:CKKSFlagChangeTokenExpired]; return true; } @@ -4038,23 +3117,7 @@ if(isDeletedZoneError) { ckkserror("ckks", self, "Received notice that our zone(%@) does not exist. Resetting local data.", self.zoneID); - /* - * If someone delete our zone, lets just start over from the begining - */ - [self dispatchSync: ^bool{ - NSError* resetError = nil; - - [self _onqueueResetLocalData: &resetError]; - if(resetError) { - ckksnotice("ckksreset", self, "CloudKit-inspired local reset of %@ ended with error: %@", self.zoneID, resetError); - } else { - ckksnotice("ckksreset", self, "CloudKit-inspired local reset of %@ ended successfully", self.zoneID); - } - - [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateInitializing withError:nil]; - return true; - }]; - + [self.stateMachine handleFlag:CKKSFlagCloudKitZoneMissing]; return false; } @@ -4081,27 +3144,25 @@ // The key state machine should handle that, so poke it. ckkserror("ckks", self, "Received update that the trust set has changed"); - self.trustedPeersSetChanged = true; - [self.pokeKeyStateMachineScheduler trigger]; + [self.stateMachine handleFlag:CKKSFlagTrustedPeersSetChanged]; } #pragma mark - Test Support - (bool) outgoingQueueEmpty: (NSError * __autoreleasing *) error { __block bool ret = false; - [self dispatchSync: ^bool{ + [self dispatchSyncWithReadOnlySQLTransaction:^{ NSArray* queueEntries = [CKKSOutgoingQueueEntry all: error]; ret = queueEntries && ([queueEntries count] == 0); - return true; }]; return ret; } -- (CKKSResultOperation*)waitForFetchAndIncomingQueueProcessing { - CKKSResultOperation* op = [self fetchAndProcessCKChanges:CKKSFetchBecauseTesting]; - [op waitUntilFinished]; - return op; +- (void)waitForFetchAndIncomingQueueProcessing +{ + [[self.zoneChangeFetcher inflightFetch] waitUntilFinished]; + [self waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; } - (void)waitForKeyHierarchyReadiness { @@ -4110,6 +3171,46 @@ } } +#pragma mark - NSOperation assistance + +- (void)scheduleOperation:(NSOperation*)op +{ + if(self.halted) { + ckkserror("ckkszone", self, "attempted to schedule an operation on a halted zone, ignoring"); + return; + } + + [op addNullableDependency:self.accountLoggedInDependency]; + [self.operationQueue addOperation: op]; +} + +// to be used rarely, if at all +- (bool)scheduleOperationWithoutDependencies:(NSOperation*)op +{ + if(self.halted) { + ckkserror("ckkszone", self, "attempted to schedule an non-dependent operation on a halted zone, ignoring"); + return false; + } + + [self.operationQueue addOperation: op]; + return true; +} + +- (void)waitUntilAllOperationsAreFinished +{ + [self.operationQueue waitUntilAllOperationsAreFinished]; +} + +- (void)waitForOperationsOfClass:(Class)operationClass +{ + NSArray* operations = [self.operationQueue.operations copy]; + for(NSOperation* op in operations) { + if([op isKindOfClass:operationClass]) { + [op waitUntilFinished]; + } + } +} + - (void)cancelPendingOperations { @synchronized(self.outgoingQueueOperations) { for(NSOperation* op in self.outgoingQueueOperations) { @@ -4131,29 +3232,34 @@ } [self.scanLocalItemsOperations removeAllObjects]; } - - [super cancelAllOperations]; } - (void)cancelAllOperations { - [self.zoneSetupOperation cancel]; - [self.keyStateMachineOperation cancel]; [self.keyStateReadyDependency cancel]; - [self.keyStateNonTransientDependency cancel]; [self.zoneChangeFetcher cancel]; [self.notifyViewChangedScheduler cancel]; - [self.pokeKeyStateMachineScheduler cancel]; [self cancelPendingOperations]; - - [self dispatchSync:^bool{ - [self _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateCancelled withError: nil]; - return true; - }]; + [self.operationQueue cancelAllOperations]; } - (void)halt { - [super halt]; + [self.stateMachine haltOperation]; + + // Synchronously set the 'halted' bit + dispatch_sync(self.queue, ^{ + self.halted = true; + }); + + // Bring all operations down, too + [self cancelAllOperations]; + + // And now, wait for all operations that are running + for(NSOperation* op in self.operationQueue.operations) { + if(op.isExecuting) { + [op waitUntilFinished]; + } + } // Don't send any more notifications, either _notifierClass = nil; @@ -4164,20 +3270,15 @@ #define boolstr(obj) (!!(obj) ? @"yes" : @"no") __block NSMutableDictionary* ret = nil; __block NSError* error = nil; - CKKSManifest* manifest = nil; ret = [[self fastStatus] mutableCopy]; - manifest = [CKKSManifest latestTrustedManifestForZone:self.zoneName error:&error]; - [self dispatchSync: ^bool { - + [self dispatchSyncWithReadOnlySQLTransaction:^{ CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID]; if(keyset.error) { error = keyset.error; } - NSString* manifestGeneration = manifest ? [NSString stringWithFormat:@"%lu", (unsigned long)manifest.generationCount] : nil; - if(error) { ckkserror("ckks", self, "error during status: %@", error); } @@ -4211,9 +3312,8 @@ @"currentTLKPtr": CKKSNilToNSNull(keyset.currentTLKPointer.currentKeyUUID), @"currentClassAPtr": CKKSNilToNSNull(keyset.currentClassAPointer.currentKeyUUID), @"currentClassCPtr": CKKSNilToNSNull(keyset.currentClassCPointer.currentKeyUUID), - @"currentManifestGen": CKKSNilToNSNull(manifestGeneration), + @"itemsyncing": self.itemSyncingEnabled ? @"enabled" : @"paused", }]; - return false; }]; return ret; } @@ -4222,7 +3322,8 @@ __block NSDictionary* ret = nil; - [self dispatchSync: ^bool { + [self dispatchSyncWithReadOnlySQLTransaction:^{ + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.zoneName]; ret = @{ @"view": CKKSNilToNSNull(self.zoneName), @@ -4232,25 +3333,18 @@ self.accountStatus == CKAccountStatusNoAccount ? @"logged out" : @"unknown", @"accounttracker": stringify(self.accountTracker), @"fetcher": stringify(self.zoneChangeFetcher), - @"zoneCreated": boolstr(self.zoneCreated), - @"zoneCreatedError": stringify(self.zoneCreatedError), - @"zoneSubscribed": boolstr(self.zoneSubscribed), - @"zoneSubscribedError": stringify(self.zoneSubscribedError), + @"zoneCreated": boolstr(ckse.ckzonecreated), + @"zoneSubscribed": boolstr(ckse.ckzonesubscribed), @"keystate": CKKSNilToNSNull(self.keyHierarchyState), - @"keyStateError": stringify(self.keyHierarchyError), @"statusError": [NSNull null], @"launchSequence": CKKSNilToNSNull([self.launch eventsByTime]), - @"zoneSetupOperation": stringify(self.zoneSetupOperation), - @"keyStateOperation": stringify(self.keyStateMachineOperation), @"lastIncomingQueueOperation": stringify(self.lastIncomingQueueOperation), @"lastNewTLKOperation": stringify(self.lastNewTLKOperation), @"lastOutgoingQueueOperation": stringify(self.lastOutgoingQueueOperation), @"lastProcessReceivedKeysOperation": stringify(self.lastProcessReceivedKeysOperation), @"lastReencryptOutgoingItemsOperation":stringify(self.lastReencryptOutgoingItemsOperation), - @"lastScanLocalItemsOperation": stringify(self.lastScanLocalItemsOperation), }; - return false; }]; return ret; diff --git a/keychain/ckks/CKKSLocalResetOperation.h b/keychain/ckks/CKKSLocalResetOperation.h new file mode 100644 index 00000000..def140d4 --- /dev/null +++ b/keychain/ckks/CKKSLocalResetOperation.h @@ -0,0 +1,26 @@ + +#import + +#if OCTAGON + +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSOperationDependencies.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CKKSLocalResetOperation : CKKSResultOperation +@property CKKSOperationDependencies* deps; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +// Used to run a local reset without scheduling its surrounding operation. +// Please be on a SQL transaction when you run this. +- (void)onqueuePerformLocalReset; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSLocalResetOperation.m b/keychain/ckks/CKKSLocalResetOperation.m new file mode 100644 index 00000000..abb1c8f1 --- /dev/null +++ b/keychain/ckks/CKKSLocalResetOperation.m @@ -0,0 +1,120 @@ + +#if OCTAGON + +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKSLocalResetOperation.h" +#import "keychain/ckks/CKKSZoneStateEntry.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSCurrentItemPointer.h" +#import "keychain/ckks/CKKSMirrorEntry.h" +#import "keychain/ot/OTDefines.h" + +@implementation CKKSLocalResetOperation + +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if(self = [super init]) { + _deps = dependencies; + + _intendedState = intendedState; + _nextState = errorState; + + self.name = @"ckks-local-reset"; + } + return self; +} + +- (void)main { + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult { + [self onqueuePerformLocalReset]; + return CKKSDatabaseTransactionCommit; + }]; +} + +- (void)onqueuePerformLocalReset +{ + NSError* localerror = nil; + + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName]; + ckse.ckzonecreated = false; + ckse.ckzonesubscribed = false; // I'm actually not sure about this: can you be subscribed to a non-existent zone? + ckse.changeToken = NULL; + [ckse saveToDatabase:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", self.deps.zoneID, "couldn't reset zone status: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSMirrorEntry deleteAll:self.deps.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSMirrorEntry: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSOutgoingQueueEntry deleteAll:self.deps.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSOutgoingQueueEntry: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSIncomingQueueEntry deleteAll:self.deps.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSIncomingQueueEntry: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSKey deleteAll:self.deps.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSKey: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSTLKShareRecord deleteAll:self.deps.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSTLKShare: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSCurrentKeyPointer deleteAll:self.deps.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSCurrentKeyPointer: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSCurrentItemPointer deleteAll:self.deps.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSCurrentItemPointer: %@", localerror); + self.error = localerror; + localerror = nil; + } + + [CKKSDeviceStateEntry deleteAll:self.deps.zoneID error:&localerror]; + if(localerror && self.error == nil) { + ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSDeviceStateEntry: %@", localerror); + self.error = localerror; + localerror = nil; + } + + if(!self.error) { + ckksnotice("local-reset", self.deps.zoneID, "Successfully deleted all local data"); + self.nextState = self.intendedState; + } +} + +@end + +#endif // OCTAGON + diff --git a/keychain/ckks/CKKSLocalSynchronizeOperation.m b/keychain/ckks/CKKSLocalSynchronizeOperation.m index fe5c09d0..585edc15 100644 --- a/keychain/ckks/CKKSLocalSynchronizeOperation.m +++ b/keychain/ckks/CKKSLocalSynchronizeOperation.m @@ -74,10 +74,10 @@ CKKSKeychainView* ckks = self.ckks; // Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety. - [ckks dispatchSync: ^bool{ + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { ckksnotice("ckksresync", ckks, "CKKSSynchronizeOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } //ckks.lastLocalSynchronizeOperation = self; @@ -94,7 +94,13 @@ [self dependOnBeforeGroupFinished:outgoingOp]; // Step 2 - CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:ckks errorOnClassAFailure:true]; + CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithDependencies:ckks.operationDependencies + ckks:ckks + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateUnhealthy + errorOnClassAFailure:true + handleMismatchedViewItems:false]; + incomingOp.name = [NSString stringWithFormat: @"resync-step%u-incoming", self.restartCount * steps + 2]; [incomingOp addSuccessDependency:outgoingOp]; [self runBeforeGroupFinished:incomingOp]; @@ -105,13 +111,23 @@ [self runBeforeGroupFinished:reloadOp]; // Step 4 - CKKSIncomingQueueOperation* incomingResyncOp = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:ckks errorOnClassAFailure:true]; + CKKSIncomingQueueOperation* incomingResyncOp = [[CKKSIncomingQueueOperation alloc] initWithDependencies:ckks.operationDependencies + ckks:ckks + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateUnhealthy + errorOnClassAFailure:true + handleMismatchedViewItems:false]; + incomingResyncOp.name = [NSString stringWithFormat: @"resync-step%u-incoming-again", self.restartCount * steps + 4]; [incomingResyncOp addSuccessDependency: reloadOp]; [self runBeforeGroupFinished:incomingResyncOp]; // Step 5 - CKKSScanLocalItemsOperation* scan = [[CKKSScanLocalItemsOperation alloc] initWithCKKSKeychainView:ckks ckoperationGroup:operationGroup]; + CKKSScanLocalItemsOperation* scan = [[CKKSScanLocalItemsOperation alloc] initWithDependencies:ckks.operationDependencies + ckks:ckks + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateError + ckoperationGroup:operationGroup]; scan.name = [NSString stringWithFormat: @"resync-step%u-scan", self.restartCount * steps + 5]; [scan addSuccessDependency: incomingResyncOp]; [self runBeforeGroupFinished: scan]; @@ -122,7 +138,7 @@ [restart addExecutionBlock:^{ STRONGIFY(self); if(!self) { - secerror("ckksresync: received callback for released object"); + ckkserror("ckksresync", ckks, "received callback for released object"); return; } @@ -151,7 +167,7 @@ [restart addSuccessDependency: scan]; [self runBeforeGroupFinished: restart]; - return true; + return CKKSDatabaseTransactionCommit; }]; } @@ -175,14 +191,14 @@ - (void)main { CKKSKeychainView* strongCKKS = self.ckks; - [strongCKKS dispatchSync: ^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; NSArray* mirrorItems = [CKKSMirrorEntry all:strongCKKS.zoneID error:&error]; if(error) { ckkserror("ckksresync", strongCKKS, "Couldn't fetch mirror items: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } // Reload all entries back into the local keychain @@ -198,7 +214,7 @@ [strongCKKS _onqueueCKRecordChanged:ckmeRecord resync:true]; } - return true; + return CKKSDatabaseTransactionCommit; }]; } @end diff --git a/keychain/ckks/CKKSLockStateTracker.m b/keychain/ckks/CKKSLockStateTracker.m index 46e6cb2a..774f0195 100644 --- a/keychain/ckks/CKKSLockStateTracker.m +++ b/keychain/ckks/CKKSLockStateTracker.m @@ -113,7 +113,7 @@ -(void)resetUnlockDependency { if(self.unlockDependency == nil || ![self.unlockDependency isPending]) { CKKSResultOperation* op = [CKKSResultOperation named:@"keybag-unlocked-dependency" withBlock: ^{ - secinfo("ckks", "Keybag unlocked"); + ckksinfo_global("ckks", "Keybag unlocked"); }]; op.descriptionErrorCode = CKKSResultDescriptionPendingUnlock; self.unlockDependency = op; @@ -125,7 +125,7 @@ bool locked = true; if(!SecAKSGetIsLocked(&locked, &aksError)) { - secerror("ckks: error querying lock state: %@", aksError); + ckkserror_global("ckks", "error querying lock state: %@", aksError); CFReleaseNull(aksError); } @@ -173,9 +173,28 @@ }); } --(bool)isLockedError:(NSError *)error { +- (bool)lockedError:(NSError *)error +{ bool isLockedError = error.code == errSecInteractionNotAllowed && ([error.domain isEqualToString:@"securityd"] || [error.domain isEqualToString:(__bridge NSString*)kSecErrorDomain]); + return isLockedError; +} + +- (bool)checkErrorChainForLockState:(NSError*)error +{ + while(error != nil) { + if([self lockedError:error]) { + return true; + } + + error = error.userInfo[NSUnderlyingErrorKey]; + } + + return false; +} + +-(bool)isLockedError:(NSError *)error { + bool isLockedError = [self checkErrorChainForLockState:error]; /* * If we are locked, and the the current lock state track disagree, lets double check diff --git a/keychain/ckks/CKKSLogging.m b/keychain/ckks/CKKSLogging.m new file mode 100644 index 00000000..4971f413 --- /dev/null +++ b/keychain/ckks/CKKSLogging.m @@ -0,0 +1,33 @@ + +#import +#import "keychain/ckks/CKKS.h" + +os_log_t CKKSLogObject(NSString* scope, NSString* _Nullable zoneName) +{ + __block os_log_t ret = OS_LOG_DISABLED; + + static dispatch_queue_t logQueue = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + logQueue = dispatch_queue_create("ckks-logger", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + }); + + static NSMutableDictionary* scopeMap = nil; + + dispatch_sync(logQueue, ^{ + if(scopeMap == nil) { + scopeMap = [NSMutableDictionary dictionary]; + } + + NSString* key = zoneName ? [scope stringByAppendingFormat:@"-%@", zoneName] : scope; + + ret = scopeMap[key]; + + if(!ret) { + ret = os_log_create("com.apple.security.ckks", [key cStringUsingEncoding:NSUTF8StringEncoding]); + scopeMap[key] = ret; + } + }); + + return ret; +} diff --git a/keychain/ckks/CKKSManifest.m b/keychain/ckks/CKKSManifest.m index 0d7f5562..4203dff7 100644 --- a/keychain/ckks/CKKSManifest.m +++ b/keychain/ckks/CKKSManifest.m @@ -286,7 +286,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) [[CKKSEgoManifest egoHelper] performWithSigningKey:^(SFECKeyPair* signingKey, NSError* error) { accountInfo.signingKey = signingKey; if(error) { - secerror("ckksmanifest: cannot get signing key from account: %@", error); + ckkserror_global("ckksmanifest", "cannot get signing key from account: %@", error); if(accountInfo.setupError == nil) { accountInfo.setupError = error; } @@ -297,7 +297,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) accountInfo.egoPeerID = egoPeerID; if(error) { - secerror("ckksmanifest: cannot get ego peer ID from account: %@", error); + ckkserror_global("ckksmanifest", "cannot get ego peer ID from account: %@", error); if(accountInfo.setupError == nil) { accountInfo.setupError = error; } @@ -307,7 +307,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) [[CKKSEgoManifest egoHelper] performWithPeerVerifyingKeys:^(NSDictionary* peerKeys, NSError* error) { accountInfo.peerVerifyingKeys = peerKeys; if(error) { - secerror("ckksmanifest: cannot get peer keys from account: %@", error); + ckkserror_global("ckksmanifest", "cannot get peer keys from account: %@", error); if(accountInfo.setupError == nil) { accountInfo.setupError = error; } @@ -471,11 +471,11 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) - (instancetype)initWithDigestValue:(NSData*)digestValue zone:(NSString*)zone generationCount:(NSUInteger)generationCount leafRecordIDs:(NSArray*)leafRecordIDs peerManifestIDs:(NSArray*)peerManifestIDs currentItems:(NSDictionary*)currentItems futureData:(NSDictionary*)futureData signatures:(NSDictionary*)signatures signerID:(NSString*)signerID schema:(NSDictionary*)schema helper:(CKKSManifestInjectionPointHelper*)helper { if ([zone containsString:manifestRecordNameDelimiter]) { - secerror("zone contains delimiter: %@", zone); + ckkserror_global("ckksmanifest", "zone contains delimiter: %@", zone); return nil; } if ([signerID containsString:manifestRecordNameDelimiter]) { - secerror("signerID contains delimiter: %@", signerID); + ckkserror_global("ckksmanifest", "signerID contains delimiter: %@", signerID); return nil; } @@ -687,7 +687,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) void (^addValueSafelyToDictionaryAndLogIfNil)(NSMutableDictionary*, NSString*, id) = ^(NSMutableDictionary* dictionary, NSString* key, id value) { if (!value) { value = [NSNull null]; - secerror("CKKSManifest: saving manifest to database but %@ is nil", key); + ckkserror_global("ckksmanifest", "saving manifest to database but %@ is nil", key); } dictionary[key] = value; @@ -728,7 +728,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) { NSArray* components = [recordName componentsSeparatedByString:manifestRecordNameDelimiter]; if (components.count < 4) { - secerror("CKKSManifest: could not parse components from record name: %@", recordName); + ckkserror_global("ckksmanifest", "could not parse components from record name: %@", recordName); } return @{ @"ckzone" : components[1], @@ -1145,7 +1145,7 @@ static NSUInteger LeafBucketIndexForUUID(NSString* uuid) if (leafRecord) { [leafRecords addObject:leafRecord]; } else { - secerror("ckksmanifest: error loading leaf record from database: %@", error ? *error : nil); + ckkserror_global("ckksmanifest", "error loading leaf record from database: %@", error ? *error : nil); return false; } } diff --git a/keychain/ckks/CKKSManifestLeafRecord.m b/keychain/ckks/CKKSManifestLeafRecord.m index a35b519b..debfd93c 100644 --- a/keychain/ckks/CKKSManifestLeafRecord.m +++ b/keychain/ckks/CKKSManifestLeafRecord.m @@ -137,7 +137,7 @@ static NSDictionary* RecordDigestDictFromDER(NSData* data, NSError** error) NSData* derData = [[NSData alloc] initWithBase64EncodedString:record[SecCKRecordManifestLeafDERKey] options:0]; NSDictionary* recordDigestDict = RecordDigestDictFromDER(derData, &error); if (!recordDigestDict) { - secerror("failed to decode manifest leaf node DER with error: %@", error); + ckkserror_global("ckksmanifest", "failed to decode manifest leaf node DER with error: %@", error); return nil; } @@ -148,7 +148,7 @@ static NSDictionary* RecordDigestDictFromDER(NSData* data, NSError** error) - (instancetype)initWithUUID:(NSString*)uuid digest:(NSData*)digest recordDigestDict:(NSDictionary*)recordDigestDict zone:(NSString*)zone { if ([uuid containsString:manifestLeafRecordNameDelimiter]) { - secerror("uuid contains delimiter: %@", uuid); + ckkserror_global("ckksmanifest", "uuid contains delimiter: %@", uuid); return nil; } @@ -176,7 +176,7 @@ static NSDictionary* RecordDigestDictFromDER(NSData* data, NSError** error) void (^addValueSafelyToDictionaryAndLogIfNil)(NSMutableDictionary*, NSString*, id) = ^(NSMutableDictionary* dictionary, NSString* key, id value) { if (!value) { value = [NSNull null]; - secerror("CKKSManifestLeafRecord: saving manifest leaf record to database but %@ is nil", key); + ckkserror_global("ckksmanifest", "CKKSManifestLeafRecord: saving manifest leaf record to database but %@ is nil", key); } dictionary[key] = value; @@ -222,7 +222,7 @@ static NSDictionary* RecordDigestDictFromDER(NSData* data, NSError** error) NSData* derData = [[NSData alloc] initWithBase64EncodedString:record[SecCKRecordManifestLeafDERKey] options:0]; NSDictionary* recordDigestDict = RecordDigestDictFromDER(derData, &error); if (!recordDigestDict || error) { - secerror("failed to decode manifest leaf node DER with error: %@", error); + ckkserror_global("ckksmanifest", "failed to decode manifest leaf node DER with error: %@", error); return; } diff --git a/keychain/ckks/CKKSMirrorEntry.m b/keychain/ckks/CKKSMirrorEntry.m index 59900f08..edbfe449 100644 --- a/keychain/ckks/CKKSMirrorEntry.m +++ b/keychain/ckks/CKKSMirrorEntry.m @@ -78,7 +78,7 @@ // Why is obj-c nullable equality so difficult? if(!((record[SecCKRecordServerWasCurrent] == nil && self.wasCurrent == 0) || [record[SecCKRecordServerWasCurrent] isEqual: [NSNumber numberWithUnsignedLongLong:self.wasCurrent]])) { - secinfo("ckksitem", "was_current does not match"); + ckksinfo_global("ckksitem", "was_current does not match"); matches = false; } } diff --git a/keychain/ckks/CKKSNewTLKOperation.h b/keychain/ckks/CKKSNewTLKOperation.h index fb831ffe..562ff05c 100644 --- a/keychain/ckks/CKKSNewTLKOperation.h +++ b/keychain/ckks/CKKSNewTLKOperation.h @@ -26,16 +26,21 @@ #import #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ckks/CKKSProvideKeySetOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachine.h" NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -@interface CKKSNewTLKOperation : CKKSGroupOperation +@interface CKKSNewTLKOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks; @end diff --git a/keychain/ckks/CKKSNewTLKOperation.m b/keychain/ckks/CKKSNewTLKOperation.m index 9cf42a1b..6f39b601 100644 --- a/keychain/ckks/CKKSNewTLKOperation.m +++ b/keychain/ckks/CKKSNewTLKOperation.m @@ -27,6 +27,7 @@ #import "CKKSNewTLKOperation.h" #import "CKKSGroupOperation.h" #import "CKKSNearFutureScheduler.h" +#import "keychain/ckks/CKKSStates.h" #import "keychain/ckks/CloudKitCategories.h" #import "keychain/categories/NSError+UsefulConstructors.h" @@ -35,22 +36,26 @@ #import "keychain/ckks/CKKSTLKShareRecord.h" @interface CKKSNewTLKOperation () -@property NSBlockOperation* cloudkitModifyOperationFinished; -@property CKOperationGroup* ckoperationGroup; - @property (nullable) CKKSCurrentKeySet* keyset; @end @implementation CKKSNewTLKOperation +@synthesize intendedState = _intendedState; +@synthesize nextState = _nextState; @synthesize keyset; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks +{ if(self = [super init]) { + _deps = dependencies; _ckks = ckks; - _ckoperationGroup = ckoperationGroup; + + _nextState = SecCKKSZoneKeyStateError; + _intendedState = SecCKKSZoneKeyStateWaitForTLKUpload; } return self; } @@ -82,12 +87,13 @@ return; } + NSArray* currentTrustStates = self.deps.currentTrustStates; + // Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety. - __block bool enterWaitForTLKUpload = false; - [ckks dispatchSyncWithAccountKeys: ^bool{ + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { ckksnotice("ckkstlk", ckks, "CKKSNewTLKOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } ckks.lastNewTLKOperation = self; @@ -118,9 +124,16 @@ ckksnotice("ckkstlk", ckks, "Old TLK is: %@ %@", oldTLK, error); if(error != nil) { - ckkserror("ckkstlk", ckks, "Couldn't fetch and unwrap old TLK: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + if([self.deps.lockStateTracker isLockedError:error]) { + ckkserror("ckkstlk", self.deps.zoneID, "Couldn't fetch and unwrap old TLK due to lock state. Entering a waiting state; %@", error); + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + } else { + ckkserror("ckkstlk", self.deps.zoneID, "Couldn't fetch and unwrap old TLK: %@", error); + self.nextState = SecCKKSZoneKeyStateError; + } + self.error = error; + return CKKSDatabaseTransactionRollback; } // Generate new hierarchy: @@ -133,9 +146,9 @@ CKKSAESSIVKey* newAESKey = [CKKSAESSIVKey randomKey:&error]; if(error) { ckkserror("ckkstlk", ckks, "Couldn't create new TLK: %@", error); + self.nextState = SecCKKSZoneKeyStateError; self.error = error; - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:error]; - return false; + return CKKSDatabaseTransactionRollback; } newTLK = [[CKKSKey alloc] initSelfWrappedWithAESKey:newAESKey uuid:[[NSUUID UUID] UUIDString] @@ -151,8 +164,9 @@ if(error != nil) { ckkserror("ckkstlk", ckks, "couldn't make new key hierarchy: %@", error); // TODO: this really isn't the error state, but a 'retry'. - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + self.error = error; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionRollback; } CKKSCurrentKeyPointer* currentTLKPointer = [CKKSCurrentKeyPointer forKeyClass: SecCKKSKeyClassTLK withKeyUUID:newTLK.uuid zoneID:ckks.zoneID error: &error]; @@ -162,8 +176,9 @@ if(error != nil) { ckkserror("ckkstlk", ckks, "couldn't make current key records: %@", error); // TODO: this really isn't the error state, but a 'retry'. - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + self.nextState = SecCKKSZoneKeyStateError; + self.error = error; + return CKKSDatabaseTransactionRollback; } // Wrap old TLK under the new TLK @@ -171,23 +186,32 @@ if(wrappedOldTLK) { [wrappedOldTLK ensureKeyLoaded: &error]; if(error != nil) { - ckkserror("ckkstlk", ckks, "couldn't unwrap TLK, aborting new TLK operation: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + if([self.deps.lockStateTracker isLockedError:error]) { + ckkserror("ckkstlk", self.deps.zoneID, "Couldn't unwrap TLK due to lock state. Entering a waiting state; %@", error); + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + } else { + ckkserror("ckkstlk", self.deps.zoneID, "couldn't unwrap TLK, aborting new TLK operation: %@", error); + self.nextState = SecCKKSZoneKeyStateError; + } + self.error = error; + return CKKSDatabaseTransactionRollback; } [wrappedOldTLK wrapUnder: newTLK error:&error]; // TODO: should we continue in this error state? Might be required to fix broken TLKs/argue over which TLK should be used if(error != nil) { ckkserror("ckkstlk", ckks, "couldn't wrap oldTLK, aborting new TLK operation: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + self.nextState = SecCKKSZoneKeyStateError; + self.error = error; + return CKKSDatabaseTransactionRollback; } wrappedOldTLK.currentkey = false; } CKKSCurrentKeySet* keyset = [[CKKSCurrentKeySet alloc] init]; + keyset.viewName = newTLK.zoneID.zoneName; keyset.tlk = newTLK; keyset.classA = newClassAKey; @@ -210,21 +234,27 @@ [newClassAKey saveKeyMaterialToKeychain: &error]; [newClassCKey saveKeyMaterialToKeychain: &error]; if(error) { + if([self.deps.lockStateTracker isLockedError:error]) { + ckkserror("ckkstlk", self.deps.zoneID, "Couldn't save new key material to keychain due to lock state. Entering a waiting state; %@", error); + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagTLKCreationRequested]; + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + } else { + ckkserror("ckkstlk", self.deps.zoneID, "couldn't save new key material to keychain; aborting new TLK operation: %@", error); + self.nextState = SecCKKSZoneKeyStateError; + } self.error = error; - ckkserror("ckkstlk", ckks, "couldn't save new key material to keychain, aborting new TLK operation: %@", error); - [ckks _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateError withError: error]; - return false; + return CKKSDatabaseTransactionRollback; } // Generate the TLK sharing records for all trusted peers NSMutableSet* tlkShares = [NSMutableSet set]; - for(CKKSPeerProviderState* trustState in ckks.currentTrustStates) { + for(CKKSPeerProviderState* trustState in currentTrustStates) { if(trustState.currentSelfPeers.currentSelf == nil || trustState.currentSelfPeersError) { if(trustState.essential) { ckksnotice("ckkstlk", ckks, "Fatal error: unable to generate TLK shares for (%@): %@", newTLK, trustState.currentSelfPeersError); self.error = trustState.currentSelfPeersError; - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError withError:trustState.currentSelfPeersError]; - return false; + self.nextState = SecCKKSZoneKeyStateError; + return CKKSDatabaseTransactionRollback; } ckksnotice("ckkstlk", ckks, "Unable to generate TLK shares for (%@): %@", newTLK, trustState); continue; @@ -249,16 +279,13 @@ // Finish this transaction to cause a keychiain db commit // This means that if we provide the new keys to another thread, they'll be able to immediately load them from the keychain - enterWaitForTLKUpload = true; - return true; + // We'll provide the keyset after the commit occurs. + self.nextState = SecCKKSZoneKeyStateWaitForTLKUpload; + return CKKSDatabaseTransactionCommit; }]; - if(enterWaitForTLKUpload) { - // And move the CKKS state machine: - [ckks dispatchSyncWithAccountKeys: ^bool{ - [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForTLKUpload withError:nil]; - return true; - }]; + if(self.keyset) { + [self.deps provideKeySet:self.keyset]; } } diff --git a/keychain/ckks/CKKSNotifier.m b/keychain/ckks/CKKSNotifier.m index 2591a046..25531ee7 100644 --- a/keychain/ckks/CKKSNotifier.m +++ b/keychain/ckks/CKKSNotifier.m @@ -25,13 +25,13 @@ #import "CKKSNotifier.h" #import -#import +#import "keychain/ckks/CKKS.h" @implementation CKKSNotifyPostNotifier +(void)post:(NSString*)notification { if(notification) { - secnotice("ckks", "posting notification %@", notification); + ckksnotice_global("ckks", "posting notification %@", notification); notify_post([notification UTF8String]); } } diff --git a/keychain/ckks/CKKSOperationDependencies.h b/keychain/ckks/CKKSOperationDependencies.h new file mode 100644 index 00000000..ce1a6f58 --- /dev/null +++ b/keychain/ckks/CKKSOperationDependencies.h @@ -0,0 +1,72 @@ +#if OCTAGON + +#import +#import + +#import "keychain/ckks/CKKSCurrentKeyPointer.h" +#import "keychain/ckks/CKKSLockStateTracker.h" +#import "keychain/ckks/CKKSPeerProvider.h" +#import "keychain/ckks/CKKSProvideKeySetOperation.h" +#import "keychain/ckks/CKKSReachabilityTracker.h" +#import "keychain/ckks/CKKSNearFutureScheduler.h" +#import "keychain/ckks/CKKSSQLDatabaseObject.h" +#import "keychain/ckks/CKKSZoneModifier.h" +#import "keychain/analytics/CKKSLaunchSequence.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" +#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CKKSOperationDependencies : NSObject + +@property (readonly) CKRecordZoneID* zoneID; +@property (nullable) CKOperationGroup* ckoperationGroup; + +@property (readonly) CKKSLaunchSequence* launch; +@property (readonly) id flagHandler; + +@property (readonly) CKKSLockStateTracker* lockStateTracker; +@property (readonly) CKKSReachabilityTracker* reachabilityTracker; + +// Due to CKKS's current operation scheduling model, these might be updated after object creation +// For example, if an operation is created and waiting to run, and trust arrives, CKKS will reach in +// and inject the new providers, possibly before the operation runs. +@property (atomic) NSArray>* peerProviders; + +// Filled in after creation item creation +@property (nullable) TPSyncingPolicy* syncingPolicy; + +// This is weak as, currently, the databaseProvider owns the CKKSOperationDependencies. +@property (readonly,weak) id databaseProvider; + +@property CKKSZoneModifier* zoneModifier; + +@property (readonly) CKKSNearFutureScheduler* notifyViewChangedScheduler; +@property (readonly) CKKSNearFutureScheduler* savedTLKNotifier; + +// This might contain some key set provider operations. if you're an operation that knows about keysets, feel free to provide them. +@property NSHashTable*>* keysetProviderOperations; + +- (instancetype)initWithZoneID:(CKRecordZoneID*)zoneID + zoneModifier:(CKKSZoneModifier*)zoneModifier + ckoperationGroup:(CKOperationGroup* _Nullable)operationGroup + flagHandler:(id)flagHandler + launchSequence:(CKKSLaunchSequence*)launchSequence + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker + peerProviders:(NSArray>*)peerProviders + databaseProvider:(id)databaseProvider + notifyViewChangedScheduler:(CKKSNearFutureScheduler*)notifyViewChangedScheduler + savedTLKNotifier:(CKKSNearFutureScheduler*)savedTLKNotifier; + +// Convenience method to fetch the trust states from all peer providers +// Do not call this while on the SQL transaction queue! +- (NSArray*)currentTrustStates; + +- (void)provideKeySet:(CKKSCurrentKeySet*)keyset; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSOperationDependencies.m b/keychain/ckks/CKKSOperationDependencies.m new file mode 100644 index 00000000..db096930 --- /dev/null +++ b/keychain/ckks/CKKSOperationDependencies.m @@ -0,0 +1,71 @@ + +#if OCTAGON + +#import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSOperationDependencies.h" + +@implementation CKKSOperationDependencies + +- (instancetype)initWithZoneID:(CKRecordZoneID*)zoneID + zoneModifier:(CKKSZoneModifier*)zoneModifier + ckoperationGroup:(CKOperationGroup* _Nullable)operationGroup + flagHandler:(id)flagHandler + launchSequence:(CKKSLaunchSequence*)launchSequence + lockStateTracker:(CKKSLockStateTracker*)lockStateTracker + reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker + peerProviders:(NSArray>*)peerProviders + databaseProvider:(id)databaseProvider + notifyViewChangedScheduler:(CKKSNearFutureScheduler*)notifyViewChangedScheduler + savedTLKNotifier:(CKKSNearFutureScheduler*)savedTLKNotifier +{ + if((self = [super init])) { + _zoneID = zoneID; + _zoneModifier = zoneModifier; + _ckoperationGroup = operationGroup; + _flagHandler = flagHandler; + _launch = launchSequence; + _lockStateTracker = lockStateTracker; + _reachabilityTracker = reachabilityTracker; + _peerProviders = peerProviders; + _databaseProvider = databaseProvider; + _notifyViewChangedScheduler = notifyViewChangedScheduler; + _savedTLKNotifier = savedTLKNotifier; + + _keysetProviderOperations = [NSHashTable weakObjectsHashTable]; + } + return self; +} + +- (NSArray*)currentTrustStates +{ + NSArray>* peerProviders = self.peerProviders; + NSMutableArray* trustStates = [NSMutableArray array]; + +#if DEBUG + NSAssert(![self.databaseProvider insideSQLTransaction], @"Cannot fetch current trust states from inside a SQL transaction, on pain of deadlocK"); +#endif + + for(id provider in peerProviders) { + ckksnotice("ckks", self.zoneID, "Fetching account keys for provider %@", provider); + [trustStates addObject:provider.currentState]; + } + + return trustStates; +} + +- (void)provideKeySet:(CKKSCurrentKeySet*)keyset +{ + if(!keyset || !keyset.currentTLKPointer.currentKeyUUID) { + ckksnotice("ckkskey", self.zoneID, "No valid keyset provided: %@", keyset); + return; + } + ckksnotice("ckkskey", self.zoneID, "Providing keyset (%@) to listeners", keyset); + + for(CKKSResultOperation* op in self.keysetProviderOperations) { + [op provideKeySet:keyset]; + } +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/CKKSOutgoingQueueEntry.h b/keychain/ckks/CKKSOutgoingQueueEntry.h index dd7b00d4..f9a4e92e 100644 --- a/keychain/ckks/CKKSOutgoingQueueEntry.h +++ b/keychain/ckks/CKKSOutgoingQueueEntry.h @@ -55,7 +55,7 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)withItem:(SecDbItemRef)item action:(NSString*)action - ckks:(CKKSKeychainView*)ckks + zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (instancetype)fromDatabase:(NSString*)uuid state:(NSString*)state @@ -75,6 +75,11 @@ NS_ASSUME_NONNULL_BEGIN zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; ++ (NSArray*)allWithUUID:(NSString*)uuid + states:(NSArray*)states + zoneID:(CKRecordZoneID*)zoneID + error:(NSError * __autoreleasing *)error; + + (NSDictionary*)countsByStateInZone:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error; + (NSInteger)countByState:(CKKSItemState *)state zone:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error; diff --git a/keychain/ckks/CKKSOutgoingQueueEntry.m b/keychain/ckks/CKKSOutgoingQueueEntry.m index 4097edd9..1db55c40 100644 --- a/keychain/ckks/CKKSOutgoingQueueEntry.m +++ b/keychain/ckks/CKKSOutgoingQueueEntry.m @@ -86,7 +86,68 @@ true) ? YES : NO; } -+ (instancetype)withItem:(SecDbItemRef)item action:(NSString*)action ckks:(CKKSKeychainView*)ckks error: (NSError * __autoreleasing *) error { + ++ (CKKSKey*)keyForItem:(SecDbItemRef)item zoneID:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error +{ + if(!item) { + ckkserror("ckks-key", zoneID, "Cannot select a key for no item!"); + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSErrorUnexpectedNil + description:@"can't pick a key class for an empty item"]; + } + return nil; + } + + CKKSKeyClass* class = nil; + + NSString* protection = (__bridge NSString*)SecDbItemGetCachedValueWithName(item, kSecAttrAccessible); + if([protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleWhenUnlocked]) { + class = SecCKKSKeyClassA; + } else if([protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleAlwaysPrivate] || + [protection isEqualToString: (__bridge NSString*)kSecAttrAccessibleAfterFirstUnlock]) { + class = SecCKKSKeyClassC; + } else { + NSError* localError = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSInvalidKeyClass + description:[NSString stringWithFormat:@"can't pick key class for protection %@", protection]]; + ckkserror("ckks-key", zoneID, "can't pick key class: %@ %@", localError, item); + if(error) { + *error = localError; + } + + return nil; + } + + NSError* currentKeyError = nil; + CKKSKey* key = [CKKSKey currentKeyForClass:class zoneID:zoneID error:¤tKeyError]; + if(!key || currentKeyError) { + ckkserror("ckks-key", zoneID, "Couldn't find current key for %@: %@", class, currentKeyError); + + if(error) { + *error = currentKeyError; + } + return nil; + } + + // and make sure it's unwrapped. + NSError* loadedError = nil; + if(![key ensureKeyLoaded:&loadedError]) { + ckkserror("ckks-key", zoneID, "Couldn't load key(%@): %@", key, loadedError); + if(error) { + *error = loadedError; + } + return nil; + } + + return key; +} + ++ (instancetype)withItem:(SecDbItemRef)item + action:(NSString*)action + zoneID:(CKRecordZoneID*)zoneID + error:(NSError * __autoreleasing *)error +{ CFErrorRef cferror = NULL; CKKSKey* key = nil; NSString* uuid = nil; @@ -96,11 +157,15 @@ NSMutableDictionary* objd = nil; + ckkserror("ckksitem", zoneID, "Creating a (%@) outgoing queue entry for: %@", action, item); + NSError* keyError = nil; - key = [ckks keyForItem:item error:&keyError]; + key = [self keyForItem:item + zoneID:zoneID + error:&keyError]; if(!key || keyError) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:keyError.code description:@"No key for item" underlying:keyError]; - ckkserror("ckksitem", ckks, "no key for item: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "no key for item: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -110,7 +175,7 @@ objd = (__bridge_transfer NSMutableDictionary*) SecDbItemCopyPListWithMask(item, kSecDbSyncFlag, &cferror); if(!objd) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:CFErrorGetCode(cferror) description:@"Couldn't create object plist" underlying:(__bridge_transfer NSError*)cferror]; - ckkserror("ckksitem", ckks, "no plist: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "no plist: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -123,7 +188,7 @@ uuid = (__bridge_transfer NSString*) CFRetainSafe(SecDbItemGetValue(item, &v10itemuuid, &cferror)); if(!uuid || cferror) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:CKKSNoUUIDOnItem description:@"No UUID for item" underlying:(__bridge_transfer NSError*)cferror]; - ckkserror("ckksitem", ckks, "No UUID for item: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "No UUID for item: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -131,7 +196,7 @@ } if([uuid isKindOfClass:[NSNull class]]) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:CKKSNoUUIDOnItem description:@"UUID not found in object" underlying:nil]; - ckkserror("ckksitem", ckks, "couldn't fetch UUID: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "couldn't fetch UUID: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -141,7 +206,7 @@ accessgroup = (__bridge_transfer NSString*) CFRetainSafe(SecDbItemGetValue(item, &v6agrp, &cferror)); if(!accessgroup || cferror) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:CFErrorGetCode(cferror) description:@"accessgroup not found in object" underlying:(__bridge_transfer NSError*)cferror]; - ckkserror("ckksitem", ckks, "couldn't fetch access group from item: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "couldn't fetch access group from item: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -149,11 +214,11 @@ } if([accessgroup isKindOfClass:[NSNull class]]) { // That's okay; this is only used for rate limiting. - ckkserror("ckksitem", ckks, "couldn't fetch accessgroup: %@", item); + ckkserror("ckksitem", zoneID, "couldn't fetch accessgroup: %@", item); accessgroup = @"no-group"; } - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid zoneID:ckks.zoneID error:error]; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid zoneID:zoneID error:error]; // The action this change should be depends on any existing pending action, if any // Particularly, we need to coalesce (existing action, new action) to: @@ -162,7 +227,8 @@ // (delete, add) => modify NSString* actualAction = action; - CKKSOutgoingQueueEntry* existingOQE = [CKKSOutgoingQueueEntry tryFromDatabase:uuid state:SecCKKSStateNew zoneID:ckks.zoneID error:error]; + NSError* fetchError = nil; + CKKSOutgoingQueueEntry* existingOQE = [CKKSOutgoingQueueEntry tryFromDatabase:uuid state:SecCKKSStateNew zoneID:zoneID error:&fetchError]; if(existingOQE) { if([existingOQE.action isEqual: SecCKKSActionAdd]) { if([action isEqual:SecCKKSActionModify]) { @@ -180,10 +246,47 @@ if([existingOQE.action isEqual: SecCKKSActionDelete] && [action isEqual:SecCKKSActionAdd]) { actualAction = SecCKKSActionModify; } + } else if(fetchError) { + ckkserror("ckksitem", zoneID, "Unable to fetch an existing OQE due to error: %@", fetchError); + fetchError = nil; + + } else { + if(!ckme && [action isEqualToString:SecCKKSActionDelete]) { + CKKSOutgoingQueueEntry* anyExistingOQE = [CKKSOutgoingQueueEntry tryFromDatabase:uuid zoneID:zoneID error:&fetchError]; + + if(fetchError) { + ckkserror("ckksitem", zoneID, "Unable to fetch an existing OQE (any state) due to error: %@", fetchError); + } else if(!anyExistingOQE) { + // This is a delete for an item which doesn't exist. Therefore, this is a no-op. + ckkserror("ckksitem", zoneID, "Asked to delete a record for which we don't have a CKME or any OQE, ignoring: %@", uuid); + return nil; + } + } } newGenerationCount = ckme ? ckme.item.generationCount : (NSInteger) 0; // TODO: this is wrong + // Is this modification just changing the mdat? As a performance improvement, don't update the item in CK + if(ckme && !existingOQE && [actualAction isEqualToString:SecCKKSActionModify]) { + NSError* ckmeError = nil; + NSMutableDictionary* mirror = [[CKKSItemEncrypter decryptItemToDictionary:ckme.item error:&ckmeError] mutableCopy]; + NSMutableDictionary* objdCopy = [objd mutableCopy]; + + if(ckmeError) { + ckkserror("ckksitem", zoneID, "Unable to decrypt current CKME: %@", ckmeError); + } else { + mirror[(__bridge id)kSecAttrModificationDate] = nil; + mirror[(__bridge id)kSecAttrSHA1] = nil; + objdCopy[(__bridge id)kSecAttrModificationDate] = nil; + objdCopy[(__bridge id)kSecAttrSHA1] = nil; + + if([mirror isEqualToDictionary:objdCopy]) { + ckksnotice("ckksitem", zoneID, "Update to item only changes mdat; skipping %@", uuid); + return nil; + } + } + } + // Pull out any unencrypted fields NSNumber* pcsServiceIdentifier = objd[(id)kSecAttrPCSPlaintextServiceIdentifier]; objd[(id)kSecAttrPCSPlaintextServiceIdentifier] = nil; @@ -196,7 +299,7 @@ CKKSItem* baseitem = [[CKKSItem alloc] initWithUUID:uuid parentKeyUUID:key.uuid - zoneID:ckks.zoneID + zoneID:zoneID encodedCKRecord:nil encItem:nil wrappedkey:nil @@ -208,7 +311,7 @@ if(!baseitem) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:CKKSItemCreationFailure description:@"Couldn't create an item" underlying:nil]; - ckkserror("ckksitem", ckks, "couldn't create an item: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "couldn't create an item: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -224,7 +327,7 @@ if(!encryptedItem || encryptionError) { NSError* localerror = [NSError errorWithDomain:CKKSErrorDomain code:encryptionError.code description:@"Couldn't encrypt item" underlying:encryptionError]; - ckkserror("ckksitem", ckks, "couldn't encrypt item: %@ %@", localerror, item); + ckkserror("ckksitem", zoneID, "couldn't encrypt item: %@ %@", localerror, item); if(error) { *error = localerror; } @@ -270,6 +373,14 @@ return [self allWhere: @{@"state":CKKSNilToNSNull(state), @"ckzone":CKKSNilToNSNull(zoneID.zoneName)} error:error]; } ++ (NSArray*)allWithUUID:(NSString*)uuid states:(NSArray*)states zoneID:(CKRecordZoneID*)zoneID error:(NSError * __autoreleasing *)error +{ + return [self allWhere:@{@"UUID": CKKSNilToNSNull(uuid), + @"state": [[CKKSSQLWhereIn alloc] initWithValues:states], + @"ckzone":CKKSNilToNSNull(zoneID.zoneName)} + error:error]; +} + #pragma mark - CKKSSQLDatabaseObject methods diff --git a/keychain/ckks/CKKSOutgoingQueueOperation.h b/keychain/ckks/CKKSOutgoingQueueOperation.h index 9bce4142..49af52da 100644 --- a/keychain/ckks/CKKSOutgoingQueueOperation.h +++ b/keychain/ckks/CKKSOutgoingQueueOperation.h @@ -21,27 +21,34 @@ * @APPLE_LICENSE_HEADER_END@ */ -#import -#import "keychain/ckks/CKKSGroupOperation.h" #if OCTAGON +#import #import +#import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -@interface CKKSOutgoingQueueOperation : CKKSGroupOperation +@interface CKKSOutgoingQueueOperation : CKKSGroupOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; @property CKOperationGroup* ckoperationGroup; @property size_t itemsProcessed; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; - +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intending + errorState:(OctagonState*)errorState + ckoperationGroup:(CKOperationGroup*)ckoperationGroup; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSOutgoingQueueOperation.m b/keychain/ckks/CKKSOutgoingQueueOperation.m index 087ad6a9..2af7e5d8 100644 --- a/keychain/ckks/CKKSOutgoingQueueOperation.m +++ b/keychain/ckks/CKKSOutgoingQueueOperation.m @@ -26,41 +26,48 @@ #import #import +#import "keychain/ckks/CKKSAnalytics.h" +#import "keychain/ckks/CKKSCurrentKeyPointer.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSItemEncrypter.h" +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSManifest.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CKKSOutgoingQueueOperation.h" +#import "keychain/ckks/CKKSReencryptOutgoingItemsOperation.h" +#import "keychain/ckks/CKKSStates.h" #import "keychain/ckks/CKKSViewManager.h" -#import "CKKSKeychainView.h" -#import "CKKSCurrentKeyPointer.h" -#import "CKKSOutgoingQueueOperation.h" -#import "CKKSIncomingQueueEntry.h" -#import "CKKSItemEncrypter.h" -#import "CKKSOutgoingQueueEntry.h" -#import "CKKSReencryptOutgoingItemsOperation.h" -#import "CKKSManifest.h" -#import "CKKSAnalytics.h" #import "keychain/ckks/CloudKitCategories.h" #import "keychain/ot/ObjCImprovements.h" #include "keychain/securityd/SecItemServer.h" #include "keychain/securityd/SecItemDb.h" #include -#include #import "CKKSPowerCollection.h" +#import "utilities/SecCoreAnalytics.h" @interface CKKSOutgoingQueueOperation() @property CKModifyRecordsOperation* modifyRecordsOperation; @end @implementation CKKSOutgoingQueueOperation - -- (instancetype)init { - if(self = [super init]) { - } - return nil; -} -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intending + errorState:(OctagonState*)errorState + ckoperationGroup:(CKOperationGroup*)ckoperationGroup +{ if(self = [super init]) { + _deps = dependencies; _ckks = ckks; _ckoperationGroup = ckoperationGroup; + _nextState = errorState; + _intendedState = intending; + [self addNullableDependency:ckks.holdOutgoingQueueOperation]; // Depend on all previous CKKSOutgoingQueueOperations @@ -73,21 +80,22 @@ } - (void) groupStart { - // Synchronous, on some thread. Get back on the CKKS queue for thread-safety. WEAKIFY(self); CKKSKeychainView* ckks = self.ckks; if(!ckks) { - ckkserror("ckksoutgoing", ckks, "no ckks object"); + ckkserror("ckksoutgoing", self.deps.zoneID, "no ckks object"); return; } - [ckks dispatchSync: ^bool{ - ckks.lastOutgoingQueueOperation = self; - if(self.cancelled) { - ckksnotice("ckksoutgoing", ckks, "CKKSOutgoingQueueOperation cancelled, quitting"); - return false; - } + if(!ckks.itemSyncingEnabled) { + ckkserror("ckksoutgoing", self.deps.zoneID, "Item syncing for this view is disabled"); + return; + } + + ckks.lastOutgoingQueueOperation = self; + + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; @@ -98,10 +106,10 @@ for(NSString* uuid in priorityUUIDs) { NSError* priorityFetchError = nil; - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase:uuid zoneID:ckks.zoneID error:&priorityFetchError]; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase:uuid zoneID:self.deps.zoneID error:&priorityFetchError]; if(priorityFetchError) { - ckkserror("ckksoutgoing", ckks, "Unable to fetch priority uuid %@: %@", uuid, priorityFetchError); + ckkserror("ckksoutgoing", self.deps.zoneID, "Unable to fetch priority uuid %@: %@", uuid, priorityFetchError); continue; } @@ -110,12 +118,12 @@ } if(![oqe.state isEqualToString:SecCKKSStateNew]) { - ckksnotice("ckksoutgoing", ckks, "Priority uuid %@ is not in 'new': %@", uuid, oqe); + ckksnotice("ckksoutgoing", self.deps.zoneID, "Priority uuid %@ is not in 'new': %@", uuid, oqe); continue; } if(oqe) { - ckksnotice("ckksoutgoing", ckks, "Found OQE to fetch priority uuid %@: %@", uuid, priorityFetchError); + ckksnotice("ckksoutgoing", self.deps.zoneID, "Found OQE to fetch priority uuid %@: %@", uuid, priorityFetchError); [priorityEntries addObject:oqe]; [priorityEntryUUIDs addObject:oqe.uuid]; } @@ -124,12 +132,12 @@ // We only actually care about queue items in the 'new' state NSArray * newEntries = [CKKSOutgoingQueueEntry fetch:SecCKKSOutgoingQueueItemsAtOnce state:SecCKKSStateNew - zoneID:ckks.zoneID + zoneID:self.deps.zoneID error:&error]; if(error != nil) { - ckkserror("ckksoutgoing", ckks, "Error fetching outgoing queue records: %@", error); + ckkserror("ckksoutgoing", self.deps.zoneID, "Error fetching outgoing queue records: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } // Build our list of oqes to transmit @@ -147,32 +155,32 @@ bool fullUpload = queueEntries.count >= SecCKKSOutgoingQueueItemsAtOnce; - [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventOutgoingQueue zone:ckks.zoneName count:[queueEntries count]]; + [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventOutgoingQueue zone:self.deps.zoneID.zoneName count:[queueEntries count]]; - ckksinfo("ckksoutgoing", ckks, "processing outgoing queue: %@", queueEntries); + ckksinfo("ckksoutgoing", self.deps.zoneID, "processing outgoing queue: %@", queueEntries); NSMutableDictionary* recordsToSave = [[NSMutableDictionary alloc] init]; NSMutableSet* recordIDsModified = [[NSMutableSet alloc] init]; NSMutableSet*oqesModified = [[NSMutableSet alloc] init]; NSMutableArray* recordIDsToDelete = [[NSMutableArray alloc] init]; - CKKSCurrentKeyPointer* currentClassAKeyPointer = [CKKSCurrentKeyPointer fromDatabase: SecCKKSKeyClassA zoneID:ckks.zoneID error: &error]; - CKKSCurrentKeyPointer* currentClassCKeyPointer = [CKKSCurrentKeyPointer fromDatabase: SecCKKSKeyClassC zoneID:ckks.zoneID error: &error]; + CKKSCurrentKeyPointer* currentClassAKeyPointer = [CKKSCurrentKeyPointer fromDatabase:SecCKKSKeyClassA zoneID:self.deps.zoneID error:&error]; + CKKSCurrentKeyPointer* currentClassCKeyPointer = [CKKSCurrentKeyPointer fromDatabase:SecCKKSKeyClassC zoneID:self.deps.zoneID error:&error]; NSMutableDictionary* currentKeysToSave = [[NSMutableDictionary alloc] init]; bool needsReencrypt = false; if(error != nil) { - ckkserror("ckksoutgoing", ckks, "Couldn't load current class keys: %@", error); - return false; + ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't load current class keys: %@", error); + return CKKSDatabaseTransactionRollback; } for(CKKSOutgoingQueueEntry* oqe in queueEntries) { if(self.cancelled) { secdebug("ckksoutgoing", "CKKSOutgoingQueueOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } - CKKSOutgoingQueueEntry* inflight = [CKKSOutgoingQueueEntry tryFromDatabase: oqe.uuid state:SecCKKSStateInFlight zoneID:ckks.zoneID error: &error]; + CKKSOutgoingQueueEntry* inflight = [CKKSOutgoingQueueEntry tryFromDatabase: oqe.uuid state:SecCKKSStateInFlight zoneID:self.deps.zoneID error:&error]; if(!error && inflight) { // There is an inflight request with this UUID. Leave this request in-queue until CloudKit returns and we resolve the inflight request. continue; @@ -191,10 +199,10 @@ } else { // This item is encrypted under an old key. Set it up for reencryption and move on. - ckksnotice("ckksoutgoing", ckks, "Item's encryption key (%@ %@) is neither %@ or %@", oqe, oqe.item.parentKeyUUID, currentClassAKeyPointer, currentClassCKeyPointer); + ckksnotice("ckksoutgoing", self.deps.zoneID, "Item's encryption key (%@ %@) is neither %@ or %@", oqe, oqe.item.parentKeyUUID, currentClassAKeyPointer, currentClassCKeyPointer); [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateReencrypt error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save oqe to database: %@", error); + ckkserror("ckksoutgoing", self.deps.zoneID, "couldn't save oqe to database: %@", error); self.error = error; error = nil; } @@ -204,55 +212,55 @@ } if([oqe.action isEqualToString: SecCKKSActionAdd]) { - CKRecord* record = [oqe.item CKRecordWithZoneID: ckks.zoneID]; + CKRecord* record = [oqe.item CKRecordWithZoneID:self.deps.zoneID]; recordsToSave[record.recordID] = record; [recordIDsModified addObject: record.recordID]; [oqesModified addObject:oqe]; [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateInFlight error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); + ckkserror("ckksoutgoing", self.deps.zoneID, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); self.error = error; } } else if ([oqe.action isEqualToString: SecCKKSActionDelete]) { - CKRecordID* recordIDToDelete = [[CKRecordID alloc] initWithRecordName: oqe.item.uuid zoneID: ckks.zoneID]; + CKRecordID* recordIDToDelete = [[CKRecordID alloc] initWithRecordName:oqe.item.uuid zoneID:self.deps.zoneID]; [recordIDsToDelete addObject: recordIDToDelete]; [recordIDsModified addObject: recordIDToDelete]; [oqesModified addObject:oqe]; [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateInFlight error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); + ckkserror("ckksoutgoing", self.deps.zoneID, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); } } else if ([oqe.action isEqualToString: SecCKKSActionModify]) { // Load the existing item from the ckmirror. - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: oqe.item.uuid zoneID:ckks.zoneID error:&error]; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:oqe.item.uuid zoneID:self.deps.zoneID error:&error]; if(!ckme) { // This is a problem: we have an update to an item that doesn't exist. // Either: an Add operation we launched failed due to a CloudKit error (conflict?) and this is a follow-on update // Or: ? - ckkserror("ckksoutgoing", ckks, "update to a record that doesn't exist? %@", oqe.item.uuid); + ckkserror("ckksoutgoing", self.deps.zoneID, "update to a record that doesn't exist? %@", oqe.item.uuid); // treat as an add. - CKRecord* record = [oqe.item CKRecordWithZoneID: ckks.zoneID]; + CKRecord* record = [oqe.item CKRecordWithZoneID:self.deps.zoneID]; recordsToSave[record.recordID] = record; [recordIDsModified addObject: record.recordID]; [oqesModified addObject:oqe]; [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateInFlight error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); + ckkserror("ckksoutgoing", self.deps.zoneID, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); self.error = error; } } else { if(![oqe.item.storedCKRecord.recordChangeTag isEqual: ckme.item.storedCKRecord.recordChangeTag]) { // The mirror entry has updated since this item was created. If we proceed, we might end up with // a badly-authenticated record. - ckksnotice("ckksoutgoing", ckks, "Record (%@)'s change tag doesn't match ckmirror's change tag, reencrypting", oqe); + ckksnotice("ckksoutgoing", self.deps.zoneID, "Record (%@)'s change tag doesn't match ckmirror's change tag, reencrypting", oqe); [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateReencrypt error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save oqe to database: %@", error); + ckkserror("ckksoutgoing", self.deps.zoneID, "couldn't save oqe to database: %@", error); self.error = error; error = nil; } @@ -260,31 +268,29 @@ continue; } // Grab the old ckrecord and update it - CKRecord* record = [oqe.item updateCKRecord: ckme.item.storedCKRecord zoneID: ckks.zoneID]; + CKRecord* record = [oqe.item updateCKRecord: ckme.item.storedCKRecord zoneID: self.deps.zoneID]; recordsToSave[record.recordID] = record; [recordIDsModified addObject: record.recordID]; [oqesModified addObject:oqe]; [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateInFlight error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); + ckkserror("ckksoutgoing", self.deps.zoneID, "couldn't save state for CKKSOutgoingQueueEntry: %@", error); } } } } if(needsReencrypt) { - ckksnotice("ckksoutgoing", ckks, "An item needs reencryption!"); - - CKKSReencryptOutgoingItemsOperation* op = [[CKKSReencryptOutgoingItemsOperation alloc] initWithCKKSKeychainView:ckks ckoperationGroup:self.ckoperationGroup]; - [ckks scheduleOperation: op]; + ckksnotice("ckksoutgoing", self.deps.zoneID, "An item needs reencryption!"); + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagItemReencryptionNeeded]; } if([recordsToSave count] == 0 && [recordIDsToDelete count] == 0) { // Nothing to do! exit. - ckksnotice("ckksoutgoing", ckks, "Nothing in outgoing queue to process"); + ckksnotice("ckksoutgoing", self.deps.zoneID, "Nothing in outgoing queue to process"); if(self.ckoperationGroup) { - ckksnotice("ckksoutgoing", ckks, "End of operation group: %@", self.ckoperationGroup); + ckksinfo("ckksoutgoing", self.deps.zoneID, "End of operation group: %@", self.ckoperationGroup); } return true; } @@ -295,40 +301,23 @@ modifyComplete.name = @"modifyRecordsComplete"; [self dependOnBeforeGroupFinished: modifyComplete]; - if ([CKKSManifest shouldSyncManifests]) { - if (ckks.egoManifest) { - [ckks.egoManifest updateWithNewOrChangedRecords:recordsToSave.allValues deletedRecordIDs:recordIDsToDelete]; - for(CKRecord* record in [ckks.egoManifest allCKRecordsWithZoneID:ckks.zoneID]) { - recordsToSave[record.recordID] = record; - } - NSError* saveError = nil; - if (![ckks.egoManifest saveToDatabase:&saveError]) { - self.error = saveError; - ckkserror("ckksoutgoing", ckks, "could not save ego manifest with error: %@", saveError); - } - } - else { - ckkserror("ckksoutgoing", ckks, "could not get current ego manifest to update"); - } - } - void (^modifyRecordsCompletionBlock)(NSArray*, NSArray*, NSError*) = ^(NSArray *savedRecords, NSArray *deletedRecordIDs, NSError *ckerror) { STRONGIFY(self); CKKSKeychainView* strongCKKS = self.ckks; if(!self || !strongCKKS) { - ckkserror("ckksoutgoing", strongCKKS, "received callback for released object"); + ckkserror("ckksoutgoing", self.deps.zoneID, "received callback for released object"); return; } CKKSAnalytics* logger = [CKKSAnalytics logger]; - [strongCKKS dispatchSyncWithAccountKeys: ^bool{ + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(ckerror) { - ckkserror("ckksoutgoing", strongCKKS, "error processing outgoing queue: %@", ckerror); + ckkserror("ckksoutgoing", self.deps.zoneID, "error processing outgoing queue: %@", ckerror); [logger logRecoverableError:ckerror forEvent:CKKSEventProcessOutgoingQueue - inView:strongCKKS + zoneName:self.deps.zoneID.zoneName withAttributes:NULL]; // Tell CKKS about any out-of-date records @@ -342,12 +331,12 @@ if([self _onqueueIsErrorBadEtagOnKeyPointersOnly:ckerror]) { // The current key pointers have updated without our knowledge, so CloudKit failed this operation. Mark all records as 'needs reencryption' and kick that off. - ckksnotice("ckksoutgoing", strongCKKS, "Error is simply due to current key pointers changing; marking all records as 'needs reencrypt'"); + ckksnotice("ckksoutgoing", self.deps.zoneID, "Error is simply due to current key pointers changing; marking all records as 'needs reencrypt'"); [self _onqueueModifyAllRecords:failedRecords.allKeys as:SecCKKSStateReencrypt]; askForReencrypt = true; } else if([self _onqueueIsErrorMissingSyncKey:ckerror]) { - ckksnotice("ckksoutgoing", strongCKKS, "Error is due to the key records missing. Marking all as 'needs reencrypt'"); + ckksnotice("ckksoutgoing", self.deps.zoneID, "Error is due to the key records missing. Marking all as 'needs reencrypt'"); [self _onqueueModifyAllRecords:failedRecords.allKeys as:SecCKKSStateReencrypt]; askForReencrypt = true; @@ -356,7 +345,7 @@ for(CKRecordID* recordID in failedRecords) { NSError* recordError = failedRecords[recordID]; - ckksnotice("ckksoutgoing", strongCKKS, "failed record: %@ %@", recordID, recordError); + ckksnotice("ckksoutgoing", self.deps.zoneID, "failed record: %@ %@", recordID, recordError); if([recordError.domain isEqualToString: CKErrorDomain] && recordError.code == CKErrorServerRecordChanged) { if([recordID.recordName isEqualToString: SecCKKSKeyClassA] || @@ -378,13 +367,13 @@ CKKSOutgoingQueueEntry* inflightOQE = [CKKSOutgoingQueueEntry tryFromDatabase:recordID.recordName state:SecCKKSStateInFlight zoneID:recordID.zoneID error:&localerror]; [strongCKKS _onqueueChangeOutgoingQueueEntry:inflightOQE toState:SecCKKSStateNew error:&localerror]; if(localerror) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't clean up outgoing queue entry: %@", localerror); + ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't clean up outgoing queue entry: %@", localerror); } } } else { // Some unknown error occurred on this record. If it's an OQE, move it to the error state. - ckkserror("ckksoutgoing", strongCKKS, "Unknown error on row: %@ %@", recordID, recordError); + ckkserror("ckksoutgoing", self.deps.zoneID, "Unknown error on row: %@ %@", recordID, recordError); if([recordIDsModified containsObject:recordID]) { [self _onqueueModifyRecordAsError:recordID recordError:recordError]; } @@ -393,40 +382,43 @@ } if(askForReencrypt) { - // This will wait for the key hierarchy to become 'ready' - ckkserror("ckksoutgoing", strongCKKS, "Starting new Reencrypt items operation"); - CKKSReencryptOutgoingItemsOperation* op = [[CKKSReencryptOutgoingItemsOperation alloc] initWithCKKSKeychainView:strongCKKS - ckoperationGroup:self.ckoperationGroup]; - [strongCKKS scheduleOperation: op]; + [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagItemReencryptionNeeded]; } } else { // Some non-partial error occured. We should place all "inflight" OQEs back into the outgoing queue. - ckksnotice("ckks", strongCKKS, "Error is scary: putting all inflight OQEs back into state 'new'"); + ckksnotice("ckks", self.deps.zoneID, "Error is scary: putting all inflight OQEs back into state 'new'"); [self _onqueueModifyAllRecords:[recordIDsModified allObjects] as:SecCKKSStateNew]; } self.error = ckerror; - return true; + return CKKSDatabaseTransactionCommit; } - ckksnotice("ckksoutgoing", strongCKKS, "Completed processing outgoing queue (%d modifications, %d deletions)", (int)savedRecords.count, (int)deletedRecordIDs.count); + for(CKRecordID* deletedRecordID in deletedRecordIDs) { + ckksnotice("ckksoutgoing", self.deps.zoneID, "Record deletion successful for %@", deletedRecordID.recordName); + } + + ckksnotice("ckksoutgoing", self.deps.zoneID, "Completed processing outgoing queue (%d modifications, %d deletions)", (int)savedRecords.count, (int)deletedRecordIDs.count); NSError* error = NULL; CKKSPowerCollection *plstats = [[CKKSPowerCollection alloc] init]; for(CKRecord* record in savedRecords) { // Save the item records if([record.recordType isEqualToString: SecCKRecordItemType]) { - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase: record.recordID.recordName state: SecCKKSStateInFlight zoneID:strongCKKS.zoneID error:&error]; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:record.recordID.recordName + state:SecCKKSStateInFlight + zoneID:self.deps.zoneID + error:&error]; [strongCKKS _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&error]; if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't update %@ in outgoingqueue: %@", record.recordID.recordName, error); + ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't update %@ in outgoingqueue: %@", record.recordID.recordName, error); self.error = error; } error = nil; CKKSMirrorEntry* ckme = [[CKKSMirrorEntry alloc] initWithCKRecord: record]; [ckme saveToDatabase: &error]; if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't save %@ to ckmirror: %@", record.recordID.recordName, error); + ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't save %@ to ckmirror: %@", record.recordID.recordName, error); self.error = error; } @@ -437,7 +429,7 @@ CKKSCurrentKeyPointer* currentkey = [[CKKSCurrentKeyPointer alloc] initWithCKRecord: record]; [currentkey saveToDatabase: &error]; if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't save %@ to currentkey: %@", record.recordID.recordName, error); + ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't save %@ to currentkey: %@", record.recordID.recordName, error); self.error = error; } @@ -445,14 +437,14 @@ CKKSDeviceStateEntry* newcdse = [[CKKSDeviceStateEntry alloc] initWithCKRecord:record]; [newcdse saveToDatabase:&error]; if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't save %@ to ckdevicestate: %@", record.recordID.recordName, error); + ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't save %@ to ckdevicestate: %@", record.recordID.recordName, error); self.error = error; } } else if ([record.recordType isEqualToString:SecCKRecordManifestType]) { } else if (![record.recordType isEqualToString:SecCKRecordManifestLeafType]) { - ckkserror("ckksoutgoing", strongCKKS, "unknown record type in results: %@", record); + ckkserror("ckksoutgoing", self.deps.zoneID, "unknown record type in results: %@", record); } } @@ -460,17 +452,20 @@ for(CKRecordID* ckrecordID in deletedRecordIDs) { NSError* error = nil; - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase: ckrecordID.recordName state: SecCKKSStateInFlight zoneID:strongCKKS.zoneID error:&error]; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:ckrecordID.recordName + state:SecCKKSStateInFlight + zoneID:self.deps.zoneID + error:&error]; [strongCKKS _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&error]; if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't delete %@ from outgoingqueue: %@", ckrecordID.recordName, error); + ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't delete %@ from outgoingqueue: %@", ckrecordID.recordName, error); self.error = error; } error = nil; - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: ckrecordID.recordName zoneID:strongCKKS.zoneID error:&error]; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: ckrecordID.recordName zoneID:self.deps.zoneID error:&error]; [ckme deleteFromDatabase: &error]; if(error) { - ckkserror("ckksoutgoing", strongCKKS, "Couldn't delete %@ from ckmirror: %@", ckrecordID.recordName, error); + ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't delete %@ from ckmirror: %@", ckrecordID.recordName, error); self.error = error; } @@ -480,54 +475,58 @@ [plstats commit]; if(self.error) { - ckkserror("ckksoutgoing", strongCKKS, "Operation failed; rolling back: %@", self.error); + ckkserror("ckksoutgoing", self.deps.zoneID, "Operation failed; rolling back: %@", self.error); [logger logRecoverableError:self.error forEvent:CKKSEventProcessOutgoingQueue - inView:strongCKKS + zoneName:strongCKKS.zoneName withAttributes:NULL]; - return false; + return CKKSDatabaseTransactionRollback; } else { - [logger logSuccessForEvent:CKKSEventProcessOutgoingQueue inView:strongCKKS]; + [logger logSuccessForEvent:CKKSEventProcessOutgoingQueue zoneName:strongCKKS.zoneName]; } - return true; + return CKKSDatabaseTransactionCommit; }]; + self.nextState = self.intendedState; [self.operationQueue addOperation: modifyComplete]; - // Kick off another queue process. We expect it to exit instantly, but who knows! - // If we think the network is iffy, though, wait for it to come back - CKKSResultOperation* possibleNetworkDependency = nil; - CKKSReachabilityTracker* reachabilityTracker = strongCKKS.reachabilityTracker; - if(ckerror && [reachabilityTracker isNetworkError:ckerror]) { - possibleNetworkDependency = reachabilityTracker.reachabilityDependency; - } - [strongCKKS processOutgoingQueueAfter:possibleNetworkDependency - requiredDelay:fullUpload && !ckerror ? NSEC_PER_MSEC * 100 : DISPATCH_TIME_FOREVER - ckoperationGroup:self.ckoperationGroup]; + // If this was a "full upload", or we errored in any way, then kick off another queue process. There might be more items to send! + if(fullUpload || self.error) { + // If we think the network is iffy, though, wait for it to come back + CKKSResultOperation* possibleNetworkDependency = nil; + CKKSReachabilityTracker* reachabilityTracker = strongCKKS.reachabilityTracker; + if(ckerror && [reachabilityTracker isNetworkError:ckerror]) { + possibleNetworkDependency = reachabilityTracker.reachabilityDependency; + } + + [strongCKKS processOutgoingQueueAfter:possibleNetworkDependency + requiredDelay:fullUpload && !ckerror ? NSEC_PER_MSEC * 100 : DISPATCH_TIME_FOREVER + ckoperationGroup:self.ckoperationGroup]; + } }; - ckksinfo("ckksoutgoing", ckks, "Current keys to update: %@", currentKeysToSave); + ckksinfo("ckksoutgoing", self.deps.zoneID, "Current keys to update: %@", currentKeysToSave); for(CKKSCurrentKeyPointer* keypointer in currentKeysToSave.allValues) { - CKRecord* record = [keypointer CKRecordWithZoneID: ckks.zoneID]; + CKRecord* record = [keypointer CKRecordWithZoneID:self.deps.zoneID]; recordsToSave[record.recordID] = record; } // Piggyback on this operation to update our device state NSError* cdseError = nil; CKKSDeviceStateEntry* cdse = [ckks _onqueueCurrentDeviceStateEntry:&cdseError]; - CKRecord* cdseRecord = [cdse CKRecordWithZoneID: ckks.zoneID]; + CKRecord* cdseRecord = [cdse CKRecordWithZoneID:self.deps.zoneID]; if(cdseError) { - ckkserror("ckksoutgoing", ckks, "Can't make current device state: %@", cdseError); + ckkserror("ckksoutgoing", self.deps.zoneID, "Can't make current device state: %@", cdseError); } else if(!cdseRecord) { - ckkserror("ckksoutgoing", ckks, "Can't make current device state cloudkit record, but no reason why"); + ckkserror("ckksoutgoing", self.deps.zoneID, "Can't make current device state cloudkit record, but no reason why"); } else { // Add the CDSE to the outgoing records // TODO: maybe only do this every few hours? - ckksnotice("ckksoutgoing", ckks, "Updating device state: %@", cdse); + ckksnotice("ckksoutgoing", self.deps.zoneID, "Updating device state: %@", cdse); recordsToSave[cdseRecord.recordID] = cdseRecord; } - ckksinfo("ckksoutgoing", ckks, "Saving records %@ to CloudKit zone %@", recordsToSave, ckks.zoneID); + ckksinfo("ckksoutgoing", self.deps.zoneID, "Saving records %@ to CloudKit zone %@", recordsToSave, self.deps.zoneID); self.modifyRecordsOperation = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:recordsToSave.allValues recordIDsToDelete:recordIDsToDelete]; self.modifyRecordsOperation.atomic = TRUE; @@ -539,17 +538,25 @@ self.modifyRecordsOperation.savePolicy = CKRecordSaveIfServerRecordUnchanged; self.modifyRecordsOperation.group = self.ckoperationGroup; - ckksnotice("ckksoutgoing", ckks, "QoS: %d; operation group is %@", (int)self.modifyRecordsOperation.qualityOfService, self.modifyRecordsOperation.group); - ckksnotice("ckksoutgoing", ckks, "Beginning upload for %@ %@", recordsToSave.allKeys, recordIDsToDelete); + ckksnotice("ckksoutgoing", self.deps.zoneID, "QoS: %d; operation group is %@", (int)self.modifyRecordsOperation.qualityOfService, self.modifyRecordsOperation.group); + ckksnotice("ckksoutgoing", self.deps.zoneID, "Beginning upload for %d records, deleting %d records", + (int)recordsToSave.count, + (int)recordIDsToDelete.count); + + for(CKRecordID* recordID in [recordsToSave allKeys]) { + ckksinfo("ckksoutgoing", self.deps.zoneID, "Record to save: %@", recordID); + } + for(CKRecordID* recordID in recordIDsToDelete) { + ckksinfo("ckksoutgoing", self.deps.zoneID, "Record to delete: %@", recordID); + } self.modifyRecordsOperation.perRecordCompletionBlock = ^(CKRecord *record, NSError * _Nullable error) { STRONGIFY(self); - CKKSKeychainView* blockCKKS = self.ckks; if(!error) { - ckksnotice("ckksoutgoing", blockCKKS, "Record upload successful for %@ (%@)", record.recordID.recordName, record.recordChangeTag); + ckksnotice("ckksoutgoing", self.deps.zoneID, "Record upload successful for %@ (%@)", record.recordID.recordName, record.recordChangeTag); } else { - ckkserror("ckksoutgoing", blockCKKS, "error on row: %@ %@", error, record); + ckkserror("ckksoutgoing", self.deps.zoneID, "error on row: %@ %@", error, record); } }; @@ -564,7 +571,7 @@ - (void)_onqueueModifyRecordAsError:(CKRecordID*)recordID recordError:(NSError*)itemerror { CKKSKeychainView* ckks = self.ckks; if(!ckks) { - ckkserror("ckksoutgoing", ckks, "no CKKS object"); + ckkserror("ckksoutgoing", self.deps.zoneID, "no CKKS object"); return; } @@ -580,10 +587,10 @@ [recordID.recordName hasPrefix:@"ManifestLeafRecord:-:"]) { // Nothing to do here. We need a whole key refetch and synchronize. } else { - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:recordID.recordName state: SecCKKSStateInFlight zoneID:ckks.zoneID error:&error]; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:recordID.recordName state:SecCKKSStateInFlight zoneID:self.deps.zoneID error:&error]; [ckks _onqueueErrorOutgoingQueueEntry: oqe itemError: itemerror error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "Couldn't set OQE %@ as error: %@", recordID.recordName, error); + ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't set OQE %@ as error: %@", recordID.recordName, error); self.error = error; } count ++; @@ -594,7 +601,7 @@ - (void)_onqueueModifyAllRecords:(NSArray*)recordIDs as:(CKKSItemState*)state { CKKSKeychainView* ckks = self.ckks; if(!ckks) { - ckkserror("ckksoutgoing", ckks, "no CKKS object"); + ckkserror("ckksoutgoing", self.deps.zoneID, "no CKKS object"); return; } @@ -609,10 +616,10 @@ [recordID.recordName isEqualToString: SecCKKSKeyClassC]) { // Nothing to do here. We need a whole key refetch and synchronize. } else { - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:recordID.recordName state: SecCKKSStateInFlight zoneID:ckks.zoneID error:&error]; + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:recordID.recordName state:SecCKKSStateInFlight zoneID:self.deps.zoneID error:&error]; [ckks _onqueueChangeOutgoingQueueEntry:oqe toState:state error:&error]; if(error) { - ckkserror("ckksoutgoing", ckks, "Couldn't set OQE %@ as %@: %@", recordID.recordName, state, error); + ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't set OQE %@ as %@: %@", recordID.recordName, state, error); self.error = error; } count ++; @@ -620,7 +627,7 @@ } if([state isEqualToString:SecCKKSStateReencrypt]) { - SecADAddValueForScalarKey((__bridge CFStringRef) SecCKKSAggdItemReencryption, count); + [SecCoreAnalytics sendEvent:SecCKKSAggdItemReencryption event:@{SecCoreAnalyticsValue: [NSNumber numberWithUnsignedInteger:count]}]; } } @@ -632,7 +639,7 @@ NSError* recordError = failedRecords[recordID]; if([recordError isCKKSServerPluginError:CKKSServerMissingRecord]) { - secnotice("ckksoutgoing", "Error is a 'missing record' error: %@", recordError); + ckksnotice("ckksoutgoing", recordID.zoneID, "Error is a 'missing record' error: %@", recordError); return YES; } } @@ -642,6 +649,8 @@ } - (bool)_onqueueIsErrorBadEtagOnKeyPointersOnly:(NSError*)ckerror { + CKKSKeychainView* ckks = self.ckks; + dispatch_assert_queue(ckks.queue); bool anyOtherErrors = false; if([ckerror.domain isEqualToString:CKErrorDomain] && (ckerror.code == CKErrorPartialFailure)) { diff --git a/keychain/ckks/CKKSPeer.m b/keychain/ckks/CKKSPeer.m index 4904574f..75d82dde 100644 --- a/keychain/ckks/CKKSPeer.m +++ b/keychain/ckks/CKKSPeer.m @@ -100,8 +100,7 @@ NSString* const CKKSSOSPeerPrefix = @"spid-"; - (nullable instancetype)initWithCoder:(nonnull NSCoder*)decoder { - self = [super init]; - if(self) { + if ((self = [super init])) { _peerID = [decoder decodeObjectOfClass:[NSString class] forKey:@"peerID"]; NSData* encryptionSPKI = [decoder decodeObjectOfClass:[NSData class] forKey:@"encryptionKey"]; @@ -185,8 +184,7 @@ NSString* const CKKSSOSPeerPrefix = @"spid-"; - (nullable instancetype)initWithCoder:(nonnull NSCoder*)decoder { - self = [super init]; - if(self) { + if ((self = [super init])) { _spid = [decoder decodeObjectOfClass:[NSString class] forKey:@"spid"]; NSData* encryptionSPKI = [decoder decodeObjectOfClass:[NSData class] forKey:@"encryptionKey"]; diff --git a/keychain/ckks/CKKSPeerProvider.h b/keychain/ckks/CKKSPeerProvider.h index 6811e63c..cb9f30ec 100644 --- a/keychain/ckks/CKKSPeerProvider.h +++ b/keychain/ckks/CKKSPeerProvider.h @@ -2,6 +2,7 @@ #import #import "keychain/ckks/CKKSPeer.h" +#import "keychain/ckks/CKKSCurrentKeyPointer.h" NS_ASSUME_NONNULL_BEGIN @@ -34,6 +35,9 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - CKKSPeerProviderState +@class CKKSKey; +@class CKKSTLKShareRecord; + @interface CKKSPeerProviderState : NSObject @property NSString* peerProviderID; @@ -54,6 +58,13 @@ NS_ASSUME_NONNULL_BEGIN trustedPeers:(NSSet>* _Nullable)currentTrustedPeers trustedPeersError:(NSError* _Nullable)trustedPeersError; +- (NSSet>* _Nullable)findPeersMissingTLKSharesFor:(CKKSCurrentKeySet*)keyset + error:(NSError**)error; + +- (BOOL)unwrapKey:(CKKSKey*)proposedTLK + fromShares:(NSArray*)tlkShares + error:(NSError**)error; + + (CKKSPeerProviderState*)noPeersState:(id)provider; // Intended for use in PeerProviders. Thread-safety is up to the PeerProvider. diff --git a/keychain/ckks/CKKSPeerProvider.m b/keychain/ckks/CKKSPeerProvider.m index f773204d..66fe568a 100644 --- a/keychain/ckks/CKKSPeerProvider.m +++ b/keychain/ckks/CKKSPeerProvider.m @@ -1,6 +1,8 @@ #if OCTAGON #import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSKey.h" #import "keychain/ckks/CKKSPeerProvider.h" +#import "keychain/ckks/CKKSTLKShareRecord.h" #import "keychain/categories/NSError+UsefulConstructors.h" @implementation CKKSPeerProviderState @@ -70,6 +72,204 @@ trustedPeers:currentTrustedPeers trustedPeersError:trustedPeersError]; } + +// For this key, who doesn't yet have a valid CKKSTLKShare for it? +// Note that we really want a record sharing the TLK to ourselves, so this function might return +// a non-empty set even if all peers have the TLK: it wants us to make a record for ourself. +- (NSSet>* _Nullable)findPeersMissingTLKSharesFor:(CKKSCurrentKeySet*)keyset + error:(NSError**)error +{ + if(self.currentTrustedPeersError) { + ckkserror("ckksshare", keyset.tlk, "Couldn't find missing shares because trusted peers aren't available: %@", self.currentTrustedPeersError); + if(error) { + *error = self.currentTrustedPeersError; + } + return [NSSet set]; + } + if(self.currentSelfPeersError) { + ckkserror("ckksshare", keyset.tlk, "Couldn't find missing shares because self peers aren't available: %@", self.currentSelfPeersError); + if(error) { + *error = self.currentSelfPeersError; + } + return [NSSet set]; + } + + NSArray* tlkShares = [keyset.tlkShares arrayByAddingObjectsFromArray:keyset.pendingTLKShares ?: @[]]; + + NSMutableSet>* peersMissingShares = [NSMutableSet set]; + + // Ensure that the 'self peer' is one of the current trusted peers. Otherwise, any TLKShare we create + // won't be considered trusted the next time through... + if(![self.currentTrustedPeerIDs containsObject:self.currentSelfPeers.currentSelf.peerID]) { + ckkserror("ckksshare", keyset.tlk, "current self peer (%@) is not in the set of trusted peers: %@", + self.currentSelfPeers.currentSelf.peerID, + self.currentTrustedPeerIDs); + + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSLackingTrust + description:[NSString stringWithFormat:@"current self peer (%@) is not in the set of trusted peers", + self.currentSelfPeers.currentSelf.peerID]]; + } + + return nil; + } + + for(id peer in self.currentTrustedPeers) { + if(![peer shouldHaveView:keyset.tlk.zoneName]) { + ckkserror("ckksshare", keyset.tlk.keycore.zoneID, "Peer (%@) is not supposed to have view, skipping", peer); + continue; + } + + // Determine if we think this peer has enough things shared to them + bool alreadyShared = false; + for(CKKSTLKShareRecord* existingShare in tlkShares) { + // Ensure this share is to this peer... + if(![existingShare.share.receiverPeerID isEqualToString:peer.peerID]) { + continue; + } + + // If an SOS Peer sent this share, is its signature still valid? Or did the signing key change? + if([existingShare.senderPeerID hasPrefix:CKKSSOSPeerPrefix]) { + NSError* signatureError = nil; + if(![existingShare signatureVerifiesWithPeerSet:self.currentTrustedPeers error:&signatureError]) { + ckksnotice("ckksshare", keyset.tlk, "Existing TLKShare's signature doesn't verify with current peer set: %@ %@", signatureError, existingShare); + continue; + } + } + + if([existingShare.tlkUUID isEqualToString:keyset.tlk.uuid] && [self.currentTrustedPeerIDs containsObject:existingShare.senderPeerID]) { + // Was this shared to us? + if([peer.peerID isEqualToString:self.currentSelfPeers.currentSelf.peerID]) { + // We only count this as 'found' if we did the sharing and it's to our current keys + NSData* currentKey = self.currentSelfPeers.currentSelf.publicEncryptionKey.keyData; + + if([existingShare.senderPeerID isEqualToString:self.currentSelfPeers.currentSelf.peerID] && + [existingShare.share.receiverPublicEncryptionKeySPKI isEqual:currentKey]) { + ckksnotice("ckksshare", keyset.tlk, "Local peer %@ is shared %@ via self: %@", peer, keyset.tlk, existingShare); + alreadyShared = true; + break; + } else { + ckksnotice("ckksshare", keyset.tlk, "Local peer %@ is shared %@ via trusted %@, but that's not good enough", peer, keyset.tlk, existingShare); + } + + } else { + // Was this shared to the remote peer's current keys? + NSData* currentKeySPKI = peer.publicEncryptionKey.keyData; + + if([existingShare.share.receiverPublicEncryptionKeySPKI isEqual:currentKeySPKI]) { + // Some other peer has a trusted share. Cool! + ckksnotice("ckksshare", keyset.tlk, "Peer %@ is shared %@ via trusted %@", peer, keyset.tlk, existingShare); + alreadyShared = true; + break; + } else { + ckksnotice("ckksshare", keyset.tlk, "Peer %@ has a share for %@, but to old keys: %@", peer, keyset.tlk, existingShare); + } + } + } + } + + if(!alreadyShared) { + // Add this peer to our set, if it has an encryption key to receive the share + if(peer.publicEncryptionKey) { + [peersMissingShares addObject:peer]; + } + } + } + + if(peersMissingShares.count > 0u) { + // Log each and every one of the things + ckksnotice("ckksshare", keyset.tlk, "Missing TLK shares for %lu peers: %@", (unsigned long)peersMissingShares.count, peersMissingShares); + ckksnotice("ckksshare", keyset.tlk, "Self peers are (%@) %@", self.currentSelfPeersError ?: @"no error", self.currentSelfPeers); + ckksnotice("ckksshare", keyset.tlk, "Trusted peers are (%@) %@", self.currentTrustedPeersError ?: @"no error", self.currentTrustedPeers); + } + + return peersMissingShares; +} + +- (BOOL)unwrapKey:(CKKSKey*)proposedTLK + fromShares:(NSArray*)tlkShares + error:(NSError**)error +{ + if(!self.currentSelfPeers.currentSelf || self.currentSelfPeersError) { + ckkserror("ckksshare", proposedTLK, "Don't have self peers for %@: %@", self.peerProviderID, self.currentSelfPeersError); + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSNoEncryptionKey + description:@"Key unwrap failed" + underlying:self.currentSelfPeersError];; + } + return NO; + } + + if(!self.currentTrustedPeers || self.currentTrustedPeersError) { + ckkserror("ckksshare", proposedTLK, "Don't have trusted peers: %@", self.currentTrustedPeersError); + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSNoPeersAvailable + description:@"No trusted peers" + underlying:self.currentTrustedPeersError]; + } + return NO; + } + + NSError* lastShareError = nil; + + for(id selfPeer in self.currentSelfPeers.allSelves) { + NSMutableArray* possibleShares = [NSMutableArray array]; + + for(CKKSTLKShareRecord* share in tlkShares) { + if([share.share.receiverPeerID isEqualToString:selfPeer.peerID]) { + [possibleShares addObject:share]; + } + } + + if(possibleShares.count == 0) { + ckksnotice("ckksshare", proposedTLK, "No CKKSTLKShares to %@ for %@", selfPeer, proposedTLK); + continue; + } + + for(CKKSTLKShareRecord* possibleShare in possibleShares) { + NSError* possibleShareError = nil; + ckksnotice("ckksshare", proposedTLK, "Checking possible TLK share %@ as %@", possibleShare, selfPeer); + + CKKSKey* possibleKey = [possibleShare recoverTLK:selfPeer + trustedPeers:self.currentTrustedPeers + error:&possibleShareError]; + + if(!possibleKey || possibleShareError) { + ckkserror("ckksshare", proposedTLK, "Unable to unwrap TLKShare(%@) as %@: %@", + possibleShare, selfPeer, possibleShareError); + ckkserror("ckksshare", proposedTLK, "Current trust set: %@", self.currentTrustedPeers); + lastShareError = possibleShareError; + continue; + } + + bool result = [proposedTLK trySelfWrappedKeyCandidate:possibleKey.aessivkey error:&possibleShareError]; + if(!result || possibleShareError) { + ckkserror("ckksshare", proposedTLK, "Unwrapped TLKShare(%@) does not unwrap proposed TLK(%@) as %@: %@", + possibleShare, proposedTLK, self.currentSelfPeers.currentSelf, possibleShareError); + lastShareError = possibleShareError; + continue; + } + + ckksnotice("ckksshare", proposedTLK, "TLKShare(%@) unlocked TLK(%@) as %@", + possibleShare, proposedTLK, selfPeer); + + return YES; + } + } + + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSNoTrustedTLKShares + description:[NSString stringWithFormat:@"No trusted TLKShares for %@", proposedTLK] + underlying:lastShareError]; + } + + return NO; +} + @end #endif diff --git a/keychain/ckks/CKKSProcessReceivedKeysOperation.h b/keychain/ckks/CKKSProcessReceivedKeysOperation.h index 362843ec..ccc7fcd7 100644 --- a/keychain/ckks/CKKSProcessReceivedKeysOperation.h +++ b/keychain/ckks/CKKSProcessReceivedKeysOperation.h @@ -32,24 +32,16 @@ NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -// CKKS's state machine depends on its operations performing callbacks to move the state, but this means -// the operations cannot be reused outside of the state machine context. -// Therefore, split this operation into two: one which does the work, and another which does the CKKS state manipulation. - -@interface CKKSProcessReceivedKeysOperation : CKKSResultOperation +@interface CKKSProcessReceivedKeysOperation : CKKSResultOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; @property CKKSZoneKeyState* nextState; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks; -@end - -@interface CKKSProcessReceivedKeysStateMachineOperation : CKKSResultOperation -@property (weak) CKKSKeychainView* ckks; - -- (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks; +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSProcessReceivedKeysOperation.m b/keychain/ckks/CKKSProcessReceivedKeysOperation.m index 3ccc4fe1..d626171f 100644 --- a/keychain/ckks/CKKSProcessReceivedKeysOperation.m +++ b/keychain/ckks/CKKSProcessReceivedKeysOperation.m @@ -29,50 +29,37 @@ #import "CKKSCurrentKeyPointer.h" #import "CKKSKey.h" #import "CKKSProcessReceivedKeysOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" #import "keychain/ckks/CloudKitCategories.h" #import "keychain/categories/NSError+UsefulConstructors.h" @implementation CKKSProcessReceivedKeysOperation +@synthesize intendedState = _intendedState; -- (instancetype)init { - return nil; -} -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks { +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ if(self = [super init]) { - _ckks = ckks; - _nextState = SecCKKSZoneKeyStateError; + _deps = dependencies; + _intendedState = intendedState; + _nextState = errorState; } return self; } - (void)main { - // Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety. + NSArray* currentTrustStates = self.deps.currentTrustStates; - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - secerror("ckkskeys: No CKKS object"); - return; - } - - if(self.cancelled) { - ckksinfo("ckkskey", ckks, "CKKSProcessReceivedKeysOperation cancelled, quitting"); - return; - } + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult { + bool ok = [self _onqueueMain:currentTrustStates]; - [ckks dispatchSyncWithAccountKeys: ^bool{ - return [self _onqueueMain:ckks]; + return ok ? CKKSDatabaseTransactionCommit : CKKSDatabaseTransactionRollback; }]; } -- (bool)_onqueueMain:(CKKSKeychainView*)ckks +- (bool)_onqueueMain:(NSArray*)currentTrustStates { - if(self.cancelled) { - ckksinfo("ckkskey", ckks, "CKKSProcessReceivedKeysOperation cancelled, quitting"); - return false; - } - - ckks.lastProcessReceivedKeysOperation = self; - NSError* error = nil; CKKSKey* tlk = nil; CKKSKey* topKey = nil; @@ -81,39 +68,39 @@ // Updates from CloudKit are marked 'remote'; everything else is 'local'. // Step 1. Find all remote keys. - NSArray* remoteKeys = [CKKSKey remoteKeys:ckks.zoneID error:&error]; + NSArray* remoteKeys = [CKKSKey remoteKeys:self.deps.zoneID error:&error]; if(!remoteKeys) { - ckkserror("ckkskey", ckks, "couldn't fetch list of remote keys: %@", error); + ckkserror("ckkskey", self.deps.zoneID, "couldn't fetch list of remote keys: %@", error); self.error = error; self.nextState = SecCKKSZoneKeyStateError; return false; } if([remoteKeys count] == 0u) { - ckksnotice("ckkskey", ckks, "No remote keys? Quitting."); + ckksnotice("ckkskey", self.deps.zoneID, "No remote keys? Quitting."); // Not a ready state, more of a quizzical one? The key state machine will know what to do. self.error = error; - self.nextState = SecCKKSZoneKeyStateReady; + self.nextState = SecCKKSZoneKeyStateBecomeReady; return false; } - ckksinfo("ckkskey", ckks, "remote keys: %@", remoteKeys); + ckksinfo("ckkskey", self.deps.zoneID, "remote keys: %@", remoteKeys); // current TLK record: - CKKSCurrentKeyPointer* currentTLKPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassTLK zoneID:ckks.zoneID error:&error]; - CKKSCurrentKeyPointer* currentClassAPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassA zoneID:ckks.zoneID error:&error]; - CKKSCurrentKeyPointer* currentClassCPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassC zoneID:ckks.zoneID error:&error]; + CKKSCurrentKeyPointer* currentTLKPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassTLK zoneID:self.deps.zoneID error:&error]; + CKKSCurrentKeyPointer* currentClassAPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassA zoneID:self.deps.zoneID error:&error]; + CKKSCurrentKeyPointer* currentClassCPointer = [CKKSCurrentKeyPointer tryFromDatabase: SecCKKSKeyClassC zoneID:self.deps.zoneID error:&error]; // Do these pointers point at anything? NSError* localerror = nil; - CKKSKey* suggestedTLK = currentTLKPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentTLKPointer.currentKeyUUID zoneID:ckks.zoneID error:&localerror] : nil; - CKKSKey* suggestedClassA = currentClassAPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentClassAPointer.currentKeyUUID zoneID:ckks.zoneID error:&localerror] : nil; - CKKSKey* suggestedClassC = currentClassCPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentClassCPointer.currentKeyUUID zoneID:ckks.zoneID error:&localerror] : nil; + CKKSKey* suggestedTLK = currentTLKPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentTLKPointer.currentKeyUUID zoneID:self.deps.zoneID error:&localerror] : nil; + CKKSKey* suggestedClassA = currentClassAPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentClassAPointer.currentKeyUUID zoneID:self.deps.zoneID error:&localerror] : nil; + CKKSKey* suggestedClassC = currentClassCPointer.currentKeyUUID ? [CKKSKey tryFromDatabaseAnyState:currentClassCPointer.currentKeyUUID zoneID:self.deps.zoneID error:&localerror] : nil; if(!currentTLKPointer || !currentClassAPointer || !currentClassCPointer || !currentTLKPointer.currentKeyUUID || !currentClassAPointer.currentKeyUUID || !currentClassCPointer.currentKeyUUID || !suggestedTLK || !suggestedClassA || !suggestedClassC) { - ckkserror("ckkskey", ckks, "no current pointer for some keyclass: tlk:%@ a:%@ c:%@ %@ %@", + ckkserror("ckkskey", self.deps.zoneID, "no current pointer for some keyclass: tlk:%@ a:%@ c:%@ %@ %@", currentTLKPointer, currentClassAPointer, currentClassCPointer, error, localerror); self.error = error; self.nextState = SecCKKSZoneKeyStateBadCurrentPointers; @@ -127,7 +114,7 @@ tlk = key; } else { NSError *newError = [NSError errorWithDomain:CKKSErrorDomain code:CKKSKeyNotSelfWrapped description:[NSString stringWithFormat: @"current TLK doesn't wrap itself: %@ %@", key, key.parentKeyUUID] underlying:error]; - ckkserror("ckkskey", ckks, "%@", error); + ckkserror("ckkskey", self.deps.zoneID, "%@", error); self.error = newError; self.nextState = SecCKKSZoneKeyStateUnhealthy; return true; @@ -136,31 +123,33 @@ } if(!tlk) { - ckkserror("ckkskey", ckks, "couldn't find active TLK: %@", currentTLKPointer); + ckkserror("ckkskey", self.deps.zoneID, "couldn't find active TLK: %@", currentTLKPointer); self.error = error; self.nextState = SecCKKSZoneKeyStateUnhealthy; return true; } - // This key is our proposed TLK. Check with the CKKS object. - if(![ckks _onqueueWithAccountKeysCheckTLK: tlk error: &error]) { - // Was this error "I've never seen that TLK before in my life"? If so, enter the "wait for TLK sync" state. - if(error && [error.domain isEqualToString: @"securityd"] && error.code == errSecItemNotFound) { - ckksnotice("ckkskey", ckks, "Received a TLK which we don't have in the local keychain(%@). Entering waitfortlk.", tlk); - self.nextState = SecCKKSZoneKeyStateWaitForTLK; - return true; - } else if(error && [ckks.lockStateTracker isLockedError:error]) { - // TODO: _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateError should handle this. But, we don't have tests, so, leave this in until 33204154 - ckksnotice("ckkskey", ckks, "Received a TLK(%@), but keybag appears to be locked. Entering a waiting state.", tlk); + if(![tlk validTLK:&error]) { + // Something has gone horribly wrong. Enter error state. + ckkserror("ckkskey", self.deps.zoneID, "CKKS claims %@ is not a valid TLK: %@", tlk, error); + self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSInvalidTLK description:@"invalid TLK from CloudKit" underlying:error]; + self.nextState = SecCKKSZoneKeyStateError; + return true; + } + + // This key is our proposed TLK. + if(![tlk tlkMaterialPresentOrRecoverableViaTLKShare:currentTrustStates + error:&error]) { + // TLK is valid, but not present locally + if(error && [self.deps.lockStateTracker isLockedError:error]) { + ckksnotice("ckkskey", self.deps.zoneID, "Received a TLK(%@), but keybag appears to be locked. Entering a waiting state.", tlk); self.nextState = SecCKKSZoneKeyStateWaitForUnlock; - return true; } else { - // Otherwise, something has gone horribly wrong. enter error state. - ckkserror("ckkskey", ckks, "CKKS claims %@ is not a valid TLK: %@", tlk, error); - self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSInvalidTLK description:@"invalid TLK from CloudKit" underlying:error]; - self.nextState = SecCKKSZoneKeyStateError; - return true; + ckksnotice("ckkskey", self.deps.zoneID, "Received a TLK(%@) which we don't have in the local keychain: %@", tlk, error); + self.error = error; + self.nextState = SecCKKSZoneKeyStateTLKMissing; } + return true; } // Ensure that new keys wrap to the TLK. @@ -172,7 +161,7 @@ topKey = [key topKeyInAnyState:&error]; if(error != nil || ![topKey.uuid isEqual: tlk.uuid]) { - ckkserror("ckkskey", ckks, "new key %@ is orphaned (%@)", key, error); + ckkserror("ckkskey", self.deps.zoneID, "new key %@ is orphaned (%@)", key, error); // TODO: possibly re-fetch. Maybe not an actual error state. self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSOrphanedKey @@ -185,13 +174,13 @@ // Okay, it wraps to the TLK. Can we unwrap it? if(![key unwrapViaKeyHierarchy:&error] || error != nil) { - if(error && [ckks.lockStateTracker isLockedError:error]) { - ckksnotice("ckkskey", ckks, "Couldn't unwrap new key (%@), but keybag appears to be locked. Entering waitforunlock.", key); + if(error && [self.deps.lockStateTracker isLockedError:error]) { + ckksnotice("ckkskey", self.deps.zoneID, "Couldn't unwrap new key (%@), but keybag appears to be locked. Entering waitforunlock.", key); self.error = error; self.nextState = SecCKKSZoneKeyStateWaitForUnlock; return true; } else { - ckkserror("ckkskey", ckks, "new key %@ claims to wrap to TLK, but we can't unwrap it: %@", topKey, error); + ckkserror("ckkskey", self.deps.zoneID, "new key %@ claims to wrap to TLK, but we can't unwrap it: %@", topKey, error); self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSOrphanedKey description:[NSString stringWithFormat:@"unwrappable key(%@) in hierarchy: %@", topKey, error] @@ -201,7 +190,7 @@ } } - ckksnotice("ckkskey", ckks, "New key %@ wraps to tlk %@", key, tlk); + ckksnotice("ckkskey", self.deps.zoneID, "New key %@ wraps to tlk %@", key, tlk); } @@ -218,25 +207,31 @@ [key saveKeyMaterialToKeychain: &error]; + if(error) { - ckkserror("ckkskey", ckks, "couldn't save newly local key %@ to database: %@", key, error); + if([self.deps.lockStateTracker isLockedError:error]) { + ckksnotice("ckkskey", self.deps.zoneID, "Couldn't save newly local key %@ keychain, due to lock state. Entering a waiting state; %@", key, error); + self.nextState = SecCKKSZoneKeyStateWaitForUnlock; + } else { + ckkserror("ckkskey", self.deps.zoneID, "couldn't save newly local key %@ to database: %@", key, error); + self.nextState = SecCKKSZoneKeyStateError; + } self.error = error; - self.nextState = SecCKKSZoneKeyStateError; return false; } } // New key hierarchy? Get it backed up! // TLKs are now saved in the local keychain; fire off a backup - CKKSNearFutureScheduler* tlkNotifier = ckks.savedTLKNotifier; - ckksnotice("ckkstlk", ckks, "triggering new TLK notification: %@", tlkNotifier); + CKKSNearFutureScheduler* tlkNotifier = self.deps.savedTLKNotifier; + ckksnotice("ckkstlk", self.deps.zoneID, "triggering new TLK notification: %@", tlkNotifier); [tlkNotifier trigger]; if(!error) { - ckksnotice("ckkskey", ckks, "Accepted new key hierarchy"); - self.nextState = SecCKKSZoneKeyStateReady; + ckksnotice("ckkskey", self.deps.zoneID, "Accepted new key hierarchy"); + self.nextState = self.intendedState; } else { - ckkserror("ckkskey", ckks, "error accepting new key hierarchy: %@", error); + ckkserror("ckkskey", self.deps.zoneID, "error accepting new key hierarchy: %@", error); self.error = error; self.nextState = SecCKKSZoneKeyStateError; } @@ -245,29 +240,4 @@ @end; -@implementation CKKSProcessReceivedKeysStateMachineOperation -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks { - if(self = [super init]) { - _ckks = ckks; - } - return self; -} - -- (void)main -{ - CKKSKeychainView* ckks = self.ckks; - - // The following is an abuse of operations, but we need the state machine advancement to be in the same txion as the decision - CKKSProcessReceivedKeysOperation* op = [[CKKSProcessReceivedKeysOperation alloc] initWithCKKSKeychainView:ckks]; - - [ckks dispatchSyncWithAccountKeys:^bool { - bool ret = [op _onqueueMain:ckks]; - ckksnotice("ckkskey", ckks, "Finished processing received keys, moving to state %@", op.nextState); - [ckks _onqueueAdvanceKeyStateMachineToState:op.nextState withError:op.error]; - return ret; - }]; -} - -@end - #endif diff --git a/keychain/ckks/CKKSProvideKeySetOperation.h b/keychain/ckks/CKKSProvideKeySetOperation.h index 5ea8c2fe..f037108e 100644 --- a/keychain/ckks/CKKSProvideKeySetOperation.h +++ b/keychain/ckks/CKKSProvideKeySetOperation.h @@ -23,7 +23,6 @@ NS_ASSUME_NONNULL_BEGIN // But! -timeout: will work, and the operation will finish @interface CKKSProvideKeySetOperation : CKKSGroupOperation - (instancetype)initWithZoneName:(NSString*)zoneName; -- (instancetype)initWithZoneName:(NSString*)zoneName keySet:(CKKSCurrentKeySet*)set; - (void)provideKeySet:(CKKSCurrentKeySet*)keyset; @end diff --git a/keychain/ckks/CKKSProvideKeySetOperation.m b/keychain/ckks/CKKSProvideKeySetOperation.m index 0ea2aa79..a274764a 100644 --- a/keychain/ckks/CKKSProvideKeySetOperation.m +++ b/keychain/ckks/CKKSProvideKeySetOperation.m @@ -5,6 +5,7 @@ @interface CKKSProvideKeySetOperation () @property (nullable) CKKSCurrentKeySet* keyset; +@property dispatch_queue_t queue; @property (nullable) NSOperation* startDependency; @end @@ -19,29 +20,30 @@ _zoneName = zoneName; _keyset = nil; _startDependency = [NSBlockOperation blockOperationWithBlock:^{}]; + _startDependency.name = @"key-set-provided"; - [self addDependency:_startDependency]; - } - return self; -} + _queue = dispatch_queue_create("key-set-queue", DISPATCH_QUEUE_SERIAL); -- (instancetype)initWithZoneName:(NSString*)zoneName keySet:(CKKSCurrentKeySet*)set -{ - if((self = [super init])) { - _zoneName = zoneName; - _keyset = set; - _startDependency = nil; + [self addDependency:_startDependency]; } return self; } - (void)provideKeySet:(CKKSCurrentKeySet *)keyset { - self.keyset = keyset; - if(self.startDependency) { - [[NSOperationQueue currentQueue] addOperation:self.startDependency]; - self.startDependency = nil; - } + // Ensure that only one keyset is provided through each operation + dispatch_sync(self.queue, ^{ + if(!self.keyset) { + self.keyset = keyset; + if(self.startDependency) { + // Create a new queue here, just to be safe in case someone is waiting + NSOperationQueue* queue = [[NSOperationQueue alloc] init]; + [queue addOperation:self.startDependency]; + self.startDependency = nil; + } + } + }); + } @end diff --git a/keychain/ckks/CKKSRateLimiter.m b/keychain/ckks/CKKSRateLimiter.m index 7eb34b36..9994c922 100644 --- a/keychain/ckks/CKKSRateLimiter.m +++ b/keychain/ckks/CKKSRateLimiter.m @@ -23,7 +23,6 @@ #if OCTAGON #import "CKKSRateLimiter.h" -#import #import typedef NS_ENUM(int, BucketType) { @@ -45,8 +44,7 @@ typedef NS_ENUM(int, BucketType) { } - (instancetype)initWithCoder:(NSCoder *)coder { - self = [super init]; - if (self) { + if ((self = [super init])) { if (coder) { NSDictionary *encoded; encoded = [coder decodeObjectOfClasses:[NSSet setWithObjects:[NSDictionary class], diff --git a/keychain/ckks/CKKSReachabilityTracker.m b/keychain/ckks/CKKSReachabilityTracker.m index d13ecc3c..736a7367 100644 --- a/keychain/ckks/CKKSReachabilityTracker.m +++ b/keychain/ckks/CKKSReachabilityTracker.m @@ -71,7 +71,7 @@ STRONGIFY(self); bool networkAvailable = (nw_path_get_status(path) == nw_path_status_satisfied); - secinfo("ckksnetwork", "nw_path update: network is %@", networkAvailable ? @"available" : @"unavailable"); + ckksinfo_global("ckksnetwork", "nw_path update: network is %@", networkAvailable ? @"available" : @"unavailable"); [self _onqueueSetNetworkReachability:networkAvailable]; }); nw_path_monitor_start(self.networkMonitor); @@ -112,14 +112,14 @@ if(self.reachabilityDependency == nil || ![self.reachabilityDependency isPending]) { WEAKIFY(self); - secnotice("ckksnetwork", "Network unavailable"); + ckksnotice_global("network", "Network unavailable"); self.reachabilityDependency = [CKKSResultOperation named:@"network-available-dependency" withBlock: ^{ STRONGIFY(self); if (self.haveNetwork) { - secnotice("ckksnetwork", "Network available"); + ckksnotice_global("network", "Network available"); } else { - secnotice("ckksnetwork", "Network still not available, retrying after waiting %2.1f hours", - ((float)(REACHABILITY_TIMEOUT/NSEC_PER_SEC)) / 3600); + ckksnotice_global("network", "Network still not available, retrying after waiting %2.1f hours", + ((float)(REACHABILITY_TIMEOUT/NSEC_PER_SEC)) / 3600); } }]; diff --git a/keychain/ckks/CKKSRecordHolder.m b/keychain/ckks/CKKSRecordHolder.m index bb9db913..3ad87f77 100644 --- a/keychain/ckks/CKKSRecordHolder.m +++ b/keychain/ckks/CKKSRecordHolder.m @@ -54,7 +54,7 @@ _encodedCKRecord = encodedCKRecord; if(self.encodedCKRecord && ![self.storedCKRecord.recordID.zoneID isEqual: self.zoneID]) { - secerror("ckks: mismatching zone ids in a single record: %@ and %@", self.zoneID, self.storedCKRecord.recordID.zoneID); + ckkserror("ckks", self.zoneID, "mismatching zone ids in a single record: %@ and %@", self.zoneID, self.storedCKRecord.recordID.zoneID); } } return self; diff --git a/keychain/ckks/CKKSReencryptOutgoingItemsOperation.h b/keychain/ckks/CKKSReencryptOutgoingItemsOperation.h index e8947de5..ae94d53c 100644 --- a/keychain/ckks/CKKSReencryptOutgoingItemsOperation.h +++ b/keychain/ckks/CKKSReencryptOutgoingItemsOperation.h @@ -25,17 +25,23 @@ #import #import #import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -@interface CKKSReencryptOutgoingItemsOperation : CKKSResultOperation - +@interface CKKSReencryptOutgoingItemsOperation : CKKSResultOperation +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + @end diff --git a/keychain/ckks/CKKSReencryptOutgoingItemsOperation.m b/keychain/ckks/CKKSReencryptOutgoingItemsOperation.m index 6727f3bb..f50324d5 100644 --- a/keychain/ckks/CKKSReencryptOutgoingItemsOperation.m +++ b/keychain/ckks/CKKSReencryptOutgoingItemsOperation.m @@ -37,40 +37,44 @@ // Note: reencryption is not, strictly speaking, a CloudKit operation. However, we preserve this to pass it back to the outgoing queue operation we'll create @interface CKKSReencryptOutgoingItemsOperation () -@property CKOperationGroup* ckoperationGroup; @end @implementation CKKSReencryptOutgoingItemsOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ if(self = [super init]) { + _deps = dependencies; _ckks = ckks; - _ckoperationGroup = ckoperationGroup; + + _nextState = errorState; + _intendedState = intendedState; [self addNullableDependency:ckks.keyStateReadyDependency]; [self addNullableDependency:ckks.holdReencryptOutgoingItemsOperation]; // We also depend on the key hierarchy being reasonable [self addNullableDependency:ckks.keyStateReadyDependency]; - } return self; } -- (void) main { +- (void)main +{ CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksreencrypt", ckks, "no CKKS object"); - return; - } - [ckks dispatchSync: ^bool{ + [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { - ckksnotice("ckksreencrypt", ckks, "CKKSReencryptOutgoingItemsOperation cancelled, quitting"); - return false; + ckksnotice("ckksreencrypt", self.deps.zoneID, "CKKSReencryptOutgoingItemsOperation cancelled, quitting"); + return CKKSDatabaseTransactionRollback; } ckks.lastReencryptOutgoingItemsOperation = self; @@ -78,30 +82,30 @@ NSError* error = nil; bool newItems = false; - NSArray* oqes = [CKKSOutgoingQueueEntry allInState: SecCKKSStateReencrypt zoneID:ckks.zoneID error:&error]; + NSArray* oqes = [CKKSOutgoingQueueEntry allInState:SecCKKSStateReencrypt zoneID:self.deps.zoneID error:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Error fetching oqes from database: %@", error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Error fetching oqes from database: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } - [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventReencryptOutgoing zone:ckks.zoneName count:oqes.count]; + [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventReencryptOutgoing zone:self.deps.zoneID.zoneName count:oqes.count]; for(CKKSOutgoingQueueEntry* oqe in oqes) { // If there's already a 'new' item replacing this one, drop the reencryption on the floor CKKSOutgoingQueueEntry* newOQE = [CKKSOutgoingQueueEntry tryFromDatabase:oqe.uuid state:SecCKKSStateNew zoneID:oqe.item.zoneID error:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't load 'new' OQE to determine status: %@", error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't load 'new' OQE to determine status: %@", error); self.error = error; error = nil; continue; } if(newOQE) { - ckksnotice("ckksreencrypt", ckks, "Have a new OQE superceding %@ (%@), skipping", oqe, newOQE); + ckksnotice("ckksreencrypt", self.deps.zoneID, "Have a new OQE superceding %@ (%@), skipping", oqe, newOQE); // Don't use the state transition here, either, since this item isn't really changing states [oqe deleteFromDatabase:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't delete reencrypting OQE(%@) from database: %@", oqe, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't delete reencrypting OQE(%@) from database: %@", oqe, error); self.error = error; error = nil; continue; @@ -109,15 +113,16 @@ continue; } - ckksnotice("ckksreencrypt", ckks, "Reencrypting item %@", oqe); + ckksnotice("ckksreencrypt", self.deps.zoneID, "Reencrypting item %@", oqe); NSDictionary* item = [CKKSItemEncrypter decryptItemToDictionary: oqe.item error:&error]; if(error) { if ([error.domain isEqualToString:@"securityd"] && error.code == errSecItemNotFound) { - ckkserror("ckksreencrypt", ckks, "Couldn't find key in keychain; attempting to poke key hierarchy: %@", error); - [ckks.pokeKeyStateMachineScheduler trigger]; + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't find key in keychain; asking for reset: %@", error); + [ckks _onqueuePokeKeyStateMachine]; + self.nextState = SecCKKSZoneKeyStateUnhealthy; } else { - ckkserror("ckksreencrypt", ckks, "Couldn't decrypt item %@: %@", oqe, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't decrypt item %@: %@", oqe, error); } self.error = error; error = nil; @@ -125,26 +130,26 @@ } // Pick a key whose class matches the keyclass that this item - CKKSKey* originalKey = [CKKSKey fromDatabase: oqe.item.parentKeyUUID zoneID:ckks.zoneID error:&error]; + CKKSKey* originalKey = [CKKSKey fromDatabase: oqe.item.parentKeyUUID zoneID:self.deps.zoneID error:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't fetch key (%@) for item %@: %@", oqe.item.parentKeyUUID, oqe, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't fetch key (%@) for item %@: %@", oqe.item.parentKeyUUID, oqe, error); self.error = error; error = nil; continue; } - CKKSKey* newkey = [CKKSKey currentKeyForClass: originalKey.keyclass zoneID:ckks.zoneID error:&error]; + CKKSKey* newkey = [CKKSKey currentKeyForClass: originalKey.keyclass zoneID:self.deps.zoneID error:&error]; [newkey ensureKeyLoaded: &error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't fetch the current key for class %@: %@", originalKey.keyclass, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't fetch the current key for class %@: %@", originalKey.keyclass, error); self.error = error; error = nil; continue; } - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:oqe.item.uuid zoneID:ckks.zoneID error:&error]; + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:oqe.item.uuid zoneID:self.deps.zoneID error:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't fetch ckme (%@) for item %@: %@", oqe.item.parentKeyUUID, oqe, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't fetch ckme (%@) for item %@: %@", oqe.item.parentKeyUUID, oqe, error); self.error = error; error = nil; continue; @@ -157,7 +162,7 @@ error:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't encrypt under the new key %@: %@", newkey, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't encrypt under the new key %@: %@", newkey, error); self.error = error; error = nil; continue; @@ -173,7 +178,7 @@ [oqe deleteFromDatabase:&error]; [replacement saveToDatabase:&error]; if(error) { - ckkserror("ckksreencrypt", ckks, "Couldn't save newly-encrypted oqe %@: %@", replacement, error); + ckkserror("ckksreencrypt", self.deps.zoneID, "Couldn't save newly-encrypted oqe %@: %@", replacement, error); self.error = error; error = nil; continue; @@ -184,14 +189,15 @@ CKKSAnalytics* logger = [CKKSAnalytics logger]; if (self.error) { - [logger logRecoverableError:error forEvent:CKKSEventProcessReencryption inView:ckks withAttributes:nil]; + [logger logRecoverableError:error forEvent:CKKSEventProcessReencryption zoneName:self.deps.zoneID.zoneName withAttributes:nil]; } else { - [logger logSuccessForEvent:CKKSEventProcessReencryption inView:ckks]; + [logger logSuccessForEvent:CKKSEventProcessReencryption zoneName:self.deps.zoneID.zoneName ]; } if(newItems) { - [ckks processOutgoingQueue:self.ckoperationGroup]; + [ckks processOutgoingQueue:self.deps.ckoperationGroup]; } + self.nextState = self.intendedState; return true; }]; } diff --git a/keychain/ckks/CKKSResultOperation.h b/keychain/ckks/CKKSResultOperation.h index 5b29fccc..318f3665 100644 --- a/keychain/ckks/CKKSResultOperation.h +++ b/keychain/ckks/CKKSResultOperation.h @@ -45,7 +45,7 @@ enum { @property (nullable) NSDate* finishDate; @property CKKSCondition* completionHandlerDidRunCondition; -@property NSInteger descriptionErrorCode; // Set to non-0 for inclusion of this operation in NSError chains. Code is application-dependent. +@property NSInteger descriptionErrorCode; // Set to non-0 for inclusion of this operation in NSError chains. Code is application-dependent, but will be -1 in cases of excessive recursion. // If you subclass CKKSResultOperation, this is the method corresponding to descriptionErrorCode. Fill it in to your heart's content. - (NSError* _Nullable)descriptionError; diff --git a/keychain/ckks/CKKSResultOperation.m b/keychain/ckks/CKKSResultOperation.m index 57417657..8228f0e6 100644 --- a/keychain/ckks/CKKSResultOperation.m +++ b/keychain/ckks/CKKSResultOperation.m @@ -28,7 +28,7 @@ #import "keychain/ckks/CKKSCondition.h" #import "keychain/categories/NSError+UsefulConstructors.h" #import "keychain/ot/ObjCImprovements.h" -#include +#import "keychain/ckks/CKKS.h" @interface CKKSResultOperation() @property NSMutableArray* successDependencies; @@ -92,7 +92,7 @@ [super setCompletionBlock:^(void) { STRONGIFY(self); if (!self) { - secerror("ckksresultoperation: completion handler called on deallocated operation instance"); + ckkserror_global("resultoperation", "completion handler called on deallocated operation instance"); completionBlock(); // go ahead and still behave as things would if this method override were not here return; } @@ -149,16 +149,31 @@ // Returns, for this CKKSResultOperation, an error describing this operation or its dependents. // Used mainly by other CKKSResultOperations who time out waiting for this operation to start/complete. - (NSError* _Nullable)descriptionError { + static __thread unsigned __descriptionRecursion = 0; + + NSError* result = nil; + + __descriptionRecursion += 1; + if(self.descriptionErrorCode != 0) { - return [NSError errorWithDomain:CKKSResultDescriptionErrorDomain - code:self.descriptionErrorCode - userInfo:nil]; + result = [NSError errorWithDomain:CKKSResultDescriptionErrorDomain + code:self.descriptionErrorCode + userInfo:nil]; + } else if(__descriptionRecursion > 10) { + result = [NSError errorWithDomain:CKKSResultDescriptionErrorDomain + code:-1 + description:@"Excess recursion"]; } else { - return [self dependenciesDescriptionError]; + result = [self dependenciesDescriptionError]; } + + __descriptionRecursion -= 1; + + return result; } - (NSError*)_onqueueTimeoutError { + dispatch_assert_queue(self.timeoutQueue); // Find if any of our dependencies are CKKSResultOperations with a custom reason for existing NSError* underlyingReason = [self descriptionError]; diff --git a/keychain/ckks/CKKSSIV.h b/keychain/ckks/CKKSSIV.h index 718954e8..3b9e492a 100644 --- a/keychain/ckks/CKKSSIV.h +++ b/keychain/ckks/CKKSSIV.h @@ -52,6 +52,9 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithData:(NSData*)data; - (NSData*)wrappedData; - (NSString*)base64WrappedKey; + +// Almost certainly not a valid key; use if you need a placeholder ++ (CKKSWrappedAESSIVKey*)zeroedKey; @end @interface CKKSAESSIVKey : CKKSBaseAESSIVKey @@ -71,6 +74,9 @@ NS_ASSUME_NONNULL_BEGIN authenticatedData:(NSDictionary* _Nullable)ad error:(NSError* __autoreleasing*)error; +// Please only call this if you're storing this key to the keychain, or sending it to a peer. +- (NSData*)keyMaterial; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSSIV.m b/keychain/ckks/CKKSSIV.m index dde5f3c1..7388162c 100644 --- a/keychain/ckks/CKKSSIV.m +++ b/keychain/ckks/CKKSSIV.m @@ -155,8 +155,7 @@ } - (nullable instancetype)initWithCoder:(nonnull NSCoder *)decoder { - self = [super init]; - if (self) { + if ((self = [super init])) { NSUInteger len = 0; const uint8_t * bytes = [decoder decodeBytesForKey:@"wrappedkey" returnedLength:&len]; @@ -167,6 +166,12 @@ return self; } ++ (CKKSWrappedAESSIVKey*)zeroedKey +{ + NSData* zeroedData = [NSMutableData dataWithLength:CKKSWrappedKeySize]; + return [[CKKSWrappedAESSIVKey alloc] initWithData:zeroedData]; +} + @end @implementation CKKSAESSIVKey @@ -427,6 +432,11 @@ out: return localerror == NULL; } +- (NSData*)keyMaterial +{ + return [NSData _newZeroingDataWithBytes:self->key length:self->size]; +} + @end diff --git a/keychain/ckks/CKKSSQLDatabaseObject.h b/keychain/ckks/CKKSSQLDatabaseObject.h index a4698b38..c8579763 100644 --- a/keychain/ckks/CKKSSQLDatabaseObject.h +++ b/keychain/ckks/CKKSSQLDatabaseObject.h @@ -53,6 +53,26 @@ NS_ASSUME_NONNULL_BEGIN - (NSData* _Nullable)asBase64DecodedData; @end +// These thread-local variables should be set by your database layer +// This ensures that all SQL write operations are performed under the protection of a transaction. +// Use [CKKSSQLDatabaseObject +performCKKSTransaction] to get one of these if you don't have any other mechanism. +extern __thread bool CKKSSQLInTransaction; +extern __thread bool CKKSSQLInWriteTransaction; + +typedef NS_ENUM(uint8_t, CKKSDatabaseTransactionResult) { + CKKSDatabaseTransactionRollback = 0, + CKKSDatabaseTransactionCommit = 1, +}; + +// A database provider must provide these operations. +@protocol CKKSDatabaseProviderProtocol +- (void)dispatchSyncWithSQLTransaction:(CKKSDatabaseTransactionResult (^)(void))block; +- (void)dispatchSyncWithReadOnlySQLTransaction:(void (^)(void))block; + +// Used to maintain lock ordering. +- (BOOL)insideSQLTransaction; +@end + @interface CKKSSQLDatabaseObject : NSObject @property (copy) NSDictionary* originalSelfWhereClause; @@ -114,6 +134,8 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *)quotedString:(NSString *)string; ++ (BOOL)performCKKSTransaction:(CKKSDatabaseTransactionResult (^)(void))block; + #pragma mark - Subclasses must implement the following: // Given a row from the database, make this object @@ -171,5 +193,10 @@ NSString* CKKSSQLWhereColumnNameAsString(CKKSSQLWhereColumnName columnName); + (instancetype)op:(CKKSSQLWhereComparator)op value:(NSString*)value; @end +@interface CKKSSQLWhereIn : NSObject +@property NSArray* values; +- (instancetype)initWithValues:(NSArray*)values; +@end + NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSSQLDatabaseObject.m b/keychain/ckks/CKKSSQLDatabaseObject.m index f8c70d96..55b1dc24 100644 --- a/keychain/ckks/CKKSSQLDatabaseObject.m +++ b/keychain/ckks/CKKSSQLDatabaseObject.m @@ -24,6 +24,7 @@ #import #import "CKKSSQLDatabaseObject.h" #include "keychain/securityd/SecItemServer.h" +#include "keychain/securityd/SecItemDb.h" #import "keychain/ckks/CKKS.h" #import "CKKSKeychainView.h" @@ -83,11 +84,19 @@ } @end +__thread bool CKKSSQLInTransaction = false; +__thread bool CKKSSQLInWriteTransaction = false; + @implementation CKKSSQLDatabaseObject + (bool) saveToDatabaseTable: (NSString*) table row: (NSDictionary*) row connection: (SecDbConnectionRef) dbconn error: (NSError * __autoreleasing *) error { __block CFErrorRef cferror = NULL; +#if DEBUG + NSAssert(CKKSSQLInTransaction, @"Must be in a transaction to perform database writes"); + NSAssert(CKKSSQLInWriteTransaction, @"Must be in a write transaction to perform database writes"); +#endif + bool (^doWithConnection)(SecDbConnectionRef) = ^bool (SecDbConnectionRef dbconn) { NSString * columns = [row.allKeys componentsJoinedByString:@", "]; NSMutableString * values = [[NSMutableString alloc] init]; @@ -151,6 +160,19 @@ CKKSSQLWhereComparatorAsString(obj.sqlOp), CKKSSQLWhereColumnNameAsString(obj.columnName)]; + } else if([value isMemberOfClass:[CKKSSQLWhereIn class]]) { + CKKSSQLWhereIn* obj = (CKKSSQLWhereIn*)value; + + NSMutableArray* q = [NSMutableArray arrayWithCapacity:obj.values.count]; + for(NSString* value in obj.values) { + [q addObject: @"?"]; + (void)value; + } + + NSString* binds = [q componentsJoinedByString:@", "]; + + [whereClause appendFormat:@"%@ IN (%@)", key, binds]; + } else { [whereClause appendFormat: @"%@=(?)", key]; } @@ -202,16 +224,27 @@ + (void)bindWhereClause:(sqlite3_stmt*)stmt whereDict:(NSDictionary*)whereDict cferror:(CFErrorRef*)cferror { - __block int whereObjectsSkipped = 0; + __block int whereLocation = 1; + [whereDict.allKeys enumerateObjectsUsingBlock:^(id _Nonnull key, NSUInteger i, BOOL * _Nonnull stop) { if([whereDict[key] class] == [CKKSSQLWhereValue class]) { CKKSSQLWhereValue* obj = (CKKSSQLWhereValue*)whereDict[key]; - SecDbBindObject(stmt, (int)(i+1-whereObjectsSkipped), (__bridge CFStringRef)obj.value, cferror); + SecDbBindObject(stmt, whereLocation, (__bridge CFStringRef)obj.value, cferror); + whereLocation++; + } else if([whereDict[key] class] == [CKKSSQLWhereColumn class]) { // skip - whereObjectsSkipped += 1; + } else if([whereDict[key] isMemberOfClass:[CKKSSQLWhereIn class]]) { + CKKSSQLWhereIn* obj = (CKKSSQLWhereIn*)whereDict[key]; + + for(NSString* value in obj.values) { + SecDbBindObject(stmt, whereLocation, (__bridge CFStringRef)value, cferror); + whereLocation++; + } + } else { - SecDbBindObject(stmt, (int)(i+1-whereObjectsSkipped), (__bridge CFStringRef) whereDict[key], cferror); + SecDbBindObject(stmt, whereLocation, (__bridge CFStringRef) whereDict[key], cferror); + whereLocation++; } }]; } @@ -219,6 +252,11 @@ + (bool) deleteFromTable: (NSString*) table where: (NSDictionary*) whereDict connection:(SecDbConnectionRef) dbconn error: (NSError * __autoreleasing *) error { __block CFErrorRef cferror = NULL; +#if DEBUG + NSAssert(CKKSSQLInTransaction, @"Must be in a transaction to perform database writes"); + NSAssert(CKKSSQLInWriteTransaction, @"Must be in a write transaction to perform database writes"); +#endif + bool (^doWithConnection)(SecDbConnectionRef) = ^bool (SecDbConnectionRef dbconn) { NSString* whereClause = [CKKSSQLDatabaseObject makeWhereClause: whereDict]; @@ -344,6 +382,60 @@ return ret; } ++ (BOOL)performCKKSTransaction:(CKKSDatabaseTransactionResult (^)(void))block +{ + CFErrorRef cferror = NULL; + bool ok = kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbconn) { + CFErrorRef cferrorInternal = NULL; + bool ret = kc_transaction_type(dbconn, kSecDbExclusiveRemoteCKKSTransactionType, &cferrorInternal, ^bool{ + CKKSDatabaseTransactionResult result = CKKSDatabaseTransactionRollback; + + CKKSSQLInTransaction = true; + CKKSSQLInWriteTransaction = true; + result = block(); + CKKSSQLInWriteTransaction = false; + CKKSSQLInTransaction = false; + return result == CKKSDatabaseTransactionCommit; + }); + if(cferrorInternal) { + ckkserror_global("ckkssql", "error performing database transaction, major problems ahead: %@", cferrorInternal); + } + CFReleaseNull(cferrorInternal); + return ret; + }); + + if(cferror) { + ckkserror_global("ckkssql", "error performing database operation, major problems ahead: %@", cferror); + } + CFReleaseNull(cferror); + return ok; +} + ++ (BOOL)performCKKSReadonlyTransaction:(void(^)(void))block +{ + CFErrorRef cferror = NULL; + bool ok = kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbconn) { + CFErrorRef cferrorInternal = NULL; + bool ret = kc_transaction_type(dbconn, kSecDbNormalTransactionType, &cferrorInternal, ^bool{ + CKKSSQLInTransaction = true; + block(); + CKKSSQLInTransaction = false; + return true; + }); + if(cferrorInternal) { + ckkserror_global("ckkssql", "error performing database transaction, major problems ahead: %@", cferrorInternal); + } + CFReleaseNull(cferrorInternal); + return ret; + }); + + if(cferror) { + ckkserror_global("ckkssql", "error performing database operation, major problems ahead: %@", cferror); + } + CFReleaseNull(cferror); + return ok; +} + #pragma mark - Instance methods - (bool) saveToDatabase: (NSError * __autoreleasing *) error { @@ -579,3 +671,15 @@ NSString* CKKSSQLWhereColumnNameAsString(CKKSSQLWhereColumnName columnName) } @end + +#pragma mark - CKKSSQLWhereIn + +@implementation CKKSSQLWhereIn : NSObject +- (instancetype)initWithValues:(NSArray*)values +{ + if((self = [super init])) { + _values = values; + } + return self; +} +@end diff --git a/keychain/ckks/CKKSScanLocalItemsOperation.h b/keychain/ckks/CKKSScanLocalItemsOperation.h index 0ad03e57..3b1f930a 100644 --- a/keychain/ckks/CKKSScanLocalItemsOperation.h +++ b/keychain/ckks/CKKSScanLocalItemsOperation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2016-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,18 +23,20 @@ #import -#import "keychain/ckks/CKKSGroupOperation.h" - #if OCTAGON +#import "keychain/ckks/CKKSResultOperation.h" +#import "keychain/ckks/CKKSOperationDependencies.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" + NS_ASSUME_NONNULL_BEGIN @class CKKSKeychainView; -@class CKKSEgoManifest; -@interface CKKSScanLocalItemsOperation : CKKSResultOperation -@property CKOperationGroup* ckoperationGroup; +@interface CKKSScanLocalItemsOperation : CKKSResultOperation +@property (nullable) CKOperationGroup* ckoperationGroup; +@property CKKSOperationDependencies* deps; @property (weak) CKKSKeychainView* ckks; @property size_t recordsFound; @@ -43,8 +45,11 @@ NS_ASSUME_NONNULL_BEGIN @property size_t missingLocalItemsFound; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup; - +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState + ckoperationGroup:(CKOperationGroup* _Nullable)ckoperationGroup; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/CKKSScanLocalItemsOperation.m b/keychain/ckks/CKKSScanLocalItemsOperation.m index 3c3a6afe..e1f66eb8 100644 --- a/keychain/ckks/CKKSScanLocalItemsOperation.m +++ b/keychain/ckks/CKKSScanLocalItemsOperation.m @@ -22,7 +22,7 @@ */ #if OCTAGON -#import +#import #import #import @@ -36,8 +36,9 @@ #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ckks/CKKSKey.h" #import "keychain/ckks/CKKSViewManager.h" -#import "keychain/ckks/CKKSManifest.h" #import "keychain/ckks/CKKSItemEncrypter.h" +#import "keychain/ckks/CKKSStates.h" +#import "keychain/ckks/CKKSZoneStateEntry.h" #import "CKKSPowerCollection.h" @@ -51,43 +52,49 @@ @interface CKKSScanLocalItemsOperation () @property (assign) NSUInteger processedItems; + +@property BOOL newCKKSEntries; @end @implementation CKKSScanLocalItemsOperation +@synthesize nextState = _nextState; +@synthesize intendedState = _intendedState; - (instancetype)init { return nil; } -- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup { - if(self = [super init]) { +- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies + ckks:(CKKSKeychainView*)ckks + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState + ckoperationGroup:(CKOperationGroup*)ckoperationGroup +{ + if((self = [super init])) { + _deps = dependencies; _ckks = ckks; _ckoperationGroup = ckoperationGroup; + + _nextState = errorState; + _intendedState = intendedState; + _recordsFound = 0; _recordsAdded = 0; } return self; } -// returns true if the currently loaded TPPolicy in the view manager says that only items with a VewHint -// matching the viewName belong to this view. -- (BOOL)policyRecommendsOnlyViewHintItems:(CKKSKeychainView*)ckks -{ - // Early-exit for when feature is not on: - if(![[CKKSViewManager manager] useCKKSViewsFromPolicy]) { - return YES; - } - +- (NSDictionary*)queryPredicatesForViewMapping { TPPBPolicyKeyViewMapping* viewRule = nil; - // If there's more than one rule matching this view, then exit with NO. + // If there's more than one rule matching this view, then exit with an empty dictionary: the language doesn't support ORs. for(TPPBPolicyKeyViewMapping* mapping in [CKKSViewManager manager].policy.keyViewMapping) { - if([mapping.view isEqualToString:ckks.zoneName]) { + if([mapping.view isEqualToString:self.deps.zoneID.zoneName]) { if(viewRule == nil) { viewRule = mapping; } else { // Too many rules for this view! Don't perform optimization. - ckksnotice("ckksscan", ckks, "Too many policy rules for view %@", ckks.zoneName); - return NO; + ckksnotice("ckksscan", self.deps.zoneID, "Too many policy rules for view %@", self.deps.zoneID.zoneName); + return @{}; } } } @@ -98,306 +105,463 @@ !viewRule.matchingRule.hasNot && !viewRule.matchingRule.hasExists && viewRule.matchingRule.hasMatch) { - if([@"vwht" isEqualToString:viewRule.matchingRule.match.fieldName] && - [viewRule.matchingRule.match.regex isEqualToString:[NSString stringWithFormat:@"^%@$", ckks.zoneName]]) { - return YES; + if([((id)kSecAttrSyncViewHint) isEqualToString:viewRule.matchingRule.match.fieldName] && + [viewRule.matchingRule.match.regex isEqualToString:[NSString stringWithFormat:@"^%@$", self.deps.zoneID.zoneName]]) { + return @{ + (id)kSecAttrSyncViewHint: self.deps.zoneID.zoneName, + }; + } else if([((id)kSecAttrAccessGroup) isEqualToString:viewRule.matchingRule.match.fieldName] && + [viewRule.matchingRule.match.regex isEqualToString:@"^com\\.apple\\.cfnetwork$"]) { + // We can't match on any regex agrp match, because it might be some actually difficult regex. But, we know about this one! + return @{ + (id)kSecAttrAccessGroup: @"com.apple.cfnetwork", + }; + + } else if([((id)kSecAttrAccessGroup) isEqualToString:viewRule.matchingRule.match.fieldName] && + [viewRule.matchingRule.match.regex isEqualToString:@"^com\\.apple\\.safari\\.credit-cards$"]) { + // We can't match on any regex agrp match, because it might be some actually difficult regex. But, we know about this one! + return @{ + (id)kSecAttrAccessGroup: @"com.apple.safari.credit-cards", + }; + } else { - ckksnotice("ckksscan", ckks, "Policy view rule is not a match against viewhint: %@", viewRule); + ckksnotice("ckksscan", self.deps.zoneID, "Policy view rule is not a match against viewhint: %@", viewRule); } } else { - ckksnotice("ckksscan", ckks, "Policy view rule is of unknown type: %@", viewRule); + ckksnotice("ckksscan", self.deps.zoneID, "Policy view rule is complex: %@", viewRule); } - return NO; + return @{}; } -- (void) main { - // Take a strong reference. - CKKSKeychainView* ckks = self.ckks; - if(!ckks) { - ckkserror("ckksscan", ckks, "no CKKS object"); +- (BOOL)executeQuery:(NSDictionary*)queryPredicates readWrite:(bool)readWrite error:(NSError**)error block:(void (^_Nonnull)(SecDbItemRef item))block +{ + __block CFErrorRef cferror = NULL; + __block bool ok = false; + + Query *q = query_create_with_limit((__bridge CFDictionaryRef)queryPredicates, NULL, kSecMatchUnlimited, NULL, &cferror); + + if(cferror) { + ckkserror("ckksscan", self.deps.zoneID, "couldn't create query: %@", cferror); + SecTranslateError(error, cferror); + return NO; + } + + ok = kc_with_dbt(readWrite, &cferror, ^(SecDbConnectionRef dbt) { + return SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef item, bool *stop) { + block(item); + }); + }); + + if(readWrite) { + ok = query_notify_and_destroy(q, ok, &cferror); + } else { + ok = query_destroy(q, &cferror); + } + + if(cferror || !ok) { + ckkserror("ckksscan", self.deps.zoneID, "couldn't execute query: %@", cferror); + SecTranslateError(error, cferror); + return NO; + } + + return YES; +} + +- (BOOL)onboardItemToCKKS:(SecDbItemRef)item error:(NSError**)error +{ + NSError* itemSaveError = nil; + + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry withItem:item + action:SecCKKSActionAdd + zoneID:self.deps.zoneID + error:&itemSaveError]; + + if(itemSaveError) { + ckkserror("ckksscan", self.deps.zoneID, "Need to upload %@, but can't create outgoing entry: %@", item, itemSaveError); + if(error) { + *error = itemSaveError; + } + return NO; + } + + ckksnotice("ckksscan", self.deps.zoneID, "Syncing new item: %@", oqe); + + [oqe saveToDatabase:&itemSaveError]; + if(itemSaveError) { + ckkserror("ckksscan", self.deps.zoneID, "Need to upload %@, but can't save to database: %@", oqe, itemSaveError); + self.error = itemSaveError; + return NO; + } + + self.newCKKSEntries = true; + self.recordsAdded += 1; + + return YES; +} + +- (void)onboardItemsWithUUIDs:(NSSet*)uuids itemClass:(NSString*)itemClass databaseProvider:(id)databaseProvider +{ + ckksnotice("ckksscan", self.deps.zoneID, "Found %d missing %@ items", (int)uuids.count, itemClass); + // Use one transaction for each item to allow for SecItem API calls to interleave + for(NSString* itemUUID in uuids) { + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult { + NSDictionary* queryAttributes = @{ + (id)kSecClass: itemClass, + (id)kSecReturnRef: @(YES), + (id)kSecAttrSynchronizable: @(YES), + (id)kSecAttrTombstone: @(NO), + (id)kSecAttrUUID: itemUUID, + }; + + ckksnotice("ckksscan", self.deps.zoneID, "Onboarding %@ %@", itemClass, itemUUID); + + __block NSError* itemSaveError = nil; + + [self executeQuery:queryAttributes readWrite:false error:&itemSaveError block:^(SecDbItemRef itemToSave) { + [self onboardItemToCKKS:itemToSave error:&itemSaveError]; + }]; + + if(itemSaveError) { + ckkserror("ckksscan", self.deps.zoneID, "Need to upload %@, but can't save to database: %@", itemUUID, itemSaveError); + self.error = itemSaveError; + return CKKSDatabaseTransactionRollback; + } + + return CKKSDatabaseTransactionCommit; + }]; + } +} + +- (void)fixUUIDlessItemsWithPrimaryKeys:(NSMutableSet*)primaryKeys databaseProvider:(id)databaseProvider +{ + ckksnotice("ckksscan", self.deps.zoneID, "Found %d items missing UUIDs", (int)primaryKeys.count); + + if([primaryKeys count] == 0) { return; } - [ckks.launch addEvent:@"scan-local-items"]; + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + __block NSError* itemError = nil; + + for(NSDictionary* primaryKey in primaryKeys) { + ckksnotice("ckksscan", self.deps.zoneID, "Found item with no uuid: %@", primaryKey); + + __block CFErrorRef cferror = NULL; + + bool connectionSuccess = kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { + Query *q = query_create_with_limit((__bridge CFDictionaryRef)primaryKey, NULL, kSecMatchUnlimited, NULL, &cferror); + + if(!q || cferror) { + ckkserror("ckksscan", self.deps.zoneID, "couldn't create query: %@", cferror); + return false; + } + + __block bool ok = true; + + ok &= SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef uuidlessItem, bool *stop) { + NSString* uuid = [[NSUUID UUID] UUIDString]; + NSDictionary* updates = @{(id)kSecAttrUUID: uuid}; + + ckksnotice("ckksscan", self.deps.zoneID, "Assigning new UUID %@ for item %@", uuid, uuidlessItem); + + SecDbItemRef new_item = SecDbItemCopyWithUpdates(uuidlessItem, (__bridge CFDictionaryRef)updates, &cferror); + + if(!new_item) { + SecTranslateError(&itemError, cferror); + self.error = itemError; + ckksnotice("ckksscan", self.deps.zoneID, "Unable to copy item with new UUID: %@", cferror); + return; + } + + bool updateSuccess = kc_transaction_type(dbt, kSecDbExclusiveRemoteCKKSTransactionType, &cferror, ^{ + return SecDbItemUpdate(uuidlessItem, new_item, dbt, kCFBooleanFalse, q->q_uuid_from_primary_key, &cferror); + }); + + if(updateSuccess) { + [self onboardItemToCKKS:new_item error:&itemError]; + } else { + ckksnotice("ckksscan", self.deps.zoneID, "Unable to update item with new UUID: %@", cferror); + } + + ok &= updateSuccess; + }); + + ok &= query_notify_and_destroy(q, ok, &cferror); + + return true; + }); - [ckks dispatchSyncWithAccountKeys: ^bool{ - if(self.cancelled) { - ckksnotice("ckksscan", ckks, "CKKSScanLocalItemsOperation cancelled, quitting"); - return false; + if(!connectionSuccess) { + ckkserror("ckksscan", self.deps.zoneID, "couldn't execute query: %@", cferror); + SecTranslateError(&itemError, cferror); + self.error = itemError; + return CKKSDatabaseTransactionRollback; + } } - ckks.lastScanLocalItemsOperation = self; - NSMutableArray* itemsForManifest = [NSMutableArray array]; + return CKKSDatabaseTransactionCommit; + }]; +} + +- (void)retriggerMissingMirrorEntires:(NSSet*)mirrorUUIDs + ckks:(CKKSKeychainView*)ckks + databaseProvider:(id)databaseProvider +{ + if (mirrorUUIDs.count > 0) { + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + ckkserror("ckksscan", self.deps.zoneID, "BUG: keychain missing %lu items from mirror and/or queues: %@", (unsigned long)mirrorUUIDs.count, mirrorUUIDs); + self.missingLocalItemsFound = mirrorUUIDs.count; + + [[CKKSAnalytics logger] logMetric:[NSNumber numberWithUnsignedInteger:mirrorUUIDs.count] withName:CKKSEventMissingLocalItemsFound]; + + for (NSString* uuid in mirrorUUIDs) { + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid zoneID:self.deps.zoneID error:&error]; + if(!ckme || error) { + ckkserror("ckksscan", self.deps.zoneID, "BUG: error fetching previously-extant CKME (uuid: %@) from database: %@", uuid, error); + self.error = error; + } else { + [ckks _onqueueCKRecordChanged:ckme.item.storedCKRecord resync:true]; + } + } + + // And, if you're not in the tests, try to collect a sysdiagnose I guess? + // Re-enable IMCore autosysdiagnose capture to securityd + //if(SecIsInternalRelease() && !SecCKKSTestsEnabled()) { + // [[IMCloudKitHooks sharedInstance] tryToAutoCollectLogsWithErrorString:@"35810558" sendLogsTo:@"rowdy_bot@icloud.com"]; + //} + return CKKSDatabaseTransactionCommit; + }]; + } else { + ckksnotice("ckksscan", self.deps.zoneID,"No missing local items found"); + } +} + +- (void)main +{ + if(SecCKKSTestsEnabled() && SecCKKSTestSkipScan()) { + ckksnotice("ckksscan", self.deps.zoneID, "Scan cancelled by test request"); + return; + } + + // We need to not be jetsamed while running this + os_transaction_t transaction = os_transaction_create([[NSString stringWithFormat:@"com.apple.securityd.ckks.scan.%@", self.deps.zoneID] UTF8String]); + + id databaseProvider = self.deps.databaseProvider; + CKKSKeychainView* ckks = self.ckks; + + [self.deps.launch addEvent:@"scan-local-items"]; + + // A map of ItemClass -> Set of found UUIDs + NSMutableDictionary*>* itemUUIDsNotYetInCKKS = [NSMutableDictionary dictionary]; + + // A list of primary keys of items that fit in this view, but have no UUIDs + NSMutableSet* primaryKeysWithNoUUIDs = [NSMutableSet set]; + + // We want this set to be empty after scanning, or else the keychain (silently) dropped something on the floor + NSMutableSet* mirrorUUIDs = [NSMutableSet set]; + + [databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{ // First, query for all synchronizable items - __block CFErrorRef cferror = NULL; __block NSError* error = nil; - __block bool newEntries = false; - // We want this set to be empty after scanning, or else the keychain (silently) dropped something on the floor - NSMutableSet* mirrorUUIDs = [NSMutableSet setWithArray:[CKKSMirrorEntry allUUIDs:ckks.zoneID error:&error]]; + [mirrorUUIDs addObjectsFromArray:[CKKSMirrorEntry allUUIDs:self.deps.zoneID error:&error]]; // Must query per-class, so: const SecDbSchema *newSchema = current_schema(); for (const SecDbClass *const *class = newSchema->classes; *class != NULL; class++) { - cferror = NULL; - if(!((*class)->itemclass)) { // Don't try to scan non-item 'classes' continue; } - // As a performance optimization, if the current policy says that this view only includes items by viewhint, - // add that to the query. - BOOL limitToViewHint = [self policyRecommendsOnlyViewHintItems:ckks]; + NSString* itemClass = (__bridge NSString*)(*class)->name; NSMutableDictionary* queryAttributes = [ - @{(__bridge NSString*) kSecClass: (__bridge NSString*) (*class)->name, - (__bridge NSString*) kSecReturnRef: @(YES), - (__bridge NSString*) kSecAttrSynchronizable: @(YES), - (__bridge NSString*) kSecAttrTombstone: @(NO), + @{(__bridge NSString*)kSecClass: itemClass, + (__bridge NSString*)kSecReturnRef: @(YES), + (__bridge NSString*)kSecAttrSynchronizable: @(YES), + (__bridge NSString*)kSecAttrTombstone: @(NO), } mutableCopy]; - if(limitToViewHint) { - queryAttributes[(__bridge NSString*)kSecAttrSyncViewHint] = ckks.zoneName; - } - - ckksnotice("ckksscan", ckks, "Scanning all synchronizable %@ items(%@) for: %@", (__bridge NSString*)(*class)->name, self.name, queryAttributes); - - Query *q = query_create_with_limit( (__bridge CFDictionaryRef) queryAttributes, NULL, kSecMatchUnlimited, &cferror); - bool ok = false; + NSDictionary* extraQueryPredicates = [self queryPredicatesForViewMapping]; + [queryAttributes addEntriesFromDictionary:extraQueryPredicates]; - if(cferror) { - ckkserror("ckksscan", ckks, "couldn't create query: %@", cferror); - SecTranslateError(&error, cferror); - self.error = error; - continue; - } + ckksnotice("ckksscan", self.deps.zoneID, "Scanning all synchronizable %@ items(%@) for: %@", itemClass, self.name, queryAttributes); - ok = kc_with_dbt(true, &cferror, ^(SecDbConnectionRef dbt) { - return SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef item, bool *stop) { - ckksnotice("ckksscan", ckks, "scanning item: %@", item); + [self executeQuery:queryAttributes readWrite:false error:&error block:^(SecDbItemRef item) { + ckksnotice("ckksscan", self.deps.zoneID, "scanning item: %@", item); - self.processedItems += 1; + self.processedItems += 1; - SecDbItemRef itemToSave = NULL; - - // First check: is this a tombstone? If so, skip with prejudice. - if(SecDbItemIsTombstone(item)) { - ckksinfo("ckksscan", ckks, "Skipping tombstone %@", item); - return; - } + // First check: is this a tombstone? If so, skip with prejudice. + if(SecDbItemIsTombstone(item)) { + ckksinfo("ckksscan", self.deps.zoneID, "Skipping tombstone %@", item); + return; + } - // Second check: is this item even for this view? If not, skip. - NSString* viewForItem = [[CKKSViewManager manager] viewNameForItem:item]; - if(![viewForItem isEqualToString: ckks.zoneName]) { - ckksinfo("ckksscan", ckks, "Scanned item is for view %@, skipping", viewForItem); - return; - } + // Second check: is this item a CKKS key for a view? If so, skip. + if([CKKSKey isItemKeyForKeychainView:item] != nil) { + ckksinfo("ckksscan", self.deps.zoneID, "Scanned item is a CKKS internal key, skipping"); + return; + } - // Third check: is this item one of our keys for a view? If not, skip. - if([CKKSKey isItemKeyForKeychainView: item] != nil) { - ckksinfo("ckksscan", ckks, "Scanned item is a CKKS internal key, skipping"); - return; - } + // Third check: What view is this for? + NSString* viewForItem = [[CKKSViewManager manager] viewNameForItem:item]; + if(![viewForItem isEqualToString:self.deps.zoneID.zoneName]) { + ckksinfo("ckksscan", self.deps.zoneID, "Scanned item is for view %@, skipping", viewForItem); + return; + } - // Fourth check: does this item have a UUID? If not, ONBOARD! - NSString* uuid = (__bridge_transfer NSString*) CFRetain(SecDbItemGetValue(item, &v10itemuuid, &cferror)); - if(!uuid || [uuid isEqual: [NSNull null]]) { - ckksnotice("ckksscan", ckks, "making new UUID for item %@", item); - - uuid = [[NSUUID UUID] UUIDString]; - NSDictionary* updates = @{(id) kSecAttrUUID: uuid}; - - SecDbItemRef new_item = SecDbItemCopyWithUpdates(item, (__bridge CFDictionaryRef) updates, &cferror); - if(SecErrorGetOSStatus(cferror) != errSecSuccess) { - ckkserror("ckksscan", ckks, "couldn't update item with new UUID: %@", cferror); - SecTranslateError(&error, cferror); - self.error = error; - CFReleaseNull(new_item); - return; - } - - if (new_item) { - bool ok = kc_transaction_type(dbt, kSecDbExclusiveRemoteCKKSTransactionType, &cferror, ^{ - return SecDbItemUpdate(item, new_item, dbt, kCFBooleanFalse, q->q_uuid_from_primary_key, &cferror); - }); - - if(!ok || SecErrorGetOSStatus(cferror) != errSecSuccess) { - ckkserror("ckksscan", ckks, "couldn't update item with new UUID: %@", cferror); - SecTranslateError(&error, cferror); - self.error = error; - CFReleaseNull(new_item); - return; - } - } - itemToSave = CFRetainSafe(new_item); - CFReleaseNull(new_item); + // Fourth check: does this item have a UUID? If not, mark for later onboarding. + CFErrorRef cferror = NULL; - } else { - // Is there a known sync item with this UUID? - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: uuid zoneID:ckks.zoneID error: &error]; - if(ckme != nil) { - if ([CKKSManifest shouldSyncManifests]) { - [itemsForManifest addObject:ckme.item]; - } - [mirrorUUIDs removeObject:uuid]; - ckksinfo("ckksscan", ckks, "Existing mirror entry with UUID %@", uuid); - - if([self areEquivalent:item ckksItem:ckme.item]) { - // Fair enough. - return; - } else { - ckksnotice("ckksscan", ckks, "Existing mirror entry with UUID %@ does not match local item", uuid); - } - } - - // We don't care about the oqe state here, just that one exists - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase: uuid zoneID:ckks.zoneID error: &error]; - if(oqe != nil) { - ckksnotice("ckksscan", ckks, "Existing outgoing queue entry with UUID %@", uuid); - // If its state is 'new', mark down that we've seen new entries that need processing - newEntries |= !![oqe.state isEqualToString: SecCKKSStateNew]; - return; - } - - itemToSave = CFRetainSafe(item); - } + NSString* uuid = (__bridge_transfer NSString*) CFRetain(SecDbItemGetValue(item, &v10itemuuid, &cferror)); + if(!uuid || [uuid isEqual: [NSNull null]]) { + ckksnotice("ckksscan", self.deps.zoneID, "making new UUID for item %@: %@", item, cferror); - // Hurray, we can help! - self.recordsFound += 1; + NSMutableDictionary* primaryKey = [(NSDictionary*)CFBridgingRelease(SecDbItemCopyPListWithMask(item, kSecDbPrimaryKeyFlag, &cferror)) mutableCopy]; - CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry withItem: itemToSave action: SecCKKSActionAdd ckks:ckks error: &error]; + // Class is an important part of a primary key, SecDb + primaryKey[(id)kSecClass] = itemClass; - if(error) { - ckkserror("ckksscan", ckks, "Need to upload %@, but can't create outgoing entry: %@", item, error); + if(SecErrorGetOSStatus(cferror) != errSecSuccess) { + ckkserror("ckksscan", self.deps.zoneID, "couldn't copy UUID-less item's primary key: %@", cferror); + SecTranslateError(&error, cferror); self.error = error; - CFReleaseNull(itemToSave); return; } - ckksnotice("ckksscan", ckks, "Syncing new item: %@", oqe); - CFReleaseNull(itemToSave); + [primaryKeysWithNoUUIDs addObject:primaryKey]; + return; + } - [oqe saveToDatabase: &error]; - if(error) { - ckkserror("ckksscan", ckks, "Need to upload %@, but can't save to database: %@", oqe, error); - self.error = error; + // Is there a known sync item with this UUID? + CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid + zoneID:self.deps.zoneID + error:&error]; + if(ckme != nil) { + [mirrorUUIDs removeObject:uuid]; + ckksinfo("ckksscan", self.deps.zoneID, "Existing mirror entry with UUID %@", uuid); + + if([self areEquivalent:item ckksItem:ckme.item]) { + // Fair enough. return; + } else { + ckksnotice("ckksscan", self.deps.zoneID, "Existing mirror entry with UUID %@ does not match local item", uuid); } - newEntries = true; - if ([CKKSManifest shouldSyncManifests]) { - [itemsForManifest addObject:oqe.item]; - } - - self.recordsAdded += 1; - }); - }); + } - if(cferror || !ok) { - ckkserror("ckksscan", ckks, "error processing or finding items: %@", cferror); - SecTranslateError(&error, cferror); - self.error = error; - query_destroy(q, NULL); - continue; - } + // We don't care about the oqe state here, just that one exists + CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase:uuid + zoneID:self.deps.zoneID + error:&error]; + if(oqe != nil) { + ckksnotice("ckksscan", self.deps.zoneID, "Existing outgoing queue entry with UUID %@", uuid); + // If its state is 'new', mark down that we've seen new entries that need processing + self.newCKKSEntries |= !![oqe.state isEqualToString:SecCKKSStateNew]; + return; + } - ok = query_notify_and_destroy(q, ok, &cferror); + // Hurray, we can help! + ckksnotice("ckksscan", self.deps.zoneID, "Item(%@) is new; will attempt to add to CKKS", uuid); + self.recordsFound += 1; - if(cferror || !ok) { - ckkserror("ckksscan", ckks, "couldn't delete query: %@", cferror); - SecTranslateError(&error, cferror); - self.error = error; - continue; - } + NSMutableSet* classUUIDs = itemUUIDsNotYetInCKKS[itemClass]; + if(!classUUIDs) { + classUUIDs = [NSMutableSet set]; + itemUUIDsNotYetInCKKS[itemClass] = classUUIDs; + } + [classUUIDs addObject:uuid]; + }]; } - // We're done checking local keychain for extra items, now let's make sure the mirror doesn't have extra items, either + // We're done checking local keychain for extra items, now let's make sure the mirror doesn't have extra items that the keychain doesn't have, either if (mirrorUUIDs.count > 0) { - ckksnotice("ckksscan", ckks, "keychain missing %lu items from mirror, proceeding with queue scanning", (unsigned long)mirrorUUIDs.count); - [mirrorUUIDs minusSet:[NSSet setWithArray:[CKKSIncomingQueueEntry allUUIDs:ckks.zoneID error:&error]]]; + ckksnotice("ckksscan", self.deps.zoneID, "keychain missing %lu items from mirror, proceeding with queue scanning", (unsigned long)mirrorUUIDs.count); + [mirrorUUIDs minusSet:[NSSet setWithArray:[CKKSIncomingQueueEntry allUUIDs:self.deps.zoneID error:&error]]]; if (error) { - ckkserror("ckksscan", ckks, "unable to inspect incoming queue: %@", error); + ckkserror("ckksscan", self.deps.zoneID, "unable to inspect incoming queue: %@", error); self.error = error; - return false; + return; } - [mirrorUUIDs minusSet:[NSSet setWithArray:[CKKSOutgoingQueueEntry allUUIDs:ckks.zoneID error:&error]]]; + [mirrorUUIDs minusSet:[NSSet setWithArray:[CKKSOutgoingQueueEntry allUUIDs:self.deps.zoneID error:&error]]]; if (error) { - ckkserror("ckksscan", ckks, "unable to inspect outgoing queue: %@", error); + ckkserror("ckksscan", self.deps.zoneID, "unable to inspect outgoing queue: %@", error); self.error = error; - return false; + return; } + } - if (mirrorUUIDs.count > 0) { - ckkserror("ckksscan", ckks, "BUG: keychain missing %lu items from mirror and/or queues: %@", (unsigned long)mirrorUUIDs.count, mirrorUUIDs); - self.missingLocalItemsFound = mirrorUUIDs.count; + // Drop off of read-only transaction + }]; - [[CKKSAnalytics logger] logMetric:[NSNumber numberWithUnsignedInteger:mirrorUUIDs.count] withName:CKKSEventMissingLocalItemsFound]; + if(self.error) { + ckksnotice("ckksscan", self.deps.zoneID, "Exiting due to previous error: %@", self.error); + return; + } - for (NSString* uuid in mirrorUUIDs) { - CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid zoneID:ckks.zoneID error:&error]; - [ckks _onqueueCKRecordChanged:ckme.item.storedCKRecord resync:true]; - } + ckksnotice("ckksscan", self.deps.zoneID, "Found %d item classes with missing items", (int)itemUUIDsNotYetInCKKS.count); - // And, if you're not in the tests, try to collect a sysdiagnose I guess? - // Re-enable IMCore autosysdiagnose capture to securityd - //if(SecIsInternalRelease() && !SecCKKSTestsEnabled()) { - // [[IMCloudKitHooks sharedInstance] tryToAutoCollectLogsWithErrorString:@"35810558" sendLogsTo:@"rowdy_bot@icloud.com"]; - //} - } else { - ckksnotice("ckksscan", ckks, "No missing local items found"); - } - } + for(NSString* itemClass in [itemUUIDsNotYetInCKKS allKeys]) { + [self onboardItemsWithUUIDs:itemUUIDsNotYetInCKKS[itemClass] itemClass:itemClass databaseProvider:databaseProvider]; + } - [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventScanLocalItems zone:ckks.zoneName count:self.processedItems]; + [self fixUUIDlessItemsWithPrimaryKeys:primaryKeysWithNoUUIDs databaseProvider:databaseProvider]; - if ([CKKSManifest shouldSyncManifests]) { - // TODO: this manifest needs to incorporate peer manifests - CKKSEgoManifest* manifest = [CKKSEgoManifest newManifestForZone:ckks.zoneName withItems:itemsForManifest peerManifestIDs:@[] currentItems:@{} error:&error]; - if (!manifest || error) { - ckkserror("ckksscan", ckks, "could not create manifest: %@", error); - self.error = error; - return false; - } + [self retriggerMissingMirrorEntires:mirrorUUIDs + ckks:ckks + databaseProvider:databaseProvider]; - [manifest saveToDatabase:&error]; - if (error) { - ckkserror("ckksscan", ckks, "could not save manifest to database: %@", error); - self.error = error; - return false; - } + [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventScanLocalItems zone:self.deps.zoneID.zoneName count:self.processedItems]; - ckks.egoManifest = manifest; - } + // Write down that a scan occurred + [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + CKKSZoneStateEntry* zoneState = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName]; - if(newEntries) { - // Schedule a "view changed" notification - [ckks.notifyViewChangedScheduler trigger]; + zoneState.lastLocalKeychainScanTime = [NSDate now]; - // notify CKKS that it should process these new entries - [ckks processOutgoingQueue:self.ckoperationGroup]; - } + NSError* saveError = nil; + [zoneState saveToDatabase:&saveError]; - if(self.missingLocalItemsFound > 0) { - [ckks processIncomingQueue:false]; + if(saveError) { + ckkserror("ckksscan", self.deps.zoneID, "Unable to save 'scanned' bit: %@", saveError); + } else { + ckksnotice("ckksscan", self.deps.zoneID, "Saved scanned status."); } - ckksnotice("ckksscan", ckks, "Completed scan"); - ckks.droppedItems = false; - return true; + return CKKSDatabaseTransactionCommit; }]; + + if(self.newCKKSEntries) { + // Schedule a "view changed" notification + [self.deps.notifyViewChangedScheduler trigger]; + + // notify CKKS that it should process these new entries + [ckks processOutgoingQueue:self.ckoperationGroup]; + // TODO: self.nextState = SecCKKSZoneKeyStateProcessOutgoingQueue; + } else { + self.nextState = self.intendedState; + } + + if(self.missingLocalItemsFound > 0) { + [ckks processIncomingQueue:false]; + // TODO [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagProcessIncomingQueue]; + } + + ckksnotice("ckksscan", self.deps.zoneID, "Completed scan"); + (void)transaction; } - (BOOL)areEquivalent:(SecDbItemRef)item ckksItem:(CKKSItem*)ckksItem { - CKKSKeychainView* ckks = self.ckks; - NSError* localerror = nil; NSDictionary* attributes = [CKKSIncomingQueueOperation decryptCKKSItemToAttributes:ckksItem error:&localerror]; if(!attributes || localerror) { - ckksnotice("ckksscan", ckks, "Could not decrypt item for comparison: %@", localerror); + ckksnotice("ckksscan", self.deps.zoneID, "Could not decrypt item for comparison: %@", localerror); return YES; } @@ -406,7 +570,7 @@ localerror = (NSError*)CFBridgingRelease(cferror); if(!objdict || localerror) { - ckksnotice("ckksscan", ckks, "Could not get item contents for comparison: %@", localerror); + ckksnotice("ckksscan", self.deps.zoneID, "Could not get item contents for comparison: %@", localerror); // Fail open: assert that this item doesn't match return NO; diff --git a/keychain/ckks/CKKSStates.h b/keychain/ckks/CKKSStates.h new file mode 100644 index 00000000..9ec50e1a --- /dev/null +++ b/keychain/ckks/CKKSStates.h @@ -0,0 +1,50 @@ + +#if OCTAGON + +#import +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ot/OctagonStateMachine.h" + +NS_ASSUME_NONNULL_BEGIN + +// Flag initialization +typedef OctagonFlag CKKSFlag; + +// The set of trusted peers has changed +extern CKKSFlag* const CKKSFlagTrustedPeersSetChanged; + +// A client has requested that TLKs be created +extern CKKSFlag* const CKKSFlagTLKCreationRequested; +// We were waiting for a TLK upload, and one has occurred +extern CKKSFlag* const CKKSFlagKeyStateTLKsUploaded; + +extern CKKSFlag* const CKKSFlagCloudKitLoggedIn; +extern CKKSFlag* const CKKSFlagCloudKitLoggedOut; + +extern CKKSFlag* const CKKSFlagBeginTrustedOperation; +extern CKKSFlag* const CKKSFlagEndTrustedOperation; + +extern CKKSFlag* const CKKSFlagChangeTokenExpired; +extern CKKSFlag* const CKKSFlagCloudKitZoneMissing; + +extern CKKSFlag* const CKKSFlagDeviceUnlocked; + +extern CKKSFlag* const CKKSFlagFetchRequested; +// Added when a key hierarchy fetch completes. +extern CKKSFlag* const CKKSFlagFetchComplete; + +extern CKKSFlag* const CKKSFlagKeyStateProcessRequested; + +extern CKKSFlag* const CKKSFlagProcessIncomingQueue; +extern CKKSFlag* const CKKSFlagProcessOutgoingQueue; +extern CKKSFlag* const CKKSFlagScanLocalItems; +extern CKKSFlag* const CKKSFlagItemReencryptionNeeded; + +extern CKKSFlag* const CKKSFlag24hrNotification; + +NSSet* CKKSAllStateFlags(void); + +NS_ASSUME_NONNULL_END + +#endif diff --git a/keychain/ckks/CKKSStates.m b/keychain/ckks/CKKSStates.m new file mode 100644 index 00000000..5eb3b4a2 --- /dev/null +++ b/keychain/ckks/CKKSStates.m @@ -0,0 +1,65 @@ + +#if OCTAGON + +#import "keychain/ckks/CKKSStates.h" +#import "keychain/ckks/CKKSKeychainView.h" +#import "keychain/ot/ObjCImprovements.h" + +CKKSFlag* const CKKSFlagTrustedPeersSetChanged = (CKKSFlag*) @"trusted_peers_changed"; + +CKKSFlag* const CKKSFlagTLKCreationRequested = (CKKSFlag*)@"tlk_creation"; +CKKSFlag* const CKKSFlagKeyStateTLKsUploaded = (CKKSFlag*)@"tlks_uploaded"; + +CKKSFlag* const CKKSFlagCloudKitLoggedIn = (CKKSFlag*)@"ck_account_logged_in"; +CKKSFlag* const CKKSFlagCloudKitLoggedOut = (CKKSFlag*)@"ck_account_logged_out"; + +CKKSFlag* const CKKSFlagBeginTrustedOperation = (CKKSFlag*)@"trusted_operation_begin"; +CKKSFlag* const CKKSFlagEndTrustedOperation = (CKKSFlag*)@"trusted_operation_end"; + +CKKSFlag* const CKKSFlagChangeTokenExpired = (CKKSFlag*)@"ck_change_token_expired"; +CKKSFlag* const CKKSFlagCloudKitZoneMissing = (CKKSFlag*)@"ck_zone_missing"; + +CKKSFlag* const CKKSFlagDeviceUnlocked = (CKKSFlag*)@"device_unlocked"; + +CKKSFlag* const CKKSFlagFetchRequested = (CKKSFlag*) @"fetch_requested"; +CKKSFlag* const CKKSFlagFetchComplete = (CKKSFlag*)@"fetch_complete"; + +CKKSFlag* const CKKSFlagKeyStateProcessRequested = (CKKSFlag*) @"key_process_requested"; + +CKKSFlag* const CKKSFlagProcessIncomingQueue = (CKKSFlag*)@"process_incoming_queue"; +CKKSFlag* const CKKSFlagProcessOutgoingQueue = (CKKSFlag*)@"process_outgoing_queue"; +CKKSFlag* const CKKSFlagScanLocalItems = (CKKSFlag*)@"dropped_items"; +CKKSFlag* const CKKSFlagItemReencryptionNeeded = (CKKSFlag*)@"item_reencryption_needed"; + +CKKSFlag* const CKKSFlag24hrNotification = (CKKSFlag*)@"24_hr_notification"; + +NSSet* CKKSAllStateFlags(void) +{ + static NSSet* s = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + s = [NSSet setWithArray:@[ + CKKSFlagFetchRequested, + CKKSFlagKeyStateProcessRequested, + CKKSFlagTrustedPeersSetChanged, + CKKSFlagTLKCreationRequested, + CKKSFlagScanLocalItems, + CKKSFlagCloudKitLoggedIn, + CKKSFlagCloudKitLoggedOut, + CKKSFlagCloudKitZoneMissing, + CKKSFlagChangeTokenExpired, + CKKSFlagProcessIncomingQueue, + CKKSFlagProcessOutgoingQueue, + CKKSFlagItemReencryptionNeeded, + CKKSFlagBeginTrustedOperation, + CKKSFlagEndTrustedOperation, + CKKSFlagDeviceUnlocked, + CKKSFlagKeyStateTLKsUploaded, + CKKSFlagFetchComplete, + CKKSFlag24hrNotification, + ]]; + }); + return s; +} + +#endif diff --git a/keychain/ckks/CKKSSynchronizeOperation.m b/keychain/ckks/CKKSSynchronizeOperation.m index f507bcb6..a6e7424d 100644 --- a/keychain/ckks/CKKSSynchronizeOperation.m +++ b/keychain/ckks/CKKSSynchronizeOperation.m @@ -76,10 +76,10 @@ CKKSKeychainView* ckks = self.ckks; // Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety. - [ckks dispatchSync: ^bool{ + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { ckksnotice("ckksresync", ckks, "CKKSSynchronizeOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } ckks.lastSynchronizeOperation = self; @@ -102,13 +102,23 @@ [self runBeforeGroupFinished: fetchOp]; // Step 2 - CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:ckks errorOnClassAFailure:true]; + CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithDependencies:ckks.operationDependencies + ckks:ckks + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateUnhealthy + errorOnClassAFailure:true + handleMismatchedViewItems:false]; + incomingOp.name = [NSString stringWithFormat: @"resync-step%u-incoming", self.restartCount * steps + 2]; [incomingOp addSuccessDependency:fetchOp]; [self runBeforeGroupFinished:incomingOp]; // Step 3 - CKKSScanLocalItemsOperation* scan = [[CKKSScanLocalItemsOperation alloc] initWithCKKSKeychainView:ckks ckoperationGroup:operationGroup]; + CKKSScanLocalItemsOperation* scan = [[CKKSScanLocalItemsOperation alloc] initWithDependencies:ckks.operationDependencies + ckks:ckks + intending:SecCKKSZoneKeyStateReady + errorState:SecCKKSZoneKeyStateError + ckoperationGroup:operationGroup]; scan.name = [NSString stringWithFormat: @"resync-step%u-scan", self.restartCount * steps + 3]; [scan addSuccessDependency: incomingOp]; [self runBeforeGroupFinished: scan]; @@ -117,6 +127,7 @@ CKKSOutgoingQueueOperation* outgoingOp = [ckks processOutgoingQueue: operationGroup]; outgoingOp.name = [NSString stringWithFormat: @"resync-step%u-outgoing", self.restartCount * steps + 4]; [self dependOnBeforeGroupFinished:outgoingOp]; + [outgoingOp addDependency:scan]; // Step 5: CKKSResultOperation* restart = [[CKKSResultOperation alloc] init]; @@ -124,7 +135,7 @@ [restart addExecutionBlock:^{ STRONGIFY(self); if(!self) { - secerror("ckksresync: received callback for released object"); + ckkserror("ckksresync", ckks, "received callback for released object"); return; } @@ -147,7 +158,7 @@ [restart addSuccessDependency: outgoingOp]; [self runBeforeGroupFinished: restart]; - return true; + return CKKSDatabaseTransactionCommit; }]; } diff --git a/keychain/ckks/CKKSTLKShare.h b/keychain/ckks/CKKSTLKShare.h index eb4de292..29753d6a 100644 --- a/keychain/ckks/CKKSTLKShare.h +++ b/keychain/ckks/CKKSTLKShare.h @@ -75,7 +75,7 @@ typedef NS_ENUM(NSUInteger, SecCKKSTLKShareVersion) { - (instancetype)initForKey:(NSString*)tlkUUID senderPeerID:(NSString*)senderPeerID recieverPeerID:(NSString*)receiverPeerID - receiverEncPublicKeySPKI:(NSData*)publicKeySPKI + receiverEncPublicKeySPKI:(NSData* _Nullable)publicKeySPKI curve:(SFEllipticCurve)curve version:(SecCKKSTLKShareVersion)version epoch:(NSInteger)epoch diff --git a/keychain/ckks/CKKSTLKShare.m b/keychain/ckks/CKKSTLKShare.m index f1019b9f..281f1ead 100644 --- a/keychain/ckks/CKKSTLKShare.m +++ b/keychain/ckks/CKKSTLKShare.m @@ -69,7 +69,7 @@ - (instancetype)initForKey:(NSString*)tlkUUID senderPeerID:(NSString*)senderPeerID recieverPeerID:(NSString*)receiverPeerID - receiverEncPublicKeySPKI:(NSData*)publicKeySPKI + receiverEncPublicKeySPKI:(NSData* _Nullable)publicKeySPKI curve:(SFEllipticCurve)curve version:(SecCKKSTLKShareVersion)version epoch:(NSInteger)epoch @@ -248,7 +248,7 @@ error:(NSError* __autoreleasing*)error { if(!peer.publicSigningKey) { - secerror("ckksshare: no signing key for peer: %@", peer); + ckkserror("ckksshare", self.zoneID, "no signing key for peer: %@", peer); if(error) { *error = [NSError errorWithDomain:CKKSErrorDomain @@ -283,7 +283,7 @@ ckrecord:ckrecord error:&localerror]; if(localerror) { - secerror("ckksshare: signature didn't verify for %@ %@: %@", self, peer, localerror); + ckkserror("ckksshare", self.zoneID, "signature didn't verify for %@ %@: %@", self, peer, localerror); lastVerificationError = localerror; } if(isSigned) { @@ -345,8 +345,7 @@ - (nullable instancetype)initWithCoder:(nonnull NSCoder*)decoder { - self = [super init]; - if(self) { + if ((self = [super init])) { _zoneID = [decoder decodeObjectOfClass:[CKRecordZoneID class] forKey:@"zoneID"]; _curve = (SFEllipticCurve) [decoder decodeInt64ForKey:@"curve"]; _version = (SecCKKSTLKShareVersion)[decoder decodeInt64ForKey:@"version"]; @@ -405,7 +404,7 @@ share.wrappedTLK = [share wrap:key publicKey:receiver.publicEncryptionKey error:&localerror]; if(localerror) { - secerror("ckksshare: couldn't share %@ (wrap failed): %@", key, localerror); + ckkserror("ckksshare", key.zoneID, "couldn't share %@ (wrap failed): %@", key, localerror); if(error) { *error = localerror; } @@ -416,7 +415,7 @@ ckrecord:nil error:&localerror]; if(localerror) { - secerror("ckksshare: couldn't share %@ (signing failed): %@", key, localerror); + ckkserror("ckksshare", key.zoneID, "couldn't share %@ (signing failed): %@", key, localerror); if(error) { *error = localerror; } diff --git a/keychain/ckks/CKKSTLKShareRecord.m b/keychain/ckks/CKKSTLKShareRecord.m index ac6ee5ad..9b1d1a38 100644 --- a/keychain/ckks/CKKSTLKShareRecord.m +++ b/keychain/ckks/CKKSTLKShareRecord.m @@ -220,7 +220,7 @@ zoneID:key.zoneID error:&localerror]; if(localerror) { - secerror("ckksshare: couldn't load old share for %@: %@", key, localerror); + ckkserror("ckksshare", key.zoneID, "couldn't load old share for %@: %@", key, localerror); if(error) { *error = localerror; } diff --git a/keychain/ckks/CKKSUpdateCurrentItemPointerOperation.m b/keychain/ckks/CKKSUpdateCurrentItemPointerOperation.m index 00080ba2..f087686b 100644 --- a/keychain/ckks/CKKSUpdateCurrentItemPointerOperation.m +++ b/keychain/ckks/CKKSUpdateCurrentItemPointerOperation.m @@ -101,10 +101,10 @@ WEAKIFY(self); - [ckks dispatchSyncWithAccountKeys:^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ if(self.cancelled) { ckksnotice("ckkscurrent", ckks, "CKKSUpdateCurrentItemPointerOperation cancelled, quitting"); - return false; + return CKKSDatabaseTransactionRollback; } NSError* error = nil; @@ -117,7 +117,7 @@ if(!self.newItem || error) { ckksnotice("ckkscurrent", ckks, "Couldn't fetch new item, quitting: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } // Now that we're on the db queue, ensure that the given hashes for the items match the hashes as they are now. @@ -130,14 +130,14 @@ code:CKKSItemChanged description:@"New item has changed; hashes mismatch. Refetch and try again." underlying:(NSError*)CFBridgingRelease(cferror)]; - return false; + return CKKSDatabaseTransactionRollback; } newItemUUID = (NSString*) CFBridgingRelease(CFRetainSafe(SecDbItemGetValue(self.newItem, &v10itemuuid, &cferror))); if(!newItemUUID || cferror) { ckkserror("ckkscurrent", ckks, "Error fetching UUID for new item: %@", cferror); self.error = (NSError*) CFBridgingRelease(cferror); - return false; + return CKKSDatabaseTransactionRollback; } // If the old item is nil, that's an indicator that the old item isn't expected to exist in the keychain anymore @@ -147,7 +147,7 @@ if(!self.oldItem || error) { ckksnotice("ckkscurrent", ckks, "Couldn't fetch old item, quitting: %@", error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } oldCurrentItemHash = (NSData*) CFBridgingRelease(CFRetainSafe(SecDbItemGetSHA1(self.oldItem, &cferror))); @@ -158,14 +158,14 @@ code:CKKSItemChanged description:@"Old item has changed; hashes mismatch. Refetch and try again." underlying:(NSError*)CFBridgingRelease(cferror)]; - return false; + return CKKSDatabaseTransactionRollback; } oldCurrentItemUUID = (NSString*) CFBridgingRelease(CFRetainSafe(SecDbItemGetValue(self.oldItem, &v10itemuuid, &cferror))); if(!oldCurrentItemUUID || cferror) { ckkserror("ckkscurrent", ckks, "Error fetching UUID for old item: %@", cferror); self.error = (NSError*) CFBridgingRelease(cferror); - return false; + return CKKSDatabaseTransactionRollback; } } @@ -180,7 +180,7 @@ code:CKKSRemoteItemChangePending description:[NSString stringWithFormat:@"Update to current item pointer is pending."]]; ckkserror("ckkscurrent", ckks, "Attempt to set a new current item pointer when one exists: %@", self.error); - return false; + return CKKSDatabaseTransactionRollback; } CKKSCurrentItemPointer* cip = [CKKSCurrentItemPointer tryFromDatabase:self.currentPointerIdentifier state:SecCKKSProcessedStateLocal zoneID:ckks.zoneID error:&error]; @@ -198,7 +198,7 @@ self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSItemChanged description:[NSString stringWithFormat:@"Current pointer(%@) does not match user-supplied %@, aborting", cip, oldCurrentItemUUID]]; - return false; + return CKKSDatabaseTransactionRollback; } // Cool. Since you know what you're updating, you're allowed to update! cip.currentItemUUID = newItemUUID; @@ -209,7 +209,7 @@ self.error = [NSError errorWithDomain:CKKSErrorDomain code:CKKSItemChanged description:[NSString stringWithFormat:@"Current pointer(%@) does not match given value of '%@', aborting", cip, oldCurrentItemUUID]]; - return false; + return CKKSDatabaseTransactionRollback; } else { // No current item pointer? How exciting! Let's make you a nice new one. cip = [[CKKSCurrentItemPointer alloc] initForIdentifier:self.currentPointerIdentifier @@ -237,7 +237,7 @@ if(error) { ckkserror("ckkscurrent", ckks, "Error attempting to update current item pointer %@: %@", self.currentPointerIdentifier, error); self.error = error; - return false; + return CKKSDatabaseTransactionRollback; } // Make sure the item is synced, though! @@ -250,11 +250,7 @@ underlying:error]; self.error = error; - return false; - } - - if ([CKKSManifest shouldSyncManifests]) { - [ckks.egoManifest setCurrentItemUUID:newItemUUID forIdentifier:self.currentPointerIdentifier]; + return CKKSDatabaseTransactionRollback; } ckksnotice("ckkscurrent", ckks, "Saving new current item pointer %@", cip); @@ -263,12 +259,6 @@ CKRecord* record = [cip CKRecordWithZoneID:ckks.zoneID]; recordsToSave[record.recordID] = record; - if([CKKSManifest shouldSyncManifests]) { - for(CKRecord* record in [ckks.egoManifest allCKRecordsWithZoneID:ckks.zoneID]) { - recordsToSave[record.recordID] = record; - } - } - // Start a CKModifyRecordsOperation to save this new/updated record. NSBlockOperation* modifyComplete = [[NSBlockOperation alloc] init]; modifyComplete.name = @"updateCurrentItemPointer-modifyRecordsComplete"; @@ -311,8 +301,8 @@ ckkserror("ckkscurrent", strongCKKS, "CloudKit returned an error: %@", ckerror); self.error = ckerror; - [strongCKKS dispatchSync:^bool { - return [strongCKKS _onqueueCKWriteFailed:ckerror attemptedRecordsChanged:recordsToSave]; + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + return [strongCKKS _onqueueCKWriteFailed:ckerror attemptedRecordsChanged:recordsToSave] ? CKKSDatabaseTransactionCommit : CKKSDatabaseTransactionRollback; }]; [strongCKKS scheduleOperation: modifyComplete]; @@ -321,7 +311,7 @@ __block NSError* error = nil; - [strongCKKS dispatchSync: ^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for(CKRecord* record in savedRecords) { // Save the item records if([record.recordType isEqualToString: SecCKRecordCurrentItemType]) { @@ -347,7 +337,7 @@ // Schedule a 'view changed' notification [strongCKKS.notifyViewChangedScheduler trigger]; } - return true; + return CKKSDatabaseTransactionCommit; }]; self.error = error; @@ -357,16 +347,17 @@ [self dependOnBeforeGroupFinished: self.modifyRecordsOperation]; [ckks.database addOperation: self.modifyRecordsOperation]; - return true; + return CKKSDatabaseTransactionCommit; }]; } - (SecDbItemRef _Nullable)_onqueueFindSecDbItem:(NSData*)persistentRef accessGroup:(NSString*)accessGroup error:(NSError**)error { + CKKSKeychainView* ckks = self.ckks; + dispatch_assert_queue(ckks.queue); __block SecDbItemRef blockItem = NULL; CFErrorRef cferror = NULL; __block NSError* localerror = NULL; - CKKSKeychainView* ckks = self.ckks; bool ok = kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { // Find the items from their persistent refs. CFErrorRef blockcfError = NULL; @@ -376,6 +367,7 @@ }, NULL, 1, + NULL, &blockcfError); if(blockcfError || !q) { ckkserror("ckkscurrent", ckks, "couldn't create query for item persistentRef: %@", blockcfError); diff --git a/keychain/ckks/CKKSUpdateDeviceStateOperation.m b/keychain/ckks/CKKSUpdateDeviceStateOperation.m index 7905d589..790d364f 100644 --- a/keychain/ckks/CKKSUpdateDeviceStateOperation.m +++ b/keychain/ckks/CKKSUpdateDeviceStateOperation.m @@ -87,13 +87,13 @@ ckkserror("ckksdevice", ckks, "Not quite sure if the account isa HSA2 or not. Probably will quit?"); } - [ckks dispatchSyncWithAccountKeys:^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSDeviceStateEntry* cdse = [ckks _onqueueCurrentDeviceStateEntry:&error]; if(error || !cdse) { ckkserror("ckksdevice", ckks, "Error creating device state entry; quitting: %@", error); - return false; + return CKKSDatabaseTransactionRollback; } if(self.rateLimit) { @@ -116,7 +116,7 @@ self.error = [NSError errorWithDomain:@"securityd" code:errSecInternalError userInfo:@{NSLocalizedDescriptionKey: @"Rate-limited the CKKSUpdateDeviceStateOperation"}]; - return false; + return CKKSDatabaseTransactionRollback; } } @@ -165,7 +165,7 @@ __block NSError* error = nil; - [strongCKKS dispatchSync: ^bool{ + [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for(CKRecord* record in savedRecords) { // Save the item records if([record.recordType isEqualToString: SecCKRecordDeviceStateType]) { @@ -176,7 +176,7 @@ } } } - return true; + return CKKSDatabaseTransactionCommit; }]; self.error = error; @@ -186,7 +186,7 @@ [self dependOnBeforeGroupFinished: self.modifyRecordsOperation]; [ckks.database addOperation: self.modifyRecordsOperation]; - return true; + return CKKSDatabaseTransactionCommit; }]; } diff --git a/keychain/ckks/CKKSViewManager.h b/keychain/ckks/CKKSViewManager.h index f19cccab..6a6b1df8 100644 --- a/keychain/ckks/CKKSViewManager.h +++ b/keychain/ckks/CKKSViewManager.h @@ -41,13 +41,14 @@ #import "keychain/ckks/CloudKitDependencies.h" #import "keychain/ckks/CKKSZoneChangeFetcher.h" #import "keychain/ckks/CKKSZoneModifier.h" +#import "keychain/ckks/CKKSKeychainBackedKey.h" #import "keychain/ot/OTSOSAdapter.h" #import "keychain/ot/OTDefines.h" NS_ASSUME_NONNULL_BEGIN -@class CKKSKeychainView, CKKSRateLimiter, TPPolicy; +@class CKKSKeychainView, CKKSRateLimiter, TPSyncingPolicy; @interface CKKSViewManager : NSObject @@ -65,7 +66,7 @@ NS_ASSUME_NONNULL_BEGIN @property id sosPeerAdapter; -@property (readonly, nullable) TPPolicy* policy; +@property (readonly, nullable) TPSyncingPolicy* policy; @property (readonly) NSMutableDictionary* views; @@ -75,15 +76,22 @@ NS_ASSUME_NONNULL_BEGIN lockStateTracker:(CKKSLockStateTracker*)lockStateTracker cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies; -- (CKKSKeychainView*)findView:(NSString*)viewName; +// Note: findView will not wait for any views to be created. You must handle +// states where the daemon has not entirely started up yourself +- (CKKSKeychainView* _Nullable)findView:(NSString*)viewName; + +// Similar to findView, but will create the view if it's not already present. - (CKKSKeychainView*)findOrCreateView:(NSString*)viewName; + +// findViewOrError will wait for the Syncing Policy to be loaded, which +// creates all views. Don't call this from any important queues. +- (CKKSKeychainView* _Nullable)findView:(NSString*)viewName error:(NSError**)error; + - (void)setView:(CKKSKeychainView*)obj; - (void)clearView:(NSString*)viewName; - (NSSet*)currentViews; -- (NSDictionary*)activeTLKs; - - (void)setupAnalytics; - (NSString* _Nullable)viewNameForItem:(SecDbItemRef)item; @@ -126,7 +134,11 @@ NS_ASSUME_NONNULL_BEGIN // Call this to set the syncing views+policy that this manager will use. // If beginCloudKitOperationOfAllViews has previously been called, then any new views created // as a result of this call will begin CK operation. -- (void)setSyncingViews:(NSSet* _Nullable)viewNames sortingPolicy:(TPPolicy* _Nullable)policy; +- (BOOL)setCurrentSyncingPolicy:(TPSyncingPolicy* _Nullable)syncingPolicy; + +// Similar to above, but please only pass policyIsFresh=YES if Octagon has contacted cuttlefish immediately previously +// Returns YES if the view set has changed as part of this set +- (BOOL)setCurrentSyncingPolicy:(TPSyncingPolicy* _Nullable)syncingPolicy policyIsFresh:(BOOL)policyIsFresh; - (void)clearAllViews; @@ -154,8 +166,12 @@ NS_ASSUME_NONNULL_BEGIN // Checks featureflags to return whether we should use policy-based views, or use the hardcoded list - (BOOL)useCKKSViewsFromPolicy; +// Extract TLKs for sending to some peer. Pass restrictToPolicy=True if you want to restrict the returned TLKs +// to what the current policy indicates (allowing to prioritize transferred TLKs) +- (NSArray* _Nullable)currentTLKsFilteredByPolicy:(BOOL)restrictToPolicy error:(NSError**)error; + // Interfaces to examine sync callbacks -- (SecBoolNSErrorCallback _Nullable)claimCallbackForUUID:(NSString*)uuid; +- (SecBoolNSErrorCallback _Nullable)claimCallbackForUUID:(NSString* _Nullable)uuid; - (NSSet*)pendingCallbackUUIDs; + (void)callSyncCallbackWithErrorNoAccount:(SecBoolNSErrorCallback)syncCallback; @end diff --git a/keychain/ckks/CKKSViewManager.m b/keychain/ckks/CKKSViewManager.m index 3838cc6b..d381ec95 100644 --- a/keychain/ckks/CKKSViewManager.m +++ b/keychain/ckks/CKKSViewManager.m @@ -34,6 +34,7 @@ #import "keychain/ckks/CKKSCondition.h" #import "keychain/ckks/CKKSListenerCollection.h" #import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/OctagonAPSReceiver.h" #import "keychain/categories/NSError+UsefulConstructors.h" #import "keychain/analytics/SecEventMetric.h" #import "keychain/analytics/SecMetrics.h" @@ -43,7 +44,7 @@ #import "keychain/ot/OTConstants.h" #import "keychain/ot/ObjCImprovements.h" -#import "TPPolicy.h" +#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h" #import "SecEntitlements.h" @@ -94,7 +95,8 @@ @property BOOL itemModificationsBeforePolicyLoaded; // Make writable -@property (nullable) TPPolicy* policy; +@property (nullable) TPSyncingPolicy* policy; +@property CKKSCondition* policyLoaded; #endif @end @@ -128,6 +130,9 @@ _zoneChangeFetcher = [[CKKSZoneChangeFetcher alloc] initWithContainer:_container fetchClass:cloudKitClassDependencies.fetchRecordZoneChangesOperationClass reachabilityTracker:_reachabilityTracker]; + OctagonAPSReceiver* globalAPSReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:cloudKitClassDependencies.apsConnectionClass]; + [globalAPSReceiver registerCKKSReceiver:_zoneChangeFetcher]; _zoneModifier = [[CKKSZoneModifier alloc] initWithContainer:_container reachabilityTracker:_reachabilityTracker @@ -155,6 +160,7 @@ }]; _policy = nil; + _policyLoaded = [[CKKSCondition alloc] init]; _listener = [NSXPCListener anonymousListener]; _listener.delegate = self; @@ -210,7 +216,7 @@ NSError* sosCircleError = nil; SOSCCStatus sosStatus = [self.sosPeerAdapter circleStatus:&sosCircleError]; if(sosCircleError) { - secerror("CKKSViewManager: couldn't fetch sos status for SF report: %@", sosCircleError); + ckkserror_global("manager", " couldn't fetch sos status for SF report: %@", sosCircleError); } NSMutableDictionary* values = [NSMutableDictionary dictionary]; @@ -243,14 +249,14 @@ NSError* sosCircleError = nil; SOSCCStatus sosStatus = [self.sosPeerAdapter circleStatus:&sosCircleError]; if(sosCircleError) { - secerror("CKKSViewManager: couldn't fetch sos status for SF report: %@", sosCircleError); + ckkserror_global("manager", " couldn't fetch sos status for SF report: %@", sosCircleError); } BOOL inCircle = (sosStatus == kSOSCCInCircle); NSMutableDictionary* values = [NSMutableDictionary dictionary]; CKKSKeychainView* view = [self findOrCreateView:viewName]; - NSDate* dateOfLastSyncClassA = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassA inView:view]; - NSDate* dateOfLastSyncClassC = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassC inView:view]; - NSDate* dateOfLastKSR = [[CKKSAnalytics logger] datePropertyForKey:CKKSAnalyticsLastKeystateReady inView:view]; + NSDate* dateOfLastSyncClassA = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassA zoneName:view.zoneName]; + NSDate* dateOfLastSyncClassC = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassC zoneName:view.zoneName]; + NSDate* dateOfLastKSR = [[CKKSAnalytics logger] datePropertyForKey:CKKSAnalyticsLastKeystateReady zoneName:view.zoneName]; NSInteger fuzzyDaysSinceClassASync = [CKKSAnalytics fuzzyDaysSinceDate:dateOfLastSyncClassA]; NSInteger fuzzyDaysSinceClassCSync = [CKKSAnalytics fuzzyDaysSinceDate:dateOfLastSyncClassC]; @@ -259,8 +265,8 @@ [values setValue:@(fuzzyDaysSinceClassCSync) forKey:[NSString stringWithFormat:@"%@-daysSinceClassCSync", viewName]]; [values setValue:@(fuzzyDaysSinceKSR) forKey:[NSString stringWithFormat:@"%@-daysSinceLastKeystateReady", viewName]]; - BOOL hasTLKs = [view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateReady] || [view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]; - /* only synced recently if between [0...7, ie withing 7 days */ + BOOL hasTLKs = [view.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateReady] || [view.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]; + /* only synced recently if between [0...7, ie within 7 days */ BOOL syncedClassARecently = fuzzyDaysSinceClassASync >= 0 && fuzzyDaysSinceClassASync < 7; BOOL syncedClassCRecently = fuzzyDaysSinceClassCSync >= 0 && fuzzyDaysSinceClassCSync < 7; BOOL incomingQueueIsErrorFree = view.lastIncomingQueueOperation.error == nil; @@ -314,7 +320,7 @@ dispatch_once_t globalZoneStateQueueOnce; CKKSZoneStateEntry* allEntry = [CKKSZoneStateEntry tryFromDatabase: @"all" error:&error]; if(error) { - secerror("CKKSViewManager: couldn't load global zone state: %@", error); + ckkserror_global("manager", " couldn't load global zone state: %@", error); } if(!error && allEntry.rateLimiter) { @@ -366,56 +372,90 @@ dispatch_once_t globalZoneStateQueueOnce; return [self.views.allKeys copy]; } -- (void)setSyncingViews:(NSSet*)viewNames sortingPolicy:(TPPolicy*)policy +- (BOOL)setCurrentSyncingPolicy:(TPSyncingPolicy* _Nullable)syncingPolicy { - secnotice("ckks-policy", "New syncing policy: %@ views: %@", policy, viewNames); + return [self setCurrentSyncingPolicy:syncingPolicy policyIsFresh:NO]; +} + +- (BOOL)setCurrentSyncingPolicy:(TPSyncingPolicy* _Nullable)syncingPolicy policyIsFresh:(BOOL)policyIsFresh +{ + if(syncingPolicy == nil) { + ckksnotice_global("ckks-policy", "Nil syncing policy presented; ignoring"); + return NO; + } + + NSSet* viewNames = syncingPolicy.viewList; + ckksnotice_global("ckks-policy", "New syncing policy: %@ views: %@", syncingPolicy, viewNames); if(![self useCKKSViewsFromPolicy]) { // Thanks, but no thanks. viewNames = [self defaultViewList]; - secnotice("ckks-policy", "Reverting to default view list: %@", viewNames); + ckksnotice_global("ckks-policy", "Reverting to default view list: %@", viewNames); } if(self.viewAllowList) { - secnotice("ckks-policy", "Intersecting view list with allow list: %@", self.viewAllowList); + ckksnotice_global("ckks-policy", "Intersecting view list with allow list: %@", self.viewAllowList); NSMutableSet* set = [viewNames mutableCopy]; [set intersectSet:self.viewAllowList]; viewNames = set; - secnotice("ckks-policy", "Final list: %@", viewNames); + ckksnotice_global("ckks-policy", "Final list: %@", viewNames); } - self.policy = policy; + // We need to not be synchronized on self.views before issuing commands to CKKS views. + // So, store the pointers for use after the critical section. + NSArray* activeViews = nil; + BOOL scanAll = NO; + BOOL viewsChanged = NO; @synchronized(self.views) { + self.policy = syncingPolicy; + NSArray* previousViewNames = [self.views.allKeys copy]; // First, shut down any views that are no longer in the set for(NSString* viewName in previousViewNames) { if(![viewNames containsObject:viewName]) { - secnotice("ckks-policy", "Stopping old view %@", viewName); + ckksnotice_global("ckks-policy", "Stopping old view %@", viewName); [self clearView:viewName]; + viewsChanged = YES; } } for(NSString* viewName in viewNames) { + CKKSKeychainView* view = nil; + if([previousViewNames containsObject:viewName]) { - CKKSKeychainView* view = [self findView:viewName]; - secnotice("ckks-policy", "Already have view %@", view); + view = [self findView:viewName]; + ckksinfo_global("ckks-policy", "Already have view %@", view); + } else { - CKKSKeychainView* view = [self findOrCreateView:viewName]; - secnotice("ckks-policy", "Created new view %@", view); + view = [self findOrCreateView:viewName]; + ckksnotice_global("ckks-policy", "Created new view %@", view); + viewsChanged = YES; } } + activeViews = [self.views.allValues copy]; + if(self.itemModificationsBeforePolicyLoaded) { - secnotice("ckks-policy", "Issuing scan suggestions to handle missed items"); - for(CKKSKeychainView* view in [self.views allValues]) { - [view scanLocalItems:@"item-added-before-policy"]; - } + ckksnotice_global("ckks-policy", "Issuing scan suggestions to handle missed items"); + scanAll = YES; self.itemModificationsBeforePolicyLoaded = NO; } } + + for(CKKSKeychainView* view in activeViews) { + [view setCurrentSyncingPolicy:self.policy policyIsFresh:policyIsFresh]; + + if(scanAll) { + [view scanLocalItems:@"item-added-before-policy"]; + } + } + + // The policy is considered loaded once the views have been created + [self.policyLoaded fulfill]; + return viewsChanged; } - (void)setSyncingViewsAllowList:(NSSet*)viewNames @@ -425,8 +465,9 @@ dispatch_once_t globalZoneStateQueueOnce; - (void)resetSyncingPolicy { - secnotice("ckks-policy", "Setting policy to nil"); + ckksnotice_global("ckks-policy", "Setting policy to nil"); self.policy = nil; + self.policyLoaded = [[CKKSCondition alloc] init]; self.startCKOperationAtViewCreation = NO; } @@ -476,11 +517,43 @@ dispatch_once_t globalZoneStateQueueOnce; if(!viewName) { return nil; } + @synchronized(self.views) { return self.views[viewName]; } } +- (CKKSKeychainView* _Nullable)findView:(NSString*)viewName error:(NSError**)error +{ + if([self.policyLoaded wait:5*NSEC_PER_SEC] != 0) { + ckkserror_global("ckks", "Haven't yet received a syncing policy; expect failure finding views"); + + if([self useCKKSViewsFromPolicy]) { + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSErrorPolicyNotLoaded + userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"CKKS syncing policy not yet loaded; cannot find view '%@'", viewName]}]; + + } + return nil; + } + } + + @synchronized(self.views) { + CKKSKeychainView* view = self.views[viewName]; + if(!view) { + if(error) { + *error = [NSError errorWithDomain:CKKSErrorDomain + code:CKKSNoSuchView + userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No syncing view for '%@'", viewName]}]; + } + return nil; + } + + return view; + } +} + - (CKKSKeychainView*)findOrCreateView:(NSString*)viewName { @synchronized(self.views) { CKKSKeychainView* kcv = self.views[viewName]; @@ -526,7 +599,7 @@ dispatch_once_t globalZoneStateQueueOnce; (void)view; } } else { - secnotice("ckks-views", "Not loading default view list due to enabled CKKS4All"); + ckksnotice_global("ckks-views", "Not loading default view list due to enabled CKKS4All"); } } @@ -539,21 +612,6 @@ dispatch_once_t globalZoneStateQueueOnce; } } -- (NSDictionary *)activeTLKs -{ - NSMutableDictionary *tlks = [NSMutableDictionary new]; - @synchronized(self.views) { - for (NSString *name in self.views) { - CKKSKeychainView *view = self.views[name]; - NSString *tlk = view.lastActiveTLKUUID; - if (tlk) { - tlks[name] = tlk; - } - } - } - return tlks; -} - - (void)haltZone:(NSString*)viewName { @synchronized(self.views) { @@ -566,7 +624,11 @@ dispatch_once_t globalZoneStateQueueOnce; - (CKKSKeychainView*)restartZone:(NSString*)viewName { [self haltZone:viewName]; - return [self findOrCreateView: viewName]; + CKKSKeychainView* view = [self findOrCreateView: viewName]; + + [view setCurrentSyncingPolicy:self.policy policyIsFresh:NO]; + + return view; } - (NSString*)viewNameForViewHint: (NSString*) viewHint { @@ -596,7 +658,7 @@ dispatch_once_t globalZoneStateQueueOnce; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - secnotice("ckks", "ViewsFromPolicy feature flag: %@", viewsFromPolicy ? @"on" : @"off"); + ckksnotice_global("ckks", "ViewsFromPolicy feature flag: %@", viewsFromPolicy ? @"on" : @"off"); }); return viewsFromPolicy; } @@ -609,32 +671,27 @@ dispatch_once_t globalZoneStateQueueOnce; NSMutableDictionary *dict = (__bridge_transfer NSMutableDictionary*) SecDbItemCopyPListWithMask(item, kSecDbSyncFlag, &cferror); if(cferror) { - secerror("ckks: Couldn't fetch attributes from item: %@", cferror); + ckkserror_global("ckks", "Couldn't fetch attributes from item: %@", cferror); CFReleaseNull(cferror); return nil; } - NSString* view = [self.policy mapKeyToView:dict]; + // Ensure that we've added the class name, because SecDbItemCopyPListWithMask doesn't do that for some reason. + dict[(__bridge NSString*)kSecClass] = (__bridge NSString*)item->class->name; + + NSString* view = [self.policy mapDictionaryToView:dict]; if (view == nil) { - secerror("ckks: No view returned from policy (%@): %@", self.policy, dict); + ckkserror_global("ckks", "No view returned from policy (%@): %@", self.policy, item); return nil; } - // Horrible hack until Cuttlefish: remove Safari prefix from view names - if([view isEqualToString:@"CreditCards"]) { - return @"SafariCreditCards"; - } - if([view isEqualToString:@"Passwords"]) { - return @"SafariPasswords"; - } - return view; } else { CFErrorRef cferror = NULL; NSString* viewHint = (__bridge NSString*) SecDbItemGetValue(item, &v7vwht, &cferror); if(cferror) { - secerror("ckks: Couldn't fetch the viewhint for some reason: %@", cferror); + ckkserror_global("ckks", "Couldn't fetch the viewhint for some reason: %@", cferror); CFReleaseNull(cferror); viewHint = nil; } @@ -646,18 +703,22 @@ dispatch_once_t globalZoneStateQueueOnce; - (void)registerSyncStatusCallback: (NSString*) uuid callback: (SecBoolNSErrorCallback) callback { // Someone is requesting future notification of this item. @synchronized(self.pendingSyncCallbacks) { - secnotice("ckkscallback", "registered callback for UUID: %@", uuid); + ckksnotice_global("ckkscallback", "registered callback for UUID: %@", uuid); self.pendingSyncCallbacks[uuid] = callback; } } -- (SecBoolNSErrorCallback _Nullable)claimCallbackForUUID:(NSString*)uuid +- (SecBoolNSErrorCallback _Nullable)claimCallbackForUUID:(NSString* _Nullable)uuid { + if(!uuid) { + return nil; + } + @synchronized(self.pendingSyncCallbacks) { SecBoolNSErrorCallback callback = self.pendingSyncCallbacks[uuid]; if(callback) { - secerror("ckkscallback : fetched UUID: %@", uuid); + ckksnotice_global("ckkscallback", "fetched UUID: %@", uuid); } self.pendingSyncCallbacks[uuid] = nil; @@ -679,7 +740,7 @@ dispatch_once_t globalZoneStateQueueOnce; } else { @synchronized(self.pendingSyncCallbacks) { if(self.pendingSyncCallbacks.count > 0) { - secnotice("ckkscallback", "No CK account; failing all pending sync callbacks"); + ckksnotice_global("ckkscallback", "No CK account; failing all pending sync callbacks"); for(NSString* uuid in [self.pendingSyncCallbacks allKeys]) { [CKKSViewManager callSyncCallbackWithErrorNoAccount:self.pendingSyncCallbacks[uuid]]; @@ -725,7 +786,7 @@ dispatch_once_t globalZoneStateQueueOnce; if(!addedSync && !deletedSync) { // Local-only change. Skip with prejudice. - secinfo("ckks", "skipping sync of non-sync item (%d, %d)", addedSync, deletedSync); + ckksinfo_global("ckks", "skipping sync of non-sync item (%d, %d)", addedSync, deletedSync); return; } @@ -733,17 +794,17 @@ dispatch_once_t globalZoneStateQueueOnce; @synchronized(self.views) { if([self useCKKSViewsFromPolicy] && !self.policy) { - secerror("ckks: No policy configured(%@). Skipping item: %@", self.policy, modified); + ckkserror_global("ckks", "No policy configured(%@). Skipping item: %@", self.policy, modified); self.itemModificationsBeforePolicyLoaded = YES; return; } - - viewName = [self viewNameForItem:modified]; } + viewName = [self viewNameForItem:modified]; + if(!viewName) { - secnotice("ckks", "No intended CKKS view for item; skipping: %@", modified); + ckksnotice_global("ckks", "No intended CKKS view for item; skipping: %@", modified); return; } @@ -751,7 +812,7 @@ dispatch_once_t globalZoneStateQueueOnce; CKKSKeychainView* view = [self findView:viewName]; if(!view) { - secnotice("ckks", "No CKKS view for %@, skipping: %@", viewName, modified); + ckksnotice_global("ckks", "No CKKS view for %@, skipping: %@", viewName, modified); NSString* uuid = (__bridge NSString*) SecDbItemGetValue(modified, &v10itemuuid, NULL); SecBoolNSErrorCallback syncCallback = [self claimCallbackForUUID:uuid]; @@ -781,13 +842,12 @@ dispatch_once_t globalZoneStateQueueOnce; hash:(NSData*)oldItemSHA1 complete:(void (^) (NSError* operror)) complete { - CKKSKeychainView* view = [self findView:viewHint]; + NSError* viewError = nil; + CKKSKeychainView* view = [self findView:viewHint error:&viewError]; if(!view) { - secnotice("ckks", "No CKKS view for %@, skipping current request", viewHint); - complete([NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoSuchView - description:[NSString stringWithFormat: @"No syncing view for view hint '%@'", viewHint]]); + ckksnotice_global("ckks", "No CKKS view for %@, skipping setcurrent request: %@", viewHint, viewError); + complete(viewError); return; } @@ -806,12 +866,11 @@ dispatch_once_t globalZoneStateQueueOnce; fetchCloudValue:(bool)fetchCloudValue complete:(void (^) (NSString* uuid, NSError* operror)) complete { - CKKSKeychainView* view = [self findView:viewHint]; + NSError* viewError = nil; + CKKSKeychainView* view = [self findView:viewHint error:&viewError]; if(!view) { - secnotice("ckks", "No CKKS view for %@, skipping current fetch request", viewHint); - complete(NULL, [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoSuchView - description:[NSString stringWithFormat: @"No view for '%@'", viewHint]]); + ckksnotice_global("ckks", "No CKKS view for %@, skipping current fetch request: %@", viewHint, viewError); + complete(NULL, viewError); return; } @@ -832,7 +891,7 @@ dispatch_once_t globalZoneStateQueueOnce; -(void)notifyNewTLKsInKeychain { // Why two functions here? Limitation of OCMock, unfortunately: can't stub and expect the same method - secnotice("ckksbackup", "New TLKs have arrived"); + ckksnotice_global("ckksbackup", "New TLKs have arrived"); [self syncBackupAndNotifyAboutSync]; } @@ -840,7 +899,7 @@ dispatch_once_t globalZoneStateQueueOnce; SOSAccount* account = (__bridge SOSAccount*)SOSKeychainAccountGetSharedAccount(); if(!account) { - secnotice("ckks", "Failed to get account object"); + ckksnotice_global("ckks", "Failed to get account object"); return; } @@ -850,14 +909,71 @@ dispatch_once_t globalZoneStateQueueOnce; (void)ignore; if(error) { - secerror("ckksbackup: Couldn't process sync with backup peers: %@", error); + ckkserror_global("backup", "Couldn't process sync with backup peers: %@", error); } else { - secnotice("ckksbackup", "telling CloudServices about TLK arrival"); + ckksnotice_global("ckksbackup", "telling CloudServices about TLK arrival"); notify_post(kSecItemBackupNotification); }; }]; } + + +- (NSArray* _Nullable)currentTLKsFilteredByPolicy:(BOOL)restrictToPolicy error:(NSError**)error +{ + NSError* localError = nil; + NSArray* actualViews = [self views:nil operation:@"current TLKs" error:&localError]; + if(localError) { + ckkserror_global("ckks", "Error getting views: %@", localError); + if(error) { + *error = localError; + } + return nil; + } + + NSMutableArray*>* keyFetchOperations = [NSMutableArray array]; + for (CKKSKeychainView* view in actualViews) { + if(restrictToPolicy && [self useCKKSViewsFromPolicy] && ![self.policy.viewsToPiggybackTLKs containsObject:view.zoneName]) { + continue; + } + + CKKSResultOperation* op = [view findKeySet:NO]; + [op timeout:10*NSEC_PER_SEC]; + [keyFetchOperations addObject:op]; + } + + NSMutableArray* tlks = [NSMutableArray array]; + + for(CKKSResultOperation* op in keyFetchOperations) { + [op waitUntilFinished]; + + if(op.error) { + ckkserror_global("ckks", "Error getting keyset: %@", op.error); + if(error) { + *error = op.error; + } + } else { + if(op.keyset.tlk) { + // Keys provided by this function must have the key material loaded + NSError* loadError = nil; + [op.keyset.tlk ensureKeyLoaded:&loadError]; + if(loadError) { + ckkserror_global("ckks", "Error loading key: %@", loadError); + if(error) { + *error = loadError; + } + } else { + [tlks addObject:[op.keyset.tlk.keycore copy]]; + } + } else { + ckkserror_global("ckks", "Do not have TLK: %@", op.keyset); + } + } + } + + return tlks; +} + #pragma mark - RPCs to manage and report state - (void)performanceCounters:(void(^)(NSDictionary *counter))reply { @@ -865,32 +981,53 @@ dispatch_once_t globalZoneStateQueueOnce; } - (NSArray*)views:(NSString*)viewName operation:(NSString*)opName error:(NSError**)error +{ + return [self views:viewName operation:opName errorOnPolicyMissing:YES error:error]; +} + +- (NSArray*)views:(NSString*)viewName + operation:(NSString*)opName + errorOnPolicyMissing:(BOOL)errorOnPolicyMissing + error:(NSError**)error { NSArray* actualViews = nil; // Ensure we've actually set up, but don't wait too long. Clients get impatient. if([self.completedSecCKKSInitialize wait:5*NSEC_PER_SEC]) { - secerror("ckks: Haven't yet initialized zones; expect failure fetching views"); + ckkserror_global("ckks", "Haven't yet initialized zones; expect failure fetching views"); } - @synchronized(self.views) { - if(viewName) { - CKKSKeychainView* view = self.views[viewName]; - secnotice("ckks", "Received a %@ request for zone %@ (%@)", opName, viewName, view); + // If the caller doesn't mind if the policy is missing, wait some, but not the full 5s + BOOL policyLoaded = [self.policyLoaded wait:(errorOnPolicyMissing ? 5 : 0.5)*NSEC_PER_SEC] == 0; + if(!policyLoaded) { + ckkserror_global("ckks", "Haven't yet received a policy; expect failure fetching views"); + } - if(!view) { + if(viewName) { + CKKSKeychainView* view = errorOnPolicyMissing ? [self findView:viewName error:error] : [self findView:viewName]; + ckksnotice_global("ckks", "Received a %@ request for zone %@ (%@)", opName, viewName, view); + + if(!view) { + return nil; + } + + actualViews = @[view]; + + } else { + if(!policyLoaded && [self useCKKSViewsFromPolicy] && errorOnPolicyMissing) { + if(error) { if(error) { *error = [NSError errorWithDomain:CKKSErrorDomain - code:CKKSNoSuchView - userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"No view for '%@'", viewName]}]; + code:CKKSErrorPolicyNotLoaded + userInfo:@{NSLocalizedDescriptionKey: @"CKKS syncing policy not yet loaded; cannot list all views"}]; } - return nil; } + return nil; + } - actualViews = @[view]; - } else { + @synchronized(self.views) { actualViews = [self.views.allValues copy]; - secnotice("ckks", "Received a %@ request for all zones: %@", opName, actualViews); + ckksnotice_global("ckks", "Received a %@ request for all zones: %@", opName, actualViews); } } actualViews = [actualViews sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"zoneName" ascending:YES]]]; @@ -901,16 +1038,16 @@ dispatch_once_t globalZoneStateQueueOnce; NSError* localError = nil; NSArray* actualViews = [self views:viewName operation:@"local reset" error:&localError]; if(localError) { - secerror("ckks: Error getting view %@: %@", viewName, localError); + ckkserror_global("ckks", "Error getting view %@: %@", viewName, localError); reply(localError); return; } CKKSResultOperation* op = [CKKSResultOperation named:@"local-reset-zones-waiter" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull strongOp) { if(!strongOp.error) { - secnotice("ckksreset", "Completed rpcResetLocal"); + ckksnotice_global("ckksreset", "Completed rpcResetLocal"); } else { - secnotice("ckks", "Completed rpcResetLocal with error: %@", strongOp.error); + ckksnotice_global("ckks", "Completed rpcResetLocal with error: %@", strongOp.error); } reply(CKXPCSuitableError(strongOp.error)); }]; @@ -928,7 +1065,7 @@ dispatch_once_t globalZoneStateQueueOnce; NSError* localError = nil; NSArray* actualViews = [self views:viewName operation:@"CloudKit reset" error:&localError]; if(localError) { - secerror("ckks: Error getting view %@: %@", viewName, localError); + ckkserror_global("ckks", "Error getting view %@: %@", viewName, localError); reply(localError); return; } @@ -940,9 +1077,9 @@ dispatch_once_t globalZoneStateQueueOnce; [op setCompletionBlock:^{ __strong __typeof(op) strongOp = weakOp; if(!strongOp.error) { - secnotice("ckksreset", "Completed rpcResetCloudKit"); + ckksnotice_global("ckksreset", "Completed rpcResetCloudKit"); } else { - secnotice("ckksreset", "Completed rpcResetCloudKit with error: %@", strongOp.error); + ckksnotice_global("ckksreset", "Completed rpcResetCloudKit with error: %@", strongOp.error); } reply(CKXPCSuitableError(strongOp.error)); }]; @@ -961,7 +1098,7 @@ dispatch_once_t globalZoneStateQueueOnce; NSError* localError = nil; NSArray* actualViews = [self views:viewName operation:@"CloudKit resync" error:&localError]; if(localError) { - secerror("ckks: Error getting view %@: %@", viewName, localError); + ckkserror_global("ckks", "Error getting view %@: %@", viewName, localError); reply(localError); return; } @@ -973,7 +1110,7 @@ dispatch_once_t globalZoneStateQueueOnce; // Use the completion block instead of the operation block, so that it runs even if the cancel fires [op setCompletionBlock:^{ __strong __typeof(op) strongOp = weakOp; - secnotice("ckks", "Ending rsync-CloudKit rpc with %@", strongOp.error); + ckksnotice_global("ckks", "Ending rsync-CloudKit rpc with %@", strongOp.error); reply(CKXPCSuitableError(strongOp.error)); }]; @@ -992,7 +1129,7 @@ dispatch_once_t globalZoneStateQueueOnce; NSError* localError = nil; NSArray* actualViews = [self views:viewName operation:@"local resync" error:&localError]; if(localError) { - secerror("ckks: Error getting view %@: %@", viewName, localError); + ckkserror_global("ckks", "Error getting view %@: %@", viewName, localError); reply(localError); return; } @@ -1003,7 +1140,7 @@ dispatch_once_t globalZoneStateQueueOnce; // Use the completion block instead of the operation block, so that it runs even if the cancel fires [op setCompletionBlock:^{ __strong __typeof(op) strongOp = weakOp; - secnotice("ckks", "Ending rsync-local rpc with %@", strongOp.error); + ckksnotice_global("ckks", "Ending rsync-local rpc with %@", strongOp.error); reply(CKXPCSuitableError(strongOp.error)); }]; @@ -1023,9 +1160,9 @@ dispatch_once_t globalZoneStateQueueOnce; { NSMutableArray* a = [[NSMutableArray alloc] init]; - // Now, query the views about their status + // Now, query the views about their status. Don't wait for the policy to be loaded NSError* error = nil; - NSArray* actualViews = [self views:viewName operation:@"status" error:&error]; + NSArray* actualViews = [self views:viewName operation:@"status" errorOnPolicyMissing:NO error:&error]; if(!actualViews || error) { reply(nil, error); return; @@ -1075,21 +1212,23 @@ dispatch_once_t globalZoneStateQueueOnce; // If we're signed in, give the views a few seconds to enter what they consider to be a non-transient state (in case this daemon just launched) if([self.accountTracker.ckAccountInfoInitialized wait:5*NSEC_PER_SEC]) { - secerror("ckks status: Haven't yet figured out cloudkit account state"); + ckkserror_global("account", "Haven't yet figured out cloudkit account state"); } if(self.accountTracker.currentCKAccountInfo.accountStatus == CKAccountStatusAvailable) { if (![self waitForTrustReady]) { - secerror("ckks status: Haven't yet figured out trust status"); + ckkserror_global("trust", "Haven't yet figured out trust status"); } - CKKSResultOperation* blockOp = [CKKSResultOperation named:@"wait-for-status" withBlock:^{}]; - [blockOp timeout:8*NSEC_PER_SEC]; for(CKKSKeychainView* view in actualViews) { - [blockOp addNullableDependency:view.keyStateNonTransientDependency]; + OctagonStateMultiStateArrivalWatcher* waitForTransient = [[OctagonStateMultiStateArrivalWatcher alloc] initNamed:@"rpc-watcher" + serialQueue:view.queue + states:CKKSKeyStateNonTransientStates()]; + [waitForTransient timeout:5*NSEC_PER_SEC]; + [view.stateMachine registerMultiStateArrivalWatcher:waitForTransient]; + + [statusOp addDependency:waitForTransient.result]; } - [statusOp addDependency:blockOp]; - [self.operationQueue addOperation:blockOp]; } [self.operationQueue addOperation:statusOp]; @@ -1188,15 +1327,14 @@ dispatch_once_t globalZoneStateQueueOnce; }]; [[SecMetrics managerObject] submitEvent:metric]; reply(NULL); - } -(void)xpc24HrNotification { // XPC has poked us and said we should do some cleanup! - secnotice("ckks", "Received a 24hr notification from XPC"); + ckksnotice_global("ckks", "Received a 24hr notification from XPC"); if (![self waitForTrustReady]) { - secnotice("ckks", "Trust not ready, still going ahead"); + ckksnotice_global("ckks", "Trust not ready, still going ahead"); } [[CKKSAnalytics logger] dailyCoreAnalyticsMetrics:@"com.apple.security.CKKSHealthSummary"]; @@ -1213,19 +1351,19 @@ dispatch_once_t globalZoneStateQueueOnce; ckksnotice("ckks", view, "Starting device state XPC update"); // Let the update know it should rate-limit itself [view updateDeviceState:true waitForKeyHierarchyInitialization:30*NSEC_PER_SEC ckoperationGroup:group]; + [view xpc24HrNotification]; } } - (void)haltAll { - [self.zoneModifier halt]; - @synchronized(self.views) { for(CKKSKeychainView* view in self.views.allValues) { [view halt]; } } + [self.zoneModifier halt]; } #endif // OCTAGON diff --git a/keychain/ckks/CKKSZone.h b/keychain/ckks/CKKSZone.h deleted file mode 100644 index 5869326c..00000000 --- a/keychain/ckks/CKKSZone.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2016 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@ - */ - -#import - -#if OCTAGON -#import "keychain/ckks/CKKSAccountStateTracker.h" -#import "keychain/ckks/CKKSReachabilityTracker.h" -#import "keychain/ckks/CloudKitDependencies.h" -#import "keychain/ckks/CKKSCloudKitClassDependencies.h" -#import "keychain/ckks/OctagonAPSReceiver.h" -#import "keychain/ckks/CKKSGroupOperation.h" -#import "keychain/ckks/CKKSNearFutureScheduler.h" -#import "keychain/ckks/CKKSZoneModifier.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface CKKSZone : NSObject -{ - CKContainer* _container; - CKDatabase* _database; - CKRecordZone* _zone; -} - -@property (readonly) NSString* zoneName; - -@property CKKSGroupOperation* zoneSetupOperation; -@property (nullable) CKOperationGroup* zoneSetupOperationGroup; // set this if you want zone creates to use a different operation group - -@property bool zoneCreated; -@property bool zoneSubscribed; -@property (nullable) NSError* zoneCreatedError; -@property (nullable) NSError* zoneSubscribedError; - -// True if this zone object has been halted. Halted zones will never recover. -@property (readonly) bool halted; - -@property CKKSAccountStatus accountStatus; - -@property (readonly) CKContainer* container; -@property (readonly) CKDatabase* database; - -@property (weak) CKKSAccountStateTracker* accountTracker; -@property (weak) CKKSReachabilityTracker* reachabilityTracker; - -@property (readonly) CKRecordZone* zone; -@property (readonly) CKRecordZoneID* zoneID; - -@property (readonly) CKKSZoneModifier* zoneModifier; - -// Dependencies (for injection) -@property (readonly) CKKSCloudKitClassDependencies* cloudKitClassDependencies; - -@property dispatch_queue_t queue; - -- (instancetype)initWithContainer:(CKContainer*)container - zoneName:(NSString*)zoneName - accountTracker:(CKKSAccountStateTracker*)accountTracker - reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker - zoneModifier:(CKKSZoneModifier*)zoneModifier - cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies; - - -- (CKKSResultOperation* _Nullable)deleteCloudKitZoneOperation:(CKOperationGroup* _Nullable)ckoperationGroup; - -// Called when CloudKit notifies us that we just logged in. -// That is, if we transition from any state to CKAccountStatusAvailable. -// This will be called under the protection of dispatchSync. -// This is a no-op; you should intercept this call and call handleCKLogin:zoneSubscribed: -// with the appropriate state -- (void)handleCKLogin; - -// Actually start a cloudkit login. Pass in whether you believe this zone has been created and if this device has -// subscribed to this zone on the server. -- (CKKSResultOperation* _Nullable)handleCKLogin:(bool)zoneCreated zoneSubscribed:(bool)zoneSubscribed; - -// Called when CloudKit notifies us that we just logged out. -// i.e. we transition from CKAccountStatusAvailable to any other state. -// This will be called under the protection of dispatchSync -- (void)handleCKLogout; - -// Call this when you're ready for this zone to kick off operations -// based on iCloud account status -- (void)beginCloudKitOperation; - -// Cancels all operations (no matter what they are). -- (void)cancelAllOperations; - -// Schedules this operation for execution (if the CloudKit account exists) -- (bool)scheduleOperation:(NSOperation*)op; - -// Use this to schedule an operation handling account status (cleaning up after logout, etc.). -- (bool)scheduleAccountStatusOperation:(NSOperation*)op; - -// Schedules this operation for execution, and doesn't do any dependency magic -// This should _only_ be used if you want to run something even if the CloudKit account is logged out -- (bool)scheduleOperationWithoutDependencies:(NSOperation*)op; - -// Use this for testing. -- (void)waitUntilAllOperationsAreFinished; - -// Use this for testing, to only wait for a certain type of operation to finish. -- (void)waitForOperationsOfClass:(Class)operationClass; - -// If this object wants to do anything that needs synchronization, use this. -// If this object has had -halt called, this block will never fire. -- (void)dispatchSync:(bool (^)(void))block; - -// Call this to halt everything this zone is doing. This object will never recover. Use for testing. -- (void)halt; - -// Call this to reset this object's setup, so you can call createSetupOperation again. -- (void)resetSetup; - -@end - -NS_ASSUME_NONNULL_END -#endif // OCTAGON diff --git a/keychain/ckks/CKKSZone.m b/keychain/ckks/CKKSZone.m deleted file mode 100644 index c5f878b3..00000000 --- a/keychain/ckks/CKKSZone.m +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (c) 2016 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@ - */ - -#include - -#import - -#if OCTAGON -#import "CloudKitDependencies.h" -#import "keychain/ckks/CKKSAccountStateTracker.h" -#import "keychain/ckks/CloudKitCategories.h" -#import "keychain/categories/NSError+UsefulConstructors.h" -#import -#import - -#import "keychain/ot/ObjCImprovements.h" - -#import "CKKSKeychainView.h" -#import "CKKSZone.h" - -#include - -@interface CKKSZone() - -@property CKDatabaseOperation* zoneCreationOperation; -@property CKDatabaseOperation* zoneDeletionOperation; -@property CKDatabaseOperation* zoneSubscriptionOperation; - -@property NSOperationQueue* operationQueue; -@property CKKSResultOperation* accountLoggedInDependency; - -@property NSHashTable* accountOperations; - -// Make writable -@property bool halted; -@end - -@implementation CKKSZone - -- (instancetype)initWithContainer:(CKContainer*)container - zoneName:(NSString*)zoneName - accountTracker:(CKKSAccountStateTracker*)accountTracker - reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker - zoneModifier:(CKKSZoneModifier*)zoneModifier - cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies -{ - if(self = [super init]) { - _container = container; - _zoneName = zoneName; - _accountTracker = accountTracker; - _reachabilityTracker = reachabilityTracker; - - _zoneModifier = zoneModifier; - - _halted = false; - - _database = [_container privateCloudDatabase]; - _zone = [[CKRecordZone alloc] initWithZoneID: [[CKRecordZoneID alloc] initWithZoneName:zoneName ownerName:CKCurrentUserDefaultName]]; - - _accountStatus = CKKSAccountStatusUnknown; - - _accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in."]; - - _accountOperations = [NSHashTable weakObjectsHashTable]; - - _cloudKitClassDependencies = cloudKitClassDependencies; - - _queue = dispatch_queue_create([[NSString stringWithFormat:@"CKKSQueue.%@.zone.%@", container.containerIdentifier, zoneName] UTF8String], DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - _operationQueue = [[NSOperationQueue alloc] init]; - } - return self; -} - -- (CKKSResultOperation*)createAccountLoggedInDependency:(NSString*)message { - WEAKIFY(self); - CKKSResultOperation* accountLoggedInDependency = [CKKSResultOperation named:@"account-logged-in-dependency" withBlock:^{ - STRONGIFY(self); - ckksnotice("ckkszone", self, "%@", message); - }]; - accountLoggedInDependency.descriptionErrorCode = CKKSResultDescriptionPendingAccountLoggedIn; - return accountLoggedInDependency; -} - -- (void)beginCloudKitOperation { - [self.accountTracker registerForNotificationsOfCloudKitAccountStatusChange:self]; -} - -- (void)resetSetup { - self.zoneCreated = false; - self.zoneSubscribed = false; - self.zoneCreatedError = nil; - self.zoneSubscribedError = nil; - - self.zoneCreationOperation = nil; - self.zoneSubscriptionOperation = nil; - self.zoneDeletionOperation = nil; -} - -- (CKRecordZoneID*)zoneID { - return [self.zone zoneID]; -} - -- (CKKSAccountStatus)accountStatusFromCKAccountInfo:(CKAccountInfo*)info -{ - if(!info) { - return CKKSAccountStatusUnknown; - } - if(info.accountStatus == CKAccountStatusAvailable && - info.hasValidCredentials) { - return CKKSAccountStatusAvailable; - } else { - return CKKSAccountStatusNoAccount; - } -} - - -- (void)cloudkitAccountStateChange:(CKAccountInfo* _Nullable)oldAccountInfo to:(CKAccountInfo*)currentAccountInfo -{ - ckksnotice("ckkszone", self, "%@ Received notification of CloudKit account status change, moving from %@ to %@", - self.zoneID.zoneName, - oldAccountInfo, - currentAccountInfo); - - // Filter for device2device encryption and cloudkit grey mode - CKKSAccountStatus oldStatus = [self accountStatusFromCKAccountInfo:oldAccountInfo]; - CKKSAccountStatus currentStatus = [self accountStatusFromCKAccountInfo:currentAccountInfo]; - - if(oldStatus == currentStatus) { - ckksnotice("ckkszone", self, "Computed status of new CK account info is same as old status: %@", [CKKSAccountStateTracker stringFromAccountStatus:currentStatus]); - return; - } - - switch(currentStatus) { - case CKKSAccountStatusAvailable: { - ckksnotice("ckkszone", self, "Logged into iCloud."); - [self handleCKLogin]; - - if(self.accountLoggedInDependency) { - [self.operationQueue addOperation:self.accountLoggedInDependency]; - self.accountLoggedInDependency = nil; - }; - } - break; - - case CKKSAccountStatusNoAccount: { - ckksnotice("ckkszone", self, "Logging out of iCloud. Shutting down."); - - if(!self.accountLoggedInDependency) { - self.accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in again."]; - } - - [self handleCKLogout]; - } - break; - - case CKKSAccountStatusUnknown: { - // We really don't expect to receive this as a notification, but, okay! - ckksnotice("ckkszone", self, "Account status has become undetermined. Pausing for %@", self.zoneID.zoneName); - - if(!self.accountLoggedInDependency) { - self.accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in again."]; - } - - [self handleCKLogout]; - } - break; - } -} - -- (CKKSResultOperation*)handleCKLogin:(bool)zoneCreated zoneSubscribed:(bool)zoneSubscribed { - if(!SecCKKSIsEnabled()) { - ckksinfo("ckkszone", self, "Skipping CloudKit registration due to disabled CKKS"); - return nil; - } - - // If we've already started set up and that hasn't finished, complain - if([self.zoneSetupOperation isPending] || [self.zoneSetupOperation isExecuting]) { - ckksnotice("ckkszone", self, "Asked to handleCKLogin, but zoneSetupOperation appears to not be complete? %@ Continuing anyway", self.zoneSetupOperation); - } - - self.zoneSetupOperation = [[CKKSGroupOperation alloc] init]; - self.zoneSetupOperation.name = [NSString stringWithFormat:@"zone-setup-operation-%@", self.zoneName]; - - self.zoneCreated = zoneCreated; - self.zoneSubscribed = zoneSubscribed; - - ckksnotice("ckkszone", self, "Setting up zone %@", self.zoneName); - - WEAKIFY(self); - - // First, check the account status. If it's sufficient, add the necessary CloudKit operations to this operation - __weak CKKSGroupOperation* weakZoneSetupOperation = self.zoneSetupOperation; - [self.zoneSetupOperation runBeforeGroupFinished:[CKKSResultOperation named:[NSString stringWithFormat:@"zone-setup-%@", self.zoneName] withBlock:^{ - STRONGIFY(self); - __strong __typeof(self.zoneSetupOperation) zoneSetupOperation = weakZoneSetupOperation; - if(!self || !zoneSetupOperation) { - ckkserror("ckkszone", self, "received callback for released object"); - return; - } - - if(self.accountStatus != CKKSAccountStatusAvailable) { - ckkserror("ckkszone", self, "Zone doesn't believe it's logged in; quitting setup"); - return; - } - - NSBlockOperation* setupCompleteOperation = [NSBlockOperation blockOperationWithBlock:^{ - STRONGIFY(self); - if(!self) { - secerror("ckkszone: received callback for released object"); - return; - } - - ckksnotice("ckkszone", self, "%@: Setup complete", self.zoneName); - }]; - setupCompleteOperation.name = @"zone-setup-complete-operation"; - - // We have an account, so fetch the push environment and bring up APS - [self.container serverPreferredPushEnvironmentWithCompletionHandler: ^(NSString *apsPushEnvString, NSError *error) { - STRONGIFY(self); - if(!self) { - secerror("ckkszone: received callback for released object"); - return; - } - - if(error || (apsPushEnvString == nil)) { - ckkserror("ckkszone", self, "Received error fetching preferred push environment (%@). Keychain syncing is highly degraded: %@", apsPushEnvString, error); - } else { - OctagonAPSReceiver* aps = [OctagonAPSReceiver receiverForEnvironment:apsPushEnvString - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:self.cloudKitClassDependencies.apsConnectionClass]; - [aps registerReceiver:self forZoneID:self.zoneID]; - } - }]; - - if(!zoneCreated || !zoneSubscribed) { - ckksnotice("ckkszone", self, "Asking to create and subscribe to CloudKit zone '%@'", self.zoneName); - CKKSZoneModifyOperations* zoneOps = [self.zoneModifier createZone:self.zone]; - - CKKSResultOperation* handleModificationsOperation = [CKKSResultOperation named:@"handle-modification" withBlock:^{ - STRONGIFY(self); - if([zoneOps.savedRecordZones containsObject:self.zone]) { - ckksnotice("ckkszone", self, "Successfully created '%@'", self.zoneName); - self.zoneCreated = true; - } else { - ckksnotice("ckkszone", self, "Failed to create '%@'", self.zoneName); - self.zoneCreatedError = zoneOps.zoneModificationOperation.error; - } - - bool createdSubscription = false; - for(CKSubscription* subscription in zoneOps.savedSubscriptions) { - if([subscription.zoneID isEqual:self.zoneID]) { - createdSubscription = true; - break; - } - } - - if(createdSubscription) { - ckksnotice("ckkszone", self, "Successfully subscribed '%@'", self.zoneName); - self.zoneSubscribed = true; - } else { - ckksnotice("ckkszone", self, "Failed to subscribe to '%@'", self.zoneName); - self.zoneSubscribedError = zoneOps.zoneSubscriptionOperation.error; - } - }]; - [setupCompleteOperation addDependency:zoneOps.zoneModificationOperation]; - [handleModificationsOperation addDependency:zoneOps.zoneModificationOperation]; - [handleModificationsOperation addDependency:zoneOps.zoneSubscriptionOperation]; - [zoneSetupOperation runBeforeGroupFinished:handleModificationsOperation]; - } else { - ckksnotice("ckkszone", self, "no need to create or subscribe to the zone '%@'", self.zoneName); - } - - [self.zoneSetupOperation runBeforeGroupFinished:setupCompleteOperation]; - }]]; - - [self scheduleAccountStatusOperation:self.zoneSetupOperation]; - return self.zoneSetupOperation; -} - - -- (CKKSResultOperation*)deleteCloudKitZoneOperation:(CKOperationGroup* _Nullable)ckoperationGroup { - if(!SecCKKSIsEnabled()) { - ckksnotice("ckkszone", self, "Skipping CloudKit reset due to disabled CKKS"); - return nil; - } - - WEAKIFY(self); - - // We want to delete this zone and this subscription from CloudKit. - - // Step 1: cancel setup operations (if they exist) - [self.accountLoggedInDependency cancel]; - [self.zoneSetupOperation cancel]; - [self.zoneCreationOperation cancel]; - [self.zoneSubscriptionOperation cancel]; - - // Step 2: Try to delete the zone - - CKKSZoneModifyOperations* zoneOps = [self.zoneModifier deleteZone:self.zoneID]; - - CKKSResultOperation* afterModification = [CKKSResultOperation named:@"after-modification" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull op) { - STRONGIFY(self); - - bool fatalError = false; - - NSError* operationError = zoneOps.zoneModificationOperation.error; - bool removed = [zoneOps.deletedRecordZoneIDs containsObject:self.zoneID]; - - if(!removed && operationError) { - // Okay, but if this error is either 'ZoneNotFound' or 'UserDeletedZone', that's fine by us: the zone is deleted. - NSDictionary* partialErrors = operationError.userInfo[CKPartialErrorsByItemIDKey]; - if([operationError.domain isEqualToString:CKErrorDomain] && operationError.code == CKErrorPartialFailure && partialErrors) { - for(CKRecordZoneID* errorZoneID in partialErrors.allKeys) { - NSError* errorZone = partialErrors[errorZoneID]; - - if(errorZone && [errorZone.domain isEqualToString:CKErrorDomain] && - (errorZone.code == CKErrorZoneNotFound || errorZone.code == CKErrorUserDeletedZone)) { - ckksnotice("ckkszone", self, "Attempted to delete zone %@, but it's already missing. This is okay: %@", errorZoneID, errorZone); - } else { - fatalError = true; - } - } - - } else { - fatalError = true; - } - - ckksnotice("ckkszone", self, "deletion of record zone %@ completed with error: %@", self.zoneID, operationError); - - if(fatalError) { - op.error = operationError; - } - } else { - ckksnotice("ckkszone", self, "deletion of record zone %@ completed successfully", self.zoneID); - } - }]; - - [afterModification addDependency:zoneOps.zoneModificationOperation]; - return afterModification; -} - -- (void)notifyZoneChange: (CKRecordZoneNotification*) notification { - ckksnotice("ckkszone", self, "received a notification for CK zone change, ignoring"); -} - -- (void)handleCKLogin { - ckksinfo("ckkszone", self, "received a notification of CK login"); - self.accountStatus = CKKSAccountStatusAvailable; -} - -- (void)handleCKLogout { - ckksinfo("ckkszone", self, "received a notification of CK logout"); - self.accountStatus = CKKSAccountStatusNoAccount; - [self resetSetup]; -} - -- (bool)scheduleOperation: (NSOperation*) op { - if(self.halted) { - ckkserror("ckkszone", self, "attempted to schedule an operation on a halted zone, ignoring"); - return false; - } - - [op addNullableDependency:self.accountLoggedInDependency]; - - [self.operationQueue addOperation: op]; - return true; -} - -- (void)cancelAllOperations { - [self.operationQueue cancelAllOperations]; -} - -- (void)waitUntilAllOperationsAreFinished { - [self.operationQueue waitUntilAllOperationsAreFinished]; -} - -- (void)waitForOperationsOfClass:(Class) operationClass { - NSArray* operations = [self.operationQueue.operations copy]; - for(NSOperation* op in operations) { - if([op isKindOfClass:operationClass]) { - [op waitUntilFinished]; - } - } -} - -- (bool)scheduleAccountStatusOperation: (NSOperation*) op { - if(self.halted) { - ckkserror("ckkszone", self, "attempted to schedule an account operation on a halted zone, ignoring"); - return false; - } - - // Always succeed. But, account status operations should always proceed in-order. - [op linearDependencies:self.accountOperations]; - [self.operationQueue addOperation: op]; - return true; -} - -// to be used rarely, if at all -- (bool)scheduleOperationWithoutDependencies:(NSOperation*)op { - if(self.halted) { - ckkserror("ckkszone", self, "attempted to schedule an non-dependent operation on a halted zone, ignoring"); - return false; - } - - [self.operationQueue addOperation: op]; - return true; -} - -- (void) dispatchSync: (bool (^)(void)) block { - // important enough to block this thread. - __block bool ok = false; - dispatch_sync(self.queue, ^{ - if(self.halted) { - ckkserror("ckkszone", self, "CKKSZone not dispatchSyncing a block (due to being halted)"); - return; - } - - ok = block(); - if(!ok) { - ckkserror("ckkszone", self, "CKKSZone block returned false"); - } - }); -} - -- (void)halt { - // Synchronously set the 'halted' bit - dispatch_sync(self.queue, ^{ - self.halted = true; - }); - - // Bring all operations down, too - [self cancelAllOperations]; - - // And now, wait for all operations that are running - for(NSOperation* op in self.operationQueue.operations) { - if(op.isExecuting) { - [op waitUntilFinished]; - } - } -} - -@end - -#endif /* OCTAGON */ - diff --git a/keychain/ckks/CKKSZoneChangeFetcher.h b/keychain/ckks/CKKSZoneChangeFetcher.h index 08510fb2..dedcf587 100644 --- a/keychain/ckks/CKKSZoneChangeFetcher.h +++ b/keychain/ckks/CKKSZoneChangeFetcher.h @@ -26,6 +26,7 @@ #import #import "keychain/ckks/CKKSResultOperation.h" #import "keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.h" +#import "keychain/ckks/OctagonAPSReceiver.h" NS_ASSUME_NONNULL_BEGIN @@ -39,7 +40,7 @@ NS_ASSUME_NONNULL_BEGIN @class CKKSReachabilityTracker; @class CKKSNearFutureScheduler; -@interface CKKSZoneChangeFetcher : NSObject +@interface CKKSZoneChangeFetcher : NSObject @property (readonly) Class fetchRecordZoneChangesOperationClass; @property (readonly) CKContainer* container; @property CKKSReachabilityTracker* reachabilityTracker; @@ -56,8 +57,11 @@ NS_ASSUME_NONNULL_BEGIN - (CKKSResultOperation*)requestSuccessfulFetch:(CKKSFetchBecause*)why; - (CKKSResultOperation*)requestSuccessfulFetchForManyReasons:(NSSet*)why; -// let server know we seen this push and if zones are ready actually perform a fetch -- (CKKSResultOperation* _Nullable)requestFetchDueToAPNS:(CKRecordZoneNotification*)notification; +// Returns the next fetch, if one is scheduled, or the last/currently executing fetch if not. +- (CKKSResultOperation* _Nullable)inflightFetch; + +// CKKSZoneUpdateReceiverProtocol +- (void)notifyZoneChange:(CKRecordZoneNotification* _Nullable)notification; // We don't particularly care what this does, as long as it finishes - (void)holdFetchesUntil:(CKKSResultOperation* _Nullable)holdOperation; diff --git a/keychain/ckks/CKKSZoneChangeFetcher.m b/keychain/ckks/CKKSZoneChangeFetcher.m index ead140b9..3eced57a 100644 --- a/keychain/ckks/CKKSZoneChangeFetcher.m +++ b/keychain/ckks/CKKSZoneChangeFetcher.m @@ -104,6 +104,8 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- @property bool newRequests; // true if there's someone pending on successfulFetchDependency @property CKKSZoneChangeFetchDependencyOperation* successfulFetchDependency; +@property (nullable) CKKSZoneChangeFetchDependencyOperation* inflightFetchDependency; + @property CKKSResultOperation* holdOperation; @end @@ -127,11 +129,12 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- _queue = dispatch_queue_create([_name UTF8String], DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); _operationQueue = [[NSOperationQueue alloc] init]; _successfulFetchDependency = [self createSuccesfulFetchDependency]; + _inflightFetchDependency = nil; _newRequests = false; - // If we're testing, for the initial delay, use 0.25 second. Otherwise, 2s. - dispatch_time_t initialDelay = (SecCKKSReduceRateLimiting() ? 250 * NSEC_PER_MSEC : 2 * NSEC_PER_SEC); + // If we're testing, for the initial delay, use 0.5 second. Otherwise, 2s. + dispatch_time_t initialDelay = (SecCKKSReduceRateLimiting() ? 500 * NSEC_PER_MSEC : 2 * NSEC_PER_SEC); // If we're testing, for the maximum delay, use 6 second. Otherwise, 2m. dispatch_time_t maximumDelay = (SecCKKSReduceRateLimiting() ? 6 * NSEC_PER_SEC : 120 * NSEC_PER_SEC); @@ -185,6 +188,12 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- return [self requestSuccessfulFetchForManyReasons:[NSSet setWithObject:why]]; } +- (void)notifyZoneChange:(CKRecordZoneNotification* _Nullable)notification +{ + ckksnotice_global("ckkspush", "received a zone change notification for %@ %@", self, notification); + [self requestFetchDueToAPNS:notification]; +} + - (CKKSResultOperation*)requestFetchDueToAPNS:(CKRecordZoneNotification*)notification { __block BOOL notReady = YES; @@ -197,6 +206,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- for(id client in clients) { if([client zoneIsReadyForFetching]) { notReady = NO; + break; } } @@ -206,7 +216,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- [self.apnsPushes addObject:notification]; if(notification.ckksPushTracingEnabled) { // Report that we saw this notification before doing anything else - secnotice("ckksfetch", "Submitting initial CKEventMetric due to notification %@", notification); + ckksnotice_global("ckksfetch", "Submitting initial CKEventMetric due to notification %@", notification); CKEventMetric *metric = [[CKEventMetric alloc] initWithEventName:@"APNSPushMetrics"]; metric.isPushTriggerFired = true; @@ -230,7 +240,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- }); if (notReady) { - secnotice("ckksfetch", "Skipping fetching size no zone is ready"); + ckksnotice_global("ckksfetch", "Skipping fetching size no zone is ready"); return NULL; } @@ -251,6 +261,23 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- return dependency; } +- (CKKSResultOperation* _Nullable)inflightFetch +{ + __block CKKSResultOperation* dependency = nil; + dispatch_sync(self.queue, ^{ + + // If we'll have a new fetch in the future, return its status. + if(self.newRequests || self.inflightFetchDependency == nil) { + dependency = self.successfulFetchDependency; + } else { + // Otherwise, return the last triggered fetch + dependency = self.inflightFetchDependency; + } + }); + + return dependency; +} + -(void)maybeCreateNewFetchOnQueue { dispatch_assert_queue(self.queue); if(self.newRequests && @@ -272,12 +299,14 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- WEAKIFY(self); CKKSZoneChangeFetchDependencyOperation* dependency = self.successfulFetchDependency; + self.inflightFetchDependency = dependency; + NSMutableSet* lastFetchReasons = self.currentFetchReasons; self.currentFetchReasons = [[NSMutableSet alloc] init]; NSString *reasonsString = [[lastFetchReasons sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES]]] componentsJoinedByString:@","]; - secnotice("ckksfetcher", "Starting a new fetch, reasons: %@", reasonsString); + ckksnotice_global("ckksfetcher", "Starting a new fetch, reasons: %@", reasonsString); NSMutableSet* lastAPNSPushes = self.apnsPushes; self.apnsPushes = [[NSMutableSet alloc] init]; @@ -287,7 +316,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- NSArray> *clients = [self clients]; if(clients.count == 0u) { - secnotice("ckksfetcher", "No clients"); + ckksnotice_global("ckksfetcher", "No clients"); // Nothing to do, really. } @@ -300,7 +329,7 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- ckoperationGroup:operationGroup]; if ([lastFetchReasons containsObject:CKKSFetchBecauseNetwork]) { - secnotice("ckksfetcher", "blocking fetch on network reachability"); + ckksnotice_global("ckksfetcher", "blocking fetch on network reachability"); [fetchAllChanges addNullableDependency: self.reachabilityTracker.reachabilityDependency]; // wait on network, if its unavailable } [fetchAllChanges addNullableDependency: self.holdOperation]; @@ -308,13 +337,13 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- self.currentProcessResult = [CKKSResultOperation operationWithBlock: ^{ STRONGIFY(self); if(!self) { - secerror("ckksfetcher: Received a null self pointer; strange."); + ckkserror_global("ckksfetcher", "Received a null self pointer; strange."); return; } bool attemptAnotherFetch = false; if(fetchAllChanges.error != nil) { - secerror("ckksfetcher: Interrogating clients about fetch error: %@", fetchAllChanges.error); + ckkserror_global("ckksfetcher", "Interrogating clients about fetch error: %@", fetchAllChanges.error); // Check in with clients: should we keep fetching for them? @synchronized(self.clientMap) { @@ -345,17 +374,17 @@ CKKSFetchBecause* const CKKSFetchBecauseMoreComing = (CKKSFetchBecause*) @"more- [self.operationQueue addOperation: dependency]; if(!attemptAnotherFetch) { - secerror("ckksfetcher: All clients thought %@ is a fatal error. Not restarting fetch.", fetchAllChanges.error); + ckkserror_global("ckksfetcher", "All clients thought %@ is a fatal error. Not restarting fetch.", fetchAllChanges.error); return; } // And in a bit, try the fetch again. NSTimeInterval delay = CKRetryAfterSecondsForError(fetchAllChanges.error); if (delay) { - secnotice("ckksfetcher", "Fetch failed with rate-limiting error, restarting in %.1f seconds: %@", delay, fetchAllChanges.error); + ckksnotice_global("ckksfetcher", "Fetch failed with rate-limiting error, restarting in %.1f seconds: %@", delay, fetchAllChanges.error); [self.fetchScheduler waitUntil:NSEC_PER_SEC * delay]; } else { - secnotice("ckksfetcher", "Fetch failed with error, restarting soon: %@", fetchAllChanges.error); + ckksnotice_global("ckksfetcher", "Fetch failed with error, restarting soon: %@", fetchAllChanges.error); } // Add the failed fetch reasons to the new fetch reasons diff --git a/keychain/ckks/CKKSZoneModifier.m b/keychain/ckks/CKKSZoneModifier.m index 58905c26..85dd700f 100644 --- a/keychain/ckks/CKKSZoneModifier.m +++ b/keychain/ckks/CKKSZoneModifier.m @@ -8,7 +8,6 @@ #import "keychain/ckks/CKKSReachabilityTracker.h" #import "keychain/ckks/CKKSZoneModifier.h" -#import "utilities/debugging.h" #import "keychain/ot/ObjCImprovements.h" @implementation CKKSZoneModifyOperations @@ -99,11 +98,11 @@ if(!self.pendingOperations) { CKKSResultOperation* zoneModificationOperationDependency = [CKKSResultOperation named:@"zone-modification" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull op) { - secnotice("ckkszonemodifier", "finished creating zones"); + ckksnotice_global("ckkszonemodifier", "finished creating zones"); }]; CKKSResultOperation* zoneSubscriptionOperationDependency = [CKKSResultOperation named:@"zone-subscription" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull op) { - secnotice("ckkszonemodifier", "finished subscribing to zones"); + ckksnotice_global("ckkszonemodifier", "finished subscribing to zones"); }]; self.pendingOperations = [[CKKSZoneModifyOperations alloc] initWithZoneModificationOperation:zoneModificationOperationDependency @@ -158,19 +157,19 @@ { dispatch_sync(self.queue, ^{ if(self.halted) { - secnotice("ckkszonemodifier", "Halted; not launching operations"); + ckksnotice_global("ckkszonemodifier", "Halted; not launching operations"); return; } CKKSZoneModifyOperations* ops = self.pendingOperations; if(!ops) { - secinfo("ckkszonemodifier", "No pending zone modification operations; quitting"); + ckksinfo_global("ckkszonemodifier", "No pending zone modification operations; quitting"); return; } if(self.inflightOperations && (![self.inflightOperations.zoneModificationOperation isFinished] || ![self.inflightOperations.zoneSubscriptionOperation isFinished])) { - secnotice("ckkszonemodifier", "Have in-flight zone modification operations, will retry later"); + ckksnotice_global("ckkszonemodifier", "Have in-flight zone modification operations, will retry later"); WEAKIFY(self); CKKSResultOperation* retrigger = [CKKSResultOperation named:@"retry" withBlock:^{ @@ -198,7 +197,7 @@ - (CKDatabaseOperation*)createModifyZonesOperation:(CKKSZoneModifyOperations*)ops { - secnotice("ckkszonemodifier", "Attempting to create zones %@, delete zones %@", ops.zonesToCreate, ops.zoneIDsToDelete); + ckksnotice_global("ckkszonemodifier", "Attempting to create zones %@, delete zones %@", ops.zonesToCreate, ops.zoneIDsToDelete); CKDatabaseOperation* zoneModifyOperation = [[self.cloudKitClassDependencies.modifyRecordZonesOperationClass alloc] initWithRecordZonesToSave:ops.zonesToCreate recordZoneIDsToDelete:ops.zoneIDsToDelete]; [zoneModifyOperation linearDependencies:self.ckOperations]; @@ -219,15 +218,15 @@ STRONGIFY(self); if(operationError) { - secerror("ckkszonemodifier: Zone modification failed: %@", operationError); + ckkserror_global("ckkszonemodifier", "Zone modification failed: %@", operationError); [self inspectErrorForRetryAfter:operationError]; if ([self.reachabilityTracker isNetworkError:operationError]){ self.networkFailure = true; } } - secnotice("ckkszonemodifier", "created zones: %@", savedRecordZones); - secnotice("ckkszonemodifier", "deleted zones: %@", deletedRecordZoneIDs); + ckksnotice_global("ckkszonemodifier", "created zones: %@", savedRecordZones); + ckksnotice_global("ckkszonemodifier", "deleted zones: %@", deletedRecordZoneIDs); ops.savedRecordZones = savedRecordZones; ops.deletedRecordZoneIDs = deletedRecordZoneIDs; @@ -237,7 +236,7 @@ }; if(self.networkFailure) { - secnotice("ckkszonemodifier", "Waiting for reachabilty before issuing zone creation"); + ckksnotice_global("ckkszonemodifier", "Waiting for reachabilty before issuing zone creation"); [zoneModifyOperation addNullableDependency:self.reachabilityTracker.reachabilityDependency]; } @@ -246,7 +245,7 @@ - (CKDatabaseOperation* _Nullable)createModifySubscriptionsOperation:(CKKSZoneModifyOperations*)ops { - secnotice("ckkszonemodifier", "Attempting to subscribe to zones %@", ops.subscriptionsToSubscribe); + ckksnotice_global("ckkszonemodifier", "Attempting to subscribe to zones %@", ops.subscriptionsToSubscribe); if(ops.subscriptionsToSubscribe.count == 0) { [self.operationQueue addOperation: ops.zoneSubscriptionOperation]; @@ -269,14 +268,14 @@ STRONGIFY(self); if(operationError) { - secerror("ckkszonemodifier: Couldn't create cloudkit zone subscription; keychain syncing is severely degraded: %@", operationError); + ckkserror_global("ckkszonemodifier", "Couldn't create cloudkit zone subscription; keychain syncing is severely degraded: %@", operationError); [self inspectErrorForRetryAfter:operationError]; if ([self.reachabilityTracker isNetworkError:operationError]){ self.networkFailure = true; } } - secnotice("ckkszonemodifier", "Successfully subscribed to %@", savedSubscriptions); + ckksnotice_global("ckkszonemodifier", "Successfully subscribed to %@", savedSubscriptions); ops.savedSubscriptions = savedSubscriptions; ops.deletedSubscriptionIDs = deletedSubscriptionIDs; @@ -288,7 +287,7 @@ [zoneSubscriptionOperation addNullableDependency:ops.zoneModificationOperation]; if(self.networkFailure) { - secnotice("ckkszonemodifier", "Waiting for reachabilty before issuing zone subscription"); + ckksnotice_global("ckkszonemodifier", "Waiting for reachabilty before issuing zone subscription"); [zoneSubscriptionOperation addNullableDependency:self.reachabilityTracker.reachabilityDependency]; } @@ -300,7 +299,7 @@ NSTimeInterval delay = CKRetryAfterSecondsForError(ckerror); if(delay) { uint64_t ns_delay = NSEC_PER_SEC * ((uint64_t) delay); - secnotice("ckkszonemodifier", "CK operation failed with rate-limit, scheduling delay for %.1f seconds: %@", delay, ckerror); + ckksnotice_global("ckkszonemodifier", "CK operation failed with rate-limit, scheduling delay for %.1f seconds: %@", delay, ckerror); [self.cloudkitRetryAfter waitUntil:ns_delay]; } } diff --git a/keychain/ckks/CKKSZoneStateEntry.h b/keychain/ckks/CKKSZoneStateEntry.h index 27213bca..f2c7a5b2 100644 --- a/keychain/ckks/CKKSZoneStateEntry.h +++ b/keychain/ckks/CKKSZoneStateEntry.h @@ -57,9 +57,11 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable) NSData* encodedChangeToken; @property BOOL moreRecordsInCloudKit; @property (nullable) NSDate* lastFetchTime; +@property (nullable) NSDate* lastLocalKeychainScanTime; @property CKKSFixup lastFixup; + @property (nullable) CKKSRateLimiter* rateLimiter; @property (nullable) NSData* encodedRateLimiter; @@ -74,10 +76,11 @@ NS_ASSUME_NONNULL_BEGIN changeToken:(NSData* _Nullable)changetoken moreRecordsInCloudKit:(BOOL)moreRecords lastFetch:(NSDate* _Nullable)lastFetch + lastScan:(NSDate* _Nullable)localKeychainScanned lastFixup:(CKKSFixup)lastFixup encodedRateLimiter:(NSData* _Nullable)encodedRateLimiter; -- (CKServerChangeToken*)getChangeToken; +- (CKServerChangeToken* _Nullable)getChangeToken; - (void)setChangeToken:(CKServerChangeToken* _Nullable)token; - (BOOL)isEqual:(id)object; diff --git a/keychain/ckks/CKKSZoneStateEntry.m b/keychain/ckks/CKKSZoneStateEntry.m index f835d9ab..0f15f257 100644 --- a/keychain/ckks/CKKSZoneStateEntry.m +++ b/keychain/ckks/CKKSZoneStateEntry.m @@ -48,6 +48,7 @@ changeToken:(NSData*)changetoken moreRecordsInCloudKit:(BOOL)moreRecords lastFetch:(NSDate*)lastFetch + lastScan:(NSDate* _Nullable)lastScan lastFixup:(CKKSFixup)lastFixup encodedRateLimiter:(NSData*)encodedRateLimiter { @@ -58,6 +59,7 @@ _encodedChangeToken = changetoken; _moreRecordsInCloudKit = moreRecords; _lastFetchTime = lastFetch; + _lastLocalKeychainScanTime = lastScan; _lastFixup = lastFixup; self.encodedRateLimiter = encodedRateLimiter; @@ -80,6 +82,7 @@ ((self.lastFetchTime == nil && obj.lastFetchTime == nil) || [self.lastFetchTime isEqualToDate: obj.lastFetchTime]) && ((self.rateLimiter == nil && obj.rateLimiter == nil) || [self.rateLimiter isEqual: obj.rateLimiter]) && self.lastFixup == obj.lastFixup && + ((self.lastLocalKeychainScanTime == nil && obj.lastLocalKeychainScanTime == nil) || [self.lastLocalKeychainScanTime isEqualToDate: obj.lastLocalKeychainScanTime]) && true) ? YES : NO; } @@ -88,7 +91,7 @@ CKKSZoneStateEntry* ret = [CKKSZoneStateEntry tryFromDatabase:ckzone error:&error]; if(error) { - secerror("CKKS: error fetching CKState(%@): %@", ckzone, error); + ckkserror_global("ckks", "error fetching CKState(%@): %@", ckzone, error); } if(!ret) { @@ -98,13 +101,14 @@ changeToken:nil moreRecordsInCloudKit:NO lastFetch:nil + lastScan:nil lastFixup:CKKSCurrentFixupNumber encodedRateLimiter:nil]; } return ret; } -- (CKServerChangeToken*) getChangeToken { +- (CKServerChangeToken* _Nullable) getChangeToken { if(self.encodedChangeToken) { NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:self.encodedChangeToken error:nil]; return [unarchiver decodeObjectOfClass:[CKServerChangeToken class] forKey:NSKeyedArchiveRootObjectKey]; @@ -151,7 +155,8 @@ } + (NSArray*) sqlColumns { - return @[@"ckzone", @"ckzonecreated", @"ckzonesubscribed", @"changetoken", @"lastfetch", @"ratelimiter", @"lastFixup", @"morecoming"]; + // Note that 'extra' is not currently used, but the schema supports adding a protobuf or other serialized data + return @[@"ckzone", @"ckzonecreated", @"ckzonesubscribed", @"changetoken", @"lastfetch", @"ratelimiter", @"lastFixup", @"morecoming", @"lastscan", @"extra"]; } - (NSDictionary*) whereClauseToFindSelf { @@ -161,15 +166,17 @@ - (NSDictionary*) sqlValues { NSISO8601DateFormatter* dateFormat = [[NSISO8601DateFormatter alloc] init]; - return @{@"ckzone": self.ckzone, - @"ckzonecreated": [NSNumber numberWithBool:self.ckzonecreated], - @"ckzonesubscribed": [NSNumber numberWithBool:self.ckzonesubscribed], - @"changetoken": CKKSNilToNSNull([self.encodedChangeToken base64EncodedStringWithOptions:0]), - @"lastfetch": CKKSNilToNSNull(self.lastFetchTime ? [dateFormat stringFromDate: self.lastFetchTime] : nil), - @"ratelimiter": CKKSNilToNSNull([self.encodedRateLimiter base64EncodedStringWithOptions:0]), - @"lastFixup": [NSNumber numberWithLong:self.lastFixup], - @"morecoming": [NSNumber numberWithBool:self.moreRecordsInCloudKit], - }; + return @{ + @"ckzone": self.ckzone, + @"ckzonecreated": [NSNumber numberWithBool:self.ckzonecreated], + @"ckzonesubscribed": [NSNumber numberWithBool:self.ckzonesubscribed], + @"changetoken": CKKSNilToNSNull([self.encodedChangeToken base64EncodedStringWithOptions:0]), + @"lastfetch": CKKSNilToNSNull(self.lastFetchTime ? [dateFormat stringFromDate: self.lastFetchTime] : nil), + @"ratelimiter": CKKSNilToNSNull([self.encodedRateLimiter base64EncodedStringWithOptions:0]), + @"lastFixup": [NSNumber numberWithLong:self.lastFixup], + @"morecoming": [NSNumber numberWithBool:self.moreRecordsInCloudKit], + @"lastscan": CKKSNilToNSNull(self.lastLocalKeychainScanTime ? [dateFormat stringFromDate:self.lastLocalKeychainScanTime] : nil), + }; } + (instancetype)fromDatabaseRow:(NSDictionary*)row { @@ -179,6 +186,7 @@ changeToken:row[@"changetoken"].asBase64DecodedData moreRecordsInCloudKit:row[@"morecoming"].asBOOL lastFetch:row[@"lastfetch"].asISO8601Date + lastScan:row[@"lastscan"].asISO8601Date lastFixup:(CKKSFixup)row[@"lastFixup"].asNSInteger encodedRateLimiter:row[@"ratelimiter"].asBase64DecodedData ]; diff --git a/keychain/ckks/CloudKitCategories.m b/keychain/ckks/CloudKitCategories.m index 50bb8904..896b27ad 100644 --- a/keychain/ckks/CloudKitCategories.m +++ b/keychain/ckks/CloudKitCategories.m @@ -83,7 +83,7 @@ if([cuttlefishError.domain isEqualToString:CuttlefishErrorDomain]) { NSNumber* val = cuttlefishError.userInfo[CuttlefishErrorRetryAfterKey]; - if (val) { + if (val != nil) { return (NSTimeInterval)val.doubleValue; } } diff --git a/keychain/ckks/CloudKitDependencies.h b/keychain/ckks/CloudKitDependencies.h index ae9ad1c3..15c4b901 100644 --- a/keychain/ckks/CloudKitDependencies.h +++ b/keychain/ckks/CloudKitDependencies.h @@ -103,6 +103,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy) NSString *operationID; @property (nonatomic, readonly, strong, nullable) CKOperationConfiguration *resolvedConfiguration; + +@property (nonatomic, strong) NSString *deviceIdentifier; @end @interface CKFetchRecordZoneChangesOperation () @@ -151,13 +153,15 @@ NS_ASSUME_NONNULL_BEGIN /* APSConnection */ @protocol OctagonAPSConnection +@property NSArray* enabledTopics; +@property NSArray* opportunisticTopics; +@property NSArray* darkWakeTopics; + + (instancetype)alloc; - (id)initWithEnvironmentName:(NSString*)environmentName namedDelegatePort:(NSString*)namedDelegatePort queue:(dispatch_queue_t)queue; -- (void)setEnabledTopics:(NSArray *)enabledTopics; -- (void)setDarkWakeTopics:(NSArray *)darkWakeTopics; @property (nonatomic, readwrite, assign) id delegate; @end diff --git a/keychain/ckks/NSOperationCategories.m b/keychain/ckks/NSOperationCategories.m index b9ea9410..5867d700 100644 --- a/keychain/ckks/NSOperationCategories.m +++ b/keychain/ckks/NSOperationCategories.m @@ -22,9 +22,9 @@ */ #import +#import "keychain/ckks/CKKS.h" #import "keychain/ckks/NSOperationCategories.h" #import "keychain/ot/ObjCImprovements.h" -#import "utilities/debugging.h" @implementation NSOperation (CKKSUsefulPrintingOperation) - (NSString*)selfname { @@ -43,7 +43,7 @@ continue; } #if DEBUG - secnotice("ckks-operation", "adding dependency of %@ on %@", self, existingop); + ckksnotice_global("ckks-operation", "adding dependency of %@ on %@", self.name, existingop); #endif [self addDependency: existingop]; } diff --git a/keychain/ckks/OctagonAPSReceiver.h b/keychain/ckks/OctagonAPSReceiver.h index 98b8920c..a5c22a02 100644 --- a/keychain/ckks/OctagonAPSReceiver.h +++ b/keychain/ckks/OctagonAPSReceiver.h @@ -39,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, nullable) NSDate* ckksPushReceivedDate; @end -@protocol CKKSZoneUpdateReceiver +@protocol CKKSZoneUpdateReceiverProtocol - (void)notifyZoneChange:(CKRecordZoneNotification* _Nullable)notification; @end @@ -55,28 +55,32 @@ NS_ASSUME_NONNULL_BEGIN @property (readonly) BOOL haveStalePushes; -+ (instancetype)receiverForEnvironment:(NSString*)environmentName - namedDelegatePort:(NSString*)namedDelegatePort - apsConnectionClass:(Class)apsConnectionClass; ++ (instancetype)receiverForNamedDelegatePort:(NSString*)namedDelegatePort + apsConnectionClass:(Class)apsConnectionClass; ++ (void)resetGlobalDelegatePortMap; -- (CKKSCondition*)registerReceiver:(id)receiver forZoneID:(CKRecordZoneID*)zoneID; +- (void)registerForEnvironment:(NSString*)environmentName; + +- (CKKSCondition*)registerCKKSReceiver:(id)receiver; + +// APS reserves the right to coalesce pushes by topic. So, any cuttlefish container push might hide pushes for other cuttlefish containers. +// This is okay for now, as we only have one active cuttlefish container per device, but if we start to have multiple accounts, this handling might need to change. - (CKKSCondition*)registerCuttlefishReceiver:(id)receiver forContainerName:(NSString*)containerName; // Test support: -- (instancetype)initWithEnvironmentName:(NSString*)environmentName - namedDelegatePort:(NSString*)namedDelegatePort +- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort apsConnectionClass:(Class)apsConnectionClass; -- (instancetype)initWithEnvironmentName:(NSString*)environmentName - namedDelegatePort:(NSString*)namedDelegatePort +- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort apsConnectionClass:(Class)apsConnectionClass stalePushTimeout:(uint64_t)stalePushTimeout; + // This is the queue that APNS will use send the notifications to us + (dispatch_queue_t)apsDeliveryQueue; +- (NSArray*)registeredPushEnvironments; @end @interface OctagonAPSReceiver (Testing) -+ (void)resetGlobalEnviornmentMap; -- (void)reportDroppedPushes:(NSDictionary*>*)notifications; +- (void)reportDroppedPushes:(NSSet*)notifications; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ckks/OctagonAPSReceiver.m b/keychain/ckks/OctagonAPSReceiver.m index e8eeb4f7..682ef868 100644 --- a/keychain/ckks/OctagonAPSReceiver.m +++ b/keychain/ckks/OctagonAPSReceiver.m @@ -33,7 +33,6 @@ #import "keychain/ot/ObjCImprovements.h" #import #include -#include @implementation CKRecordZoneNotification (CKKSPushTracing) - (void)setCkksPushTracingEnabled:(BOOL)ckksPushTracingEnabled { @@ -66,62 +65,70 @@ @property CKKSNearFutureScheduler *clearStalePushNotifications; +@property NSString* namedDelegatePort; +@property NSMutableDictionary>* environmentMap; + + // If we receive notifications for a record zone that hasn't been registered yet, send them a their updates when they register -@property NSMutableDictionary*>* undeliveredUpdates; +@property NSMutableSet* undeliveredUpdates; // Same, but for cuttlefish containers (and only remember that a push was received; don't remember the pushes themselves) @property NSMutableSet* undeliveredCuttlefishUpdates; -@property NSMapTable>* zoneMap; +@property (nullable) id zoneUpdateReceiver; @property NSMapTable>* octagonContainerMap; @end @implementation OctagonAPSReceiver -+ (instancetype)receiverForEnvironment:(NSString *)environmentName - namedDelegatePort:(NSString*)namedDelegatePort - apsConnectionClass:(Class)apsConnectionClass ++ (instancetype)receiverForNamedDelegatePort:(NSString*)namedDelegatePort + apsConnectionClass:(Class)apsConnectionClass { - if(environmentName == nil) { - secnotice("octagonpush", "No push environment; not bringing up APS."); - return nil; - } - @synchronized([self class]) { - NSMutableDictionary* environmentMap = [self synchronizedGlobalEnvironmentMap]; + NSMutableDictionary* delegatePortMap = [self synchronizedGlobalDelegatePortMap]; - OctagonAPSReceiver* recv = [environmentMap valueForKey: environmentName]; + OctagonAPSReceiver* recv = delegatePortMap[namedDelegatePort]; if(recv == nil) { - recv = [[OctagonAPSReceiver alloc] initWithEnvironmentName: environmentName namedDelegatePort:namedDelegatePort apsConnectionClass: apsConnectionClass]; - [environmentMap setValue: recv forKey: environmentName]; + recv = [[OctagonAPSReceiver alloc] initWithNamedDelegatePort:namedDelegatePort + apsConnectionClass:apsConnectionClass]; + delegatePortMap[namedDelegatePort] = recv; } return recv; } } -+ (void)resetGlobalEnviornmentMap ++ (void)resetGlobalDelegatePortMap { @synchronized (self) { - [self resettableSynchronizedGlobalEnvironmentMap:YES]; + [self resettableSynchronizedGlobalDelegatePortMap:YES]; } } -+ (NSMutableDictionary*)synchronizedGlobalEnvironmentMap ++ (NSMutableDictionary*)synchronizedGlobalDelegatePortMap { - return [self resettableSynchronizedGlobalEnvironmentMap:NO]; + return [self resettableSynchronizedGlobalDelegatePortMap:NO]; } -+ (NSMutableDictionary*)resettableSynchronizedGlobalEnvironmentMap:(BOOL)reset ++ (NSMutableDictionary*)resettableSynchronizedGlobalDelegatePortMap:(BOOL)reset { - static NSMutableDictionary* environmentMap = nil; + static NSMutableDictionary* delegatePortMap = nil; - if(environmentMap == nil || reset) { - environmentMap = [[NSMutableDictionary alloc] init]; + if(delegatePortMap == nil || reset) { + delegatePortMap = [[NSMutableDictionary alloc] init]; } - return environmentMap; + return delegatePortMap; +} + +- (NSArray*)registeredPushEnvironments +{ + __block NSArray* environments = nil; + dispatch_sync([OctagonAPSReceiver apsDeliveryQueue], ^{ + environments = [self.environmentMap allKeys]; + }); + return environments; } + (dispatch_queue_t)apsDeliveryQueue { @@ -142,66 +149,46 @@ return haveStalePushes; } -- (NSSet*)cuttlefishPushTopics +- (NSArray*)cuttlefishPushTopics { NSString* cuttlefishTopic = [kCKPushTopicPrefix stringByAppendingString:@"com.apple.security.cuttlefish"]; // Currently cuttlefish pushes are sent to TPH. System XPC services can't properly register to be woken // at push time, so receive them for it. NSString* tphTopic = [kCKPushTopicPrefix stringByAppendingString:@"com.apple.TrustedPeersHelper"]; - NSString* securitydTopic = [kCKPushTopicPrefix stringByAppendingString:@"com.apple.securityd"]; - return [NSSet setWithArray:@[cuttlefishTopic, tphTopic, securitydTopic]]; + return @[cuttlefishTopic, tphTopic]; } -- (instancetype)initWithEnvironmentName:(NSString*)environmentName - namedDelegatePort:(NSString*)namedDelegatePort - apsConnectionClass:(Class)apsConnectionClass +- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort + apsConnectionClass:(Class)apsConnectionClass { - return [self initWithEnvironmentName:environmentName - namedDelegatePort:namedDelegatePort - apsConnectionClass:apsConnectionClass - stalePushTimeout:5*60*NSEC_PER_SEC]; + return [self initWithNamedDelegatePort:namedDelegatePort + apsConnectionClass:apsConnectionClass + stalePushTimeout:5*60*NSEC_PER_SEC]; } -- (instancetype)initWithEnvironmentName:(NSString*)environmentName - namedDelegatePort:(NSString*)namedDelegatePort - apsConnectionClass:(Class)apsConnectionClass - stalePushTimeout:(uint64_t)stalePushTimeout +- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort + apsConnectionClass:(Class)apsConnectionClass + stalePushTimeout:(uint64_t)stalePushTimeout { - if(self = [super init]) { + if((self = [super init])) { _apsConnectionClass = apsConnectionClass; - _apsConnection = NULL; - _undeliveredUpdates = [NSMutableDictionary dictionary]; + _undeliveredUpdates = [NSMutableSet set]; _undeliveredCuttlefishUpdates = [[NSMutableSet alloc] init]; - // APS might be slow. This doesn't need to happen immediately, so let it happen later. - WEAKIFY(self); - dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{ - STRONGIFY(self); - if(!self) { - return; - } - self.apsConnection = [[self.apsConnectionClass alloc] initWithEnvironmentName:environmentName namedDelegatePort:namedDelegatePort queue:[OctagonAPSReceiver apsDeliveryQueue]]; - self.apsConnection.delegate = self; + _namedDelegatePort = namedDelegatePort; - // The following string should match: [[NSBundle mainBundle] bundleIdentifier] - NSString* ckksTopic = [kCKPushTopicPrefix stringByAppendingString:@"com.apple.securityd"]; + _environmentMap = [NSMutableDictionary dictionary]; - NSArray* topics = [@[ckksTopic] arrayByAddingObjectsFromArray:[self cuttlefishPushTopics].allObjects]; - [self.apsConnection setEnabledTopics:topics]; -#if TARGET_OS_OSX - [self.apsConnection setDarkWakeTopics:topics]; -#endif - }); - - _zoneMap = [NSMapTable strongToWeakObjectsMapTable]; _octagonContainerMap = [NSMapTable strongToWeakObjectsMapTable]; + _zoneUpdateReceiver = nil; + WEAKIFY(self); void (^clearPushBlock)(void) = ^{ dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{ - NSDictionary*> *droppedUpdates; + NSMutableSet *droppedUpdates; STRONGIFY(self); if (self == nil) { return; @@ -209,7 +196,7 @@ droppedUpdates = self.undeliveredUpdates; - self.undeliveredUpdates = [NSMutableDictionary dictionary]; + self.undeliveredUpdates = [NSMutableSet set]; [self.undeliveredCuttlefishUpdates removeAllObjects]; [self reportDroppedPushes:droppedUpdates]; @@ -225,8 +212,47 @@ return self; } +- (void)registerForEnvironment:(NSString*)environmentName +{ + WEAKIFY(self); + + // APS might be slow. This doesn't need to happen immediately, so let it happen later. + dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{ + STRONGIFY(self); + if(!self) { + return; + } + + id apsConnection = self.environmentMap[environmentName]; + if(apsConnection) { + // We've already set one of these up. + return; + } + + apsConnection = [[self.apsConnectionClass alloc] initWithEnvironmentName:environmentName namedDelegatePort:self.namedDelegatePort queue:[OctagonAPSReceiver apsDeliveryQueue]]; + self.environmentMap[environmentName] = apsConnection; + + apsConnection.delegate = self; + + // The following string should match: [[NSBundle mainBundle] bundleIdentifier] + NSString* ckksTopic = [kCKPushTopicPrefix stringByAppendingString:@"com.apple.securityd"]; + +#if TARGET_OS_WATCH + // Watches treat CKKS as opportunistic, and Octagon as normal priority. + apsConnection.enabledTopics = [self cuttlefishPushTopics]; + apsConnection.opportunisticTopics = @[ckksTopic]; +#else + apsConnection.enabledTopics = [[self cuttlefishPushTopics] arrayByAddingObject:ckksTopic]; +#if TARGET_OS_OSX + apsConnection.darkWakeTopics = self.apsConnection.enabledTopics; +#endif // TARGET_OS_OSX + +#endif // TARGET_OS_WATCH + }); +} + // Report that pushes we are dropping -- (void)reportDroppedPushes:(NSDictionary*>*)notifications +- (void)reportDroppedPushes:(NSSet*)notifications { bool hasBeenUnlocked = false; CFErrorRef error = NULL; @@ -243,44 +269,43 @@ eventName = @"CKKS APNS Push Dropped - never unlocked"; } - for (NSString *zone in notifications) { - for (CKRecordZoneNotification *notification in notifications[zone]) { - if (notification.ckksPushTracingEnabled) { - secnotice("apsnotification", "Submitting initial CKEventMetric due to notification %@", notification); + for (CKRecordZoneNotification *notification in notifications) { + if (notification.ckksPushTracingEnabled) { + ckksnotice_global("apsnotification", "Submitting initial CKEventMetric due to notification %@", notification); - SecEventMetric *metric = [[SecEventMetric alloc] initWithEventName:@"APNSPushMetrics"]; - metric[@"push_token_uuid"] = notification.ckksPushTracingUUID; - metric[@"push_received_date"] = notification.ckksPushReceivedDate; + SecEventMetric *metric = [[SecEventMetric alloc] initWithEventName:@"APNSPushMetrics"]; + metric[@"push_token_uuid"] = notification.ckksPushTracingUUID; + metric[@"push_received_date"] = notification.ckksPushReceivedDate; - metric[@"push_event_name"] = eventName; + metric[@"push_event_name"] = eventName; - [[SecMetrics managerObject] submitEvent:metric]; - } + [[SecMetrics managerObject] submitEvent:metric]; } } } - - -- (CKKSCondition*)registerReceiver:(id)receiver forZoneID:(CKRecordZoneID *)zoneID { +- (CKKSCondition*)registerCKKSReceiver:(id)receiver +{ CKKSCondition* finished = [[CKKSCondition alloc] init]; WEAKIFY(self); dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{ STRONGIFY(self); if(!self) { - secerror("ckks: received registration for released OctagonAPSReceiver"); + ckkserror_global("octagonpush", "received registration for released OctagonAPSReceiver"); return; } - [self.zoneMap setObject:receiver forKey: zoneID.zoneName]; + ckksnotice_global("octagonpush", "Registering new CKKS push receiver: %@", receiver); + + self.zoneUpdateReceiver = receiver; - NSMutableSet* currentPendingMessages = self.undeliveredUpdates[zoneID.zoneName]; - [self.undeliveredUpdates removeObjectForKey:zoneID.zoneName]; + NSMutableSet* currentPendingMessages = [self.undeliveredUpdates copy]; + [self.undeliveredUpdates removeAllObjects]; for(CKRecordZoneNotification* message in currentPendingMessages.allObjects) { // Now, send the receiver its notification! - secerror("ckks: sending stored push(%@) to newly-registered zone(%@): %@", message, zoneID.zoneName, receiver); + ckkserror_global("octagonpush", "sending stored push(%@) to newly-registered receiver: %@", message, receiver); [receiver notifyZoneChange:message]; } @@ -299,7 +324,7 @@ dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{ STRONGIFY(self); if(!self) { - secerror("octagon: received registration for released OctagonAPSReceiver"); + ckkserror_global("octagonpush", "received registration for released OctagonAPSReceiver"); return; } @@ -308,7 +333,7 @@ [self.undeliveredCuttlefishUpdates removeObject:containerName]; // Now, send the receiver its fake notification! - secerror("octagon: sending fake push to newly-registered cuttlefish receiver(%@): %@", containerName, receiver); + ckkserror_global("octagonpush", "sending fake push to newly-registered cuttlefish receiver(%@): %@", containerName, receiver); [receiver notifyContainerChange:nil]; } @@ -322,29 +347,27 @@ - (void)connection:(APSConnection *)connection didReceivePublicToken:(NSData *)publicToken { // no-op. - secnotice("octagonpush", "OctagonAPSDelegate initiated: %@", connection); + ckksnotice_global("octagonpush", "OctagonAPSDelegate initiated: %@", connection); } - (void)connection:(APSConnection *)connection didReceiveToken:(NSData *)token forTopic:(NSString *)topic identifier:(NSString *)identifier { - secnotice("octagonpush", "Received per-topic push token \"%@\" for topic \"%@\" identifier \"%@\" on connection %@", token, topic, identifier, connection); + ckksnotice_global("octagonpush", "Received per-topic push token \"%@\" for topic \"%@\" identifier \"%@\" on connection %@", token, topic, identifier, connection); } - (void)connection:(APSConnection *)connection didReceiveIncomingMessage:(APSIncomingMessage *)message { - secnotice("octagonpush", "OctagonAPSDelegate received a message(%@): %@ ", message.topic, message.userInfo); + ckksnotice_global("octagonpush", "OctagonAPSDelegate received a message(%@): %@ ", message.topic, message.userInfo); // Report back through APS that we received a message if(message.tracingEnabled) { [connection confirmReceiptForMessage:message]; } - NSSet* cuttlefishTopics = [self cuttlefishPushTopics]; - // Separate and handle cuttlefish notifications - if([cuttlefishTopics containsObject:message.topic] && [message.userInfo objectForKey:@"cf"]) { + if(message.userInfo[@"cf"] != nil) { NSDictionary* cfInfo = message.userInfo[@"cf"]; NSString* container = cfInfo[@"c"]; - secnotice("octagonpush", "Received a cuttlefish push to container %@", container); + ckksnotice_global("octagonpush", "Received a cuttlefish push to container %@", container); [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastOctagonPush]; if(container) { @@ -353,7 +376,7 @@ if(receiver) { [receiver notifyContainerChange:message]; } else { - secerror("octagonpush: received cuttlefish push for unregistered container: %@", container); + ckkserror_global("octagonpush", "received cuttlefish push for unregistered container: %@", container); [self.undeliveredCuttlefishUpdates addObject:container]; [self.clearStalePushNotifications trigger]; } @@ -380,23 +403,16 @@ [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastCKKSPush]; // Find receiever in map - id recv = [self.zoneMap objectForKey:rznotification.recordZoneID.zoneName]; + id recv = self.zoneUpdateReceiver; if(recv) { [recv notifyZoneChange:rznotification]; } else { - secerror("ckks: received push for unregistered zone: %@", rznotification); - if(rznotification.recordZoneID) { - NSMutableSet* currentPendingMessages = self.undeliveredUpdates[rznotification.recordZoneID.zoneName]; - if(currentPendingMessages) { - [currentPendingMessages addObject:rznotification]; - } else { - self.undeliveredUpdates[rznotification.recordZoneID.zoneName] = [NSMutableSet setWithObject:rznotification]; - [self.clearStalePushNotifications trigger]; - } - } + ckkserror_global("ckkspush", "received push for unregistered receiver: %@", rznotification); + [self.undeliveredUpdates addObject:rznotification]; + [self.clearStalePushNotifications trigger]; } } else { - secerror("ckks: unexpected notification: %@", notification); + ckkserror_global("ckkspush", "unexpected notification: %@", notification); } } diff --git a/keychain/ckks/RateLimiter.m b/keychain/ckks/RateLimiter.m index 1dd84320..ed7fb034 100644 --- a/keychain/ckks/RateLimiter.m +++ b/keychain/ckks/RateLimiter.m @@ -22,8 +22,8 @@ */ #import "RateLimiter.h" -#import #import "sec_action.h" +#import "keychain/ckks/CKKS.h" #import // For clarity. Also included in debugging.h @interface RateLimiter() @@ -37,8 +37,7 @@ @implementation RateLimiter - (instancetype)initWithConfig:(NSDictionary *)config { - self = [super init]; - if (self) { + if ((self = [super init])) { _config = config; _assetType = nil; [self reset]; @@ -50,8 +49,7 @@ if (!coder) { return nil; } - self = [super init]; - if (self) { + if ((self = [super init])) { _groups = [coder decodeObjectOfClasses:[NSSet setWithObjects: [NSArray class], [NSMutableDictionary class], [NSString class], @@ -87,7 +85,7 @@ dispatch_once(&token, ^{ action = sec_action_create("ratelimiterdisabledlogevent", 60); sec_action_set_handler(action, ^{ - secnotice("ratelimit", "Rate limiting disabled, returning automatic all-clear"); + ckksnotice_global("ratelimit", "Rate limiting disabled, returning automatic all-clear"); }); }); sec_action_perform(action); @@ -135,7 +133,7 @@ // approved properties 'accessGroup' and 'uuid' and if the item doesn't have either it's sad times anyway. // Improve rate limiter error handling if (!name) { - secerror("RateLimiter[%@]: Got nil instead of property named %@", self.config[@"general"][@"name"], groupConfig[@"property"]); + ckkserror_global("ratelimiter", "RateLimiter[%@]: Got nil instead of property named %@", self.config[@"general"][@"name"], groupConfig[@"property"]); continue; } NSDate *singleTokenTime = [self consumeTokenFromBucket:self.groups[idx] @@ -205,7 +203,7 @@ if ([self stateSize] > [self.config[@"general"][@"maxStateSize"] unsignedIntegerValue]) { // Trimming did not reduce size (enough), we need to take measures self.overloadUntil = [time dateByAddingTimeInterval:[self.config[@"general"][@"overloadDuration"] unsignedIntValue]]; - secerror("RateLimiter[%@] state size %lu exceeds max %lu, overloaded until %@", + ckkserror_global("ratelimiter", "RateLimiter[%@] state size %lu exceeds max %lu, overloaded until %@", self.config[@"general"][@"name"], (unsigned long)[self stateSize], [self.config[@"general"][@"maxStateSize"] unsignedLongValue], diff --git a/keychain/ckks/tests/AutoreleaseTest.c b/keychain/ckks/tests/AutoreleaseTest.c index 796ef505..81fb47f4 100644 --- a/keychain/ckks/tests/AutoreleaseTest.c +++ b/keychain/ckks/tests/AutoreleaseTest.c @@ -41,8 +41,7 @@ read_releases_pending(int fd, void (^handler)(ssize_t)) char *line = NULL; size_t linecap = 0; - ssize_t linelen; - while ((linelen = getline(&line, &linecap, fp)) > 0) { + while (getline(&line, &linecap, fp) > 0) { ssize_t pending; if (sscanf(line, "objc[%*d]: %ld releases pending", &pending) == 1) { diff --git a/keychain/ckks/tests/CKKSAESSIVEncryptionTests.m b/keychain/ckks/tests/CKKSAESSIVEncryptionTests.m index 1dc7249f..5c395edc 100644 --- a/keychain/ckks/tests/CKKSAESSIVEncryptionTests.m +++ b/keychain/ckks/tests/CKKSAESSIVEncryptionTests.m @@ -308,7 +308,13 @@ NSData* testCKRecord = [@"nonsense" dataUsingEncoding:NSUTF8StringEncoding]; CKKSKey* tlk = [self fakeTLK:self.testZoneID]; - [tlk saveToDatabase:&error]; + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [tlk saveToDatabase:&saveError]; + XCTAssertNil(saveError, "tlk saved to database without error"); + return CKKSDatabaseTransactionCommit; + }]; + [tlk saveKeyMaterialToKeychain:&error]; XCTAssertNil(error, "tlk saved to database without error"); @@ -317,15 +323,24 @@ XCTAssertNotNil(level1, "level 1 key created"); XCTAssertNil(error, "level 1 key created"); - [level1 saveToDatabase:&error]; - XCTAssertNil(error, "level 1 key saved to database without error"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [level1 saveToDatabase:&saveError]; + XCTAssertNil(saveError, "level 1 key saved to database without error"); + return CKKSDatabaseTransactionCommit; + }]; CKKSKey* level2 = [CKKSKey randomKeyWrappedByParent: level1 error:&error]; level2.encodedCKRecord = testCKRecord; XCTAssertNotNil(level2, "level 2 key created"); XCTAssertNil(error, "no error creating level 2 key"); - [level2 saveToDatabase:&error]; - XCTAssertNil(error, "level 2 key saved to database without error"); + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [level2 saveToDatabase:&saveError]; + XCTAssertNil(saveError, "level 2 key saved to database without error"); + return CKKSDatabaseTransactionCommit; + }]; NSString* level2UUID = level2.uuid; @@ -344,8 +359,14 @@ - (void)ensureKeychainSaveLoad: (CKKSKey*) key { NSError* error = nil; - [key saveToDatabase:&error]; - XCTAssertNil(error, "no error saving to database"); + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [key saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error saving to database"); + return CKKSDatabaseTransactionCommit; + }]; + [key saveKeyMaterialToKeychain:&error]; XCTAssertNil(error, "no error saving to keychain"); @@ -421,7 +442,12 @@ NSString *uuid = @"8b2aeb7f-4af3-43e9-b6e6-70d5c728ebf7"; CKKSKey* key = [self fakeTLK:self.testZoneID]; - [key saveToDatabase: &error]; + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [key saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error saving to database"); + return CKKSDatabaseTransactionCommit; + }]; [key saveKeyMaterialToKeychain:&error]; XCTAssertNil(error, @"could save the fake TLK to the database"); @@ -467,9 +493,15 @@ error:&error]; XCTAssertNil(error); CKKSKey* key = [self fakeTLK:self.testZoneID]; - [key saveToDatabase: &error]; + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [key saveToDatabase:&saveError]; + XCTAssertNil(saveError, "could save the fake TLK to the database"); + return CKKSDatabaseTransactionCommit; + }]; [key saveKeyMaterialToKeychain:&error]; - XCTAssertNil(error, @"could save the fake TLK to the database"); + XCTAssertNil(error, @"could save the fake TLK to the keychain"); CKKSAESSIVKey* keyToWrap = [[CKKSAESSIVKey alloc] initWithBase64: @"uImdbZ7Zg+6WJXScTnRBfNmoU1UiMkSYxWc+d1Vuq3IFn2RmTRkTdWTe3HmeWo1pAomqy+upK8KHg2PGiRGhqg=="]; CKKSWrappedAESSIVKey* wrappedKey = [key wrapAESKey: keyToWrap error:&error]; @@ -735,7 +767,7 @@ memset((unsigned char *)[data mutableBytes], 0x55, 23); NSData *padded = [CKKSItemEncrypter padData:data blockSize:0 additionalBlock:extra]; XCTAssertNotNil(padded, "Padding never returns nil"); - XCTAssertTrue(padded.length == data.length + extra ? 2 : 1, "One byte of padding has been added, 2 if extra padding"); + XCTAssertTrue(padded.length == data.length + (extra ? 2 : 1), "One byte of padding has been added, 2 if extra padding"); NSData *unpadded = [CKKSItemEncrypter removePaddingFromData:padded]; XCTAssertNotNil(unpadded, "Successfully removed padding again"); XCTAssertEqualObjects(data, unpadded, "Data effectively unmodified through padding-unpadding trip"); diff --git a/keychain/ckks/tests/CKKSAPSHandlingTests.m b/keychain/ckks/tests/CKKSAPSHandlingTests.m index 4aa357ac..3a5e8077 100644 --- a/keychain/ckks/tests/CKKSAPSHandlingTests.m +++ b/keychain/ckks/tests/CKKSAPSHandlingTests.m @@ -144,9 +144,8 @@ // Inject a message at the APS layer // Because we can only make APS receivers once iCloud tells us the push environment after sign-in, we can't use our normal injection strategy, and fell back on global state. - OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForEnvironment:self.apsEnvironment - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; + OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:[FakeAPSConnection class]]; XCTAssertNotNil(apsReceiver, "Should have gotten an APS receiver"); // Also, CKKS should handle this in one single fetch @@ -209,9 +208,8 @@ // Inject a message at the APS layer // Because we can only make APS receivers once iCloud tells us the push environment after sign-in, we can't use our normal injection strategy, and fell back on global state. - OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForEnvironment:self.apsEnvironment - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; + OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:[FakeAPSConnection class]]; XCTAssertNotNil(apsReceiver, "Should have gotten an APS receiver"); // Also, CKKS should handle this in one single fetch @@ -224,6 +222,7 @@ // Launch! [apsReceiver connection:nil didReceiveIncomingMessage:apsMessage]; OCMVerifyAllWithDelay(self.mockContainerExpectations, 16); + OCMVerifyAllWithDelay(self.mockDatabase, 20); // Now, wait for both views to run their processing [keychainProcessTimeoutOp waitUntilFinished]; @@ -258,14 +257,10 @@ // Inject a message at the APS layer // Because we can only make APS receivers once iCloud tells us the push environment after sign-in, we can't use our normal injection strategy, and fell back on global state. - OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForEnvironment:self.apsEnvironment - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; + OctagonAPSReceiver* apsReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:[FakeAPSConnection class]]; XCTAssertNotNil(apsReceiver, "Should have gotten an APS receiver"); - [apsReceiver connection:nil didReceiveIncomingMessage:apsMessage]; - [apsReceiver connection:nil didReceiveIncomingMessage:apsMessage2]; - // Expect four metric pushes, two per push: one from receiving the push and one from after we finish the fetch // AFAICT there's no way to introspect a metric object to ensure we did it right OCMExpect([self.mockContainerExpectations submitEventMetric:[OCMArg any]]); @@ -273,6 +268,9 @@ OCMExpect([self.mockContainerExpectations submitEventMetric:[OCMArg any]]); OCMExpect([self.mockContainerExpectations submitEventMetric:[OCMArg any]]); + [apsReceiver connection:nil didReceiveIncomingMessage:apsMessage]; + [apsReceiver connection:nil didReceiveIncomingMessage:apsMessage2]; + // Launch! CKKSKeychainView* pushTestView = [self.injectedManager findOrCreateView:pushTestZone.zoneName]; [self.ckksViews addObject:pushTestView]; @@ -291,8 +289,7 @@ APSIncomingMessage* apsMessage = [CKKSAPSHandlingTests messageWithTracingEnabledForZoneID:pushTestZone]; // Don't use the global map here, because we need to ensure we create a new object (to use the stalePushTimeout we injected above) - OctagonAPSReceiver* apsReceiver = OCMPartialMock([[OctagonAPSReceiver alloc] initWithEnvironmentName:self.apsEnvironment - namedDelegatePort:SecCKKSAPSNamedPort + OctagonAPSReceiver* apsReceiver = OCMPartialMock([[OctagonAPSReceiver alloc] initWithNamedDelegatePort:SecCKKSAPSNamedPort apsConnectionClass:[FakeAPSConnection class] stalePushTimeout:4 * NSEC_PER_SEC]); XCTAssertNotNil(apsReceiver, "Should have gotten an APS receiver"); diff --git a/keychain/ckks/tests/CKKSCloudKitTests.m b/keychain/ckks/tests/CKKSCloudKitTests.m deleted file mode 100644 index 82239815..00000000 --- a/keychain/ckks/tests/CKKSCloudKitTests.m +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright (c) 2017 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@ - */ - -#import -#import -#import - -#import -#import -#import "keychain/securityd/SecItemServer.h" -#if NO_SERVER -#include "keychain/securityd/spi.h" -#endif - -#import "keychain/ckks/CKKS.h" -#import "keychain/ckks/CKKSViewManager.h" -#import "keychain/ckks/CKKSKeychainView.h" -#import "keychain/ckks/CKKSCurrentKeyPointer.h" -#import "keychain/ckks/CKKSMirrorEntry.h" -#import "keychain/ckks/CKKSItemEncrypter.h" -#import "keychain/ckks/CloudKitCategories.h" -#import "keychain/categories/NSError+UsefulConstructors.h" -#import "keychain/ckks/tests/MockCloudKit.h" -#import "keychain/ot/OTManager.h" - -@interface CKKSCloudKitTests : XCTestCase - -@property NSOperationQueue *operationQueue; -@property CKContainer *container; -@property CKDatabase *database; -@property CKKSKeychainView *kcv; -@property NSString *zoneName; -@property CKRecordZoneID *zoneID; -@property NSDictionary *remoteItems; -@property NSInteger queueTimeout; - -@end - -// TODO: item modification should up gencount, check this - -@implementation CKKSCloudKitTests - -#if OCTAGON - -#pragma mark Setup - -+ (void)setUp { - SecCKKSResetSyncing(); - SecCKKSTestsEnable(); - SecCKKSSetReduceRateLimiting(true); - [super setUp]; - -#if NO_SERVER - securityd_init_local_spi(); -#endif -} - -- (void)setUp { - self.remoteItems = nil; - self.queueTimeout = 900; // CloudKit can be *very* slow, and some tests upload a lot of items indeed - NSString *containerName = [NSString stringWithFormat:@"com.apple.test.p01.B.com.apple.security.keychain.%@", [[NSUUID new] UUIDString]]; - self.container = [CKContainer containerWithIdentifier:containerName]; - - SecCKKSTestResetFlags(); - SecCKKSTestSetDisableSOS(true); - - self.operationQueue = [NSOperationQueue new]; - - CKKSCloudKitClassDependencies* cloudKitClassDependencies = [[CKKSCloudKitClassDependencies alloc] initWithFetchRecordZoneChangesOperationClass:[CKFetchRecordZoneChangesOperation class] - fetchRecordsOperationClass:[CKFetchRecordsOperation class] - queryOperationClass:[CKQueryOperation class] - modifySubscriptionsOperationClass:[CKModifySubscriptionsOperation class] - modifyRecordZonesOperationClass:[CKModifyRecordZonesOperation class] - apsConnectionClass:[APSConnection class] - nsnotificationCenterClass:[NSNotificationCenter class] - nsdistributednotificationCenterClass:[NSDistributedNotificationCenter class] - notifierClass:[FakeCKKSNotifier class]]; - - CKContainer* container = [CKKSViewManager makeCKContainer:SecCKKSContainerName usePCS:SecCKKSContainerUsePCS]; - CKKSAccountStateTracker* accountStateTracker = [[CKKSAccountStateTracker alloc] init:container - nsnotificationCenterClass:cloudKitClassDependencies.nsnotificationCenterClass]; - - CKKSLockStateTracker* lockStateTracker = [[CKKSLockStateTracker alloc] init]; - - CKKSViewManager* manager = [[CKKSViewManager alloc] initWithContainer:container - sosAdapter:nil - accountStateTracker:accountStateTracker - lockStateTracker:lockStateTracker - cloudKitClassDependencies:cloudKitClassDependencies]; - // No longer a supported mechanism: - //[CKKSViewManager resetManager:false setTo:manager]; - (void)manager; - - // Make a new fake keychain - NSString* smallName = [self.name componentsSeparatedByString:@" "][1]; - smallName = [smallName stringByReplacingOccurrencesOfString:@"]" withString:@""]; - - NSString* tmp_dir = [NSString stringWithFormat: @"/tmp/%@.%X", smallName, arc4random()]; - [[NSFileManager defaultManager] createDirectoryAtPath:[NSString stringWithFormat: @"%@/Library/Keychains", tmp_dir] withIntermediateDirectories:YES attributes:nil error:NULL]; - - SetCustomHomeURLString((__bridge CFStringRef) tmp_dir); - SecKeychainDbReset(NULL); - // Actually load the database. - kc_with_dbt(true, NULL, ^bool (SecDbConnectionRef dbt) { return false; }); - - self.zoneName = @"keychain"; - self.zoneID = [[CKRecordZoneID alloc] initWithZoneName:self.zoneName ownerName:CKCurrentUserDefaultName]; - self.kcv = [[CKKSViewManager manager] findOrCreateView:@"keychain"]; -} - -- (void)tearDown { - self.remoteItems = nil; - [[CKKSViewManager manager] clearView:@"keychain"]; - SecCKKSTestResetFlags(); -} - -+ (void)tearDown { - SecCKKSResetSyncing(); -} - -#pragma mark Helpers - -- (BOOL)waitForEmptyOutgoingQueue:(CKKSKeychainView *)view { - [view processOutgoingQueue:[CKOperationGroup CKKSGroupWithName:@"waitForEmptyOutgoingQueue"]]; - NSInteger secondsToWait = self.queueTimeout; - while (true) { - if ([view outgoingQueueEmpty:nil]) { - return YES; - } - [NSThread sleepForTimeInterval:1]; - if (--secondsToWait % 60 == 0) { - long minutesWaited = (self.queueTimeout - secondsToWait)/60; - NSLog(@"Waiting %ld minute%@ for empty outgoingQueue", minutesWaited, minutesWaited > 1 ? @"s" : @""); - } - if (secondsToWait <= 0) { - XCTFail(@"Timed out waiting for '%@' OutgoingQueue to become empty", view); - NSLog(@"Giving up waiting for empty outgoingQueue"); - return NO; - } - - } -} - -- (void)startCKKSSubsystem { - // TODO: we removed this mechanism, but haven't tested to see if these tests still succeed -} - -- (NSMutableDictionary *)fetchLocalItems { - NSDictionary *query = @{(id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - (id)kSecReturnAttributes : (id)kCFBooleanTrue, - (id)kSecReturnData : (id)kCFBooleanTrue, - (id)kSecMatchLimit : (id)kSecMatchLimitAll, - }; - CFTypeRef cfresults; - OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &cfresults); - XCTAssert(status == errSecSuccess || status == errSecItemNotFound, @"retrieved zero or more local items"); - if (status == errSecItemNotFound) { - return [NSMutableDictionary new]; - } else if (status != errSecSuccess) { - return nil; - } - - NSArray *results = CFBridgingRelease(cfresults); - - NSMutableDictionary *ret = [NSMutableDictionary new]; - for (NSMutableDictionary *item in results) { - ret[item[@"UUID"]] = item; - } - - return ret; -} - -- (NSMutableDictionary *)fetchRemoteItems { - CKFetchRecordZoneChangesConfiguration *options = [CKFetchRecordZoneChangesConfiguration new]; - options.previousServerChangeToken = nil; - - CKFetchRecordZoneChangesOperation *op = [[CKFetchRecordZoneChangesOperation alloc] initWithRecordZoneIDs:@[self.zoneID] configurationsByRecordZoneID:@{self.zoneID : options}]; - op.configuration.automaticallyRetryNetworkFailures = NO; - op.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; - op.configuration.isCloudKitSupportOperation = YES; - op.configuration.container = self.container; - - __block NSMutableDictionary *data = [NSMutableDictionary new]; - __block NSUInteger synckeys = 0; - __block NSUInteger currkeys = 0; - op.recordChangedBlock = ^(CKRecord *record) { - if ([record.recordType isEqualToString:SecCKRecordItemType]) { - data[record.recordID.recordName] = [self decryptRecord:record]; - } else if ([record.recordType isEqualToString:SecCKRecordIntermediateKeyType]) { - synckeys += 1; - } else if ([record.recordType isEqualToString:SecCKRecordCurrentKeyType]) { - currkeys += 1; - } else { - XCTFail(@"Encountered unexpected item %@", record); - } - }; - - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - op.recordZoneFetchCompletionBlock = ^(CKRecordZoneID * _Nonnull recordZoneID, - CKServerChangeToken * _Nullable serverChangeToken, - NSData * _Nullable clientChangeTokenData, - BOOL moreComing, - NSError * _Nullable recordZoneError) { - XCTAssertNil(recordZoneError, @"No error in recordZoneFetchCompletionBlock"); - if (!moreComing) { - dispatch_semaphore_signal(sema); - } - }; - - [op start]; - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - - // These are new, fresh zones for each test. There should not be old keys yet. - if (synckeys != 3) {XCTFail(@"Unexpected number of synckeys: %lu", (unsigned long)synckeys);} - if (currkeys != 3) {XCTFail(@"Unexpected number of current keys: %lu", (unsigned long)currkeys);} - - self.remoteItems = data; - return data; -} - -- (BOOL)compareLocalItem:(NSDictionary *)lhs remote:(NSDictionary *)rhs { - if ([lhs[@"cdat"] compare: rhs[@"cdat"]] != NSOrderedSame) {XCTFail(@"Creation date differs"); return NO;} - if ([lhs[@"mdat"] compare: rhs[@"mdat"]] != NSOrderedSame) {XCTFail(@"Modification date differs"); return NO;} - if (![lhs[@"agrp"] isEqualToString:rhs[@"agrp"]]) {XCTFail(@"Access group differs"); return NO;} - if (![lhs[@"acct"] isEqualToString:rhs[@"acct"]]) {XCTFail(@"Account differs"); return NO;} - if (![lhs[@"v_Data"] isEqualToData:rhs[@"v_Data"]]) {XCTFail(@"Data differs"); return NO;} - // class for lhs is already genp due to copymatching query - if (![rhs[@"class"] isEqualToString:@"genp"]) {XCTFail(@"Class not genp for remote item"); return NO;} - return YES; -} - -- (BOOL)compareLocalKeychainWithCloudKitState { - BOOL success = YES; - NSMutableDictionary *localItems = [self fetchLocalItems]; - if (localItems == nil) {XCTFail(@"Received nil for localItems"); return NO;} - NSMutableDictionary *remoteItems = [self fetchRemoteItems]; - if (remoteItems == nil) {XCTFail(@"Received nil for remoteItems"); return NO;} - - for (NSString *uuid in localItems.allKeys) { - if (remoteItems[uuid] == nil) { - XCTFail(@"account %@ item %@ not present in remote", localItems[uuid][@"acct"], localItems[uuid]); - success = NO; - continue; - } - if (![self compareLocalItem:localItems[uuid] remote:remoteItems[uuid]]) { - XCTFail(@"local item %@ matches remote item %@", localItems[uuid], remoteItems[uuid]); - success = NO; - } - [remoteItems removeObjectForKey:uuid]; - } - if ([remoteItems count]) { - XCTFail(@"No remote items present not found in local, %@", remoteItems); - return NO; - } - return success; -} - -- (BOOL)updateGenericPassword:(NSString *)password account:(NSString *)account { - NSDictionary *query = @{(id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, - (id)kSecAttrAccount : account, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - }; - NSDictionary *newpasswd = @{(id)kSecValueData : (id) [password dataUsingEncoding:NSUTF8StringEncoding]}; - - return errSecSuccess == SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)newpasswd); -} - -- (BOOL)uploadRecords:(NSArray*)records { - CKModifyRecordsOperation *op = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:records recordIDsToDelete:nil]; - op.configuration.automaticallyRetryNetworkFailures = NO; - op.configuration.discretionaryNetworkBehavior = CKOperationDiscretionaryNetworkBehaviorNonDiscretionary; - op.configuration.isCloudKitSupportOperation = YES; - op.configuration.container = self.container; - - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - __block BOOL result = NO; - op.modifyRecordsCompletionBlock = ^(NSArray *savedRecords, - NSArray *deletedRecordIDs, - NSError *operationError) { - XCTAssertNil(operationError, @"No error uploading records, %@", operationError); - if (operationError == nil) { - result = YES; - } - dispatch_semaphore_signal(sema); - }; - - [op start]; - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - - return result; -} - -#pragma mark Helpers Adapted from MockXCTest - -- (CKRecord*)createFakeRecord: (CKRecordZoneID*)zoneID recordName:(NSString*)recordName { - return [self createFakeRecord: zoneID recordName:recordName withAccount: nil]; -} - -- (CKRecord*)createFakeRecord: (CKRecordZoneID*)zoneID recordName:(NSString*)recordName withAccount: (NSString*) account { - NSError* error = nil; - - /* Basically: @{ - @"acct" : @"account-delete-me", - @"agrp" : @"com.apple.security.sos", - @"cdat" : @"2016-12-21 03:33:25 +0000", - @"class" : @"genp", - @"mdat" : @"2016-12-21 03:33:25 +0000", - @"musr" : [[NSData alloc] init], - @"pdmn" : @"ak", - @"sha1" : [[NSData alloc] initWithBase64EncodedString: @"C3VWONaOIj8YgJjk/xwku4By1CY=" options:0], - @"svce" : @"", - @"tomb" : [NSNumber numberWithInt: 0], - @"v_Data" : [@"data" dataUsingEncoding: NSUTF8StringEncoding], - }; - TODO: this should be binary encoded instead of expanded, but the plist encoder should handle it fine */ - NSData* itemdata = [[NSData alloc] initWithBase64EncodedString:@"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8ZGljdD4KCTxrZXk+YWNjdDwva2V5PgoJPHN0cmluZz5hY2NvdW50LWRlbGV0ZS1tZTwvc3RyaW5nPgoJPGtleT5hZ3JwPC9rZXk+Cgk8c3RyaW5nPmNvbS5hcHBsZS5zZWN1cml0eS5zb3M8L3N0cmluZz4KCTxrZXk+Y2RhdDwva2V5PgoJPGRhdGU+MjAxNi0xMi0yMVQwMzozMzoyNVo8L2RhdGU+Cgk8a2V5PmNsYXNzPC9rZXk+Cgk8c3RyaW5nPmdlbnA8L3N0cmluZz4KCTxrZXk+bWRhdDwva2V5PgoJPGRhdGU+MjAxNi0xMi0yMVQwMzozMzoyNVo8L2RhdGU+Cgk8a2V5Pm11c3I8L2tleT4KCTxkYXRhPgoJPC9kYXRhPgoJPGtleT5wZG1uPC9rZXk+Cgk8c3RyaW5nPmFrPC9zdHJpbmc+Cgk8a2V5PnNoYTE8L2tleT4KCTxkYXRhPgoJQzNWV09OYU9JajhZZ0pqay94d2t1NEJ5MUNZPQoJPC9kYXRhPgoJPGtleT5zdmNlPC9rZXk+Cgk8c3RyaW5nPjwvc3RyaW5nPgoJPGtleT50b21iPC9rZXk+Cgk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJPGtleT52X0RhdGE8L2tleT4KCTxkYXRhPgoJWkdGMFlRPT0KCTwvZGF0YT4KPC9kaWN0Pgo8L3BsaXN0Pgo=" options:0]; - NSMutableDictionary * item = [[NSPropertyListSerialization propertyListWithData:itemdata - options:0 - format:nil - error:&error] mutableCopy]; - // Fix up dictionary - item[@"agrp"] = @"com.apple.security.ckks"; - - XCTAssertNil(error, "interpreted data as item"); - - if(account) { - [item setObject: account forKey: (__bridge id) kSecAttrAccount]; - } - - CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:recordName zoneID:zoneID]; - return [self newRecord: ckrid withNewItemData: item]; -} - -- (CKRecord*)newRecord: (CKRecordID*) recordID withNewItemData:(NSDictionary*) dictionary { - NSError* error = nil; - CKKSKey* classCKey = [CKKSKey currentKeyForClass:SecCKKSKeyClassC zoneID:recordID.zoneID error:&error]; - XCTAssertNotNil(classCKey, "Have class C key for zone"); - - CKKSItem* cipheritem = [CKKSItemEncrypter encryptCKKSItem:[[CKKSItem alloc] initWithUUID:recordID.recordName - parentKeyUUID:classCKey.uuid - zoneID:recordID.zoneID] - dataDictionary:dictionary - updatingCKKSItem:nil - parentkey:classCKey - error:&error]; - - CKKSOutgoingQueueEntry* ciphertext = [[CKKSOutgoingQueueEntry alloc] initWithCKKSItem:cipheritem - action:SecCKKSActionAdd - state:SecCKKSStateNew - waitUntil:nil - accessGroup:@"unused in this function"]; - XCTAssertNil(error, "encrypted item with class c key"); - - CKRecord* ckr = [ciphertext.item CKRecordWithZoneID: recordID.zoneID]; - XCTAssertNotNil(ckr, "Created a CKRecord"); - return ckr; -} - -- (NSDictionary*)decryptRecord: (CKRecord*) record { - CKKSMirrorEntry* ckme = [[CKKSMirrorEntry alloc] initWithCKRecord: record]; - - NSError* error = nil; - - NSDictionary* ret = [CKKSItemEncrypter decryptItemToDictionary:ckme.item error:&error]; - XCTAssertNil(error); - XCTAssertNotNil(ret); - return ret; -} - -- (BOOL)addMultiplePasswords:(NSString *)password account:(NSString *)account amount:(NSUInteger)amount { - while (amount > 0) { - if (![self addGenericPassword:password account:[NSString stringWithFormat:@"%@%03lu", account, amount]]) { - return NO; - } - amount -= 1; - } - return YES; -} - -- (BOOL)deleteMultiplePasswords:(NSString *)account amount:(NSUInteger)amount { - while (amount > 0) { - if (![self deleteGenericPassword:[NSString stringWithFormat:@"%@%03lu", account, amount]]) { - return NO; - } - amount -= 1; - } - return YES; -} - -- (BOOL)addGenericPassword: (NSString*) password account: (NSString*) account viewHint: (NSString*) viewHint expecting: (OSStatus) status message: (NSString*) message { - NSMutableDictionary* query = [@{ - (id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, - (id)kSecAttrAccount : account, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - (id)kSecValueData : (id) [password dataUsingEncoding:NSUTF8StringEncoding], - } mutableCopy]; - - if(viewHint) { - query[(id)kSecAttrSyncViewHint] = viewHint; - } - - return status == SecItemAdd((__bridge CFDictionaryRef) query, NULL); -} - -- (BOOL)addGenericPassword: (NSString*) password account: (NSString*) account expecting: (OSStatus) status message: (NSString*) message { - return [self addGenericPassword:password account:account viewHint:nil expecting:errSecSuccess message:message]; -} - -- (BOOL)addGenericPassword: (NSString*) password account: (NSString*) account { - return [self addGenericPassword:password account:account viewHint:nil expecting:errSecSuccess message:@"Add item to keychain"]; -} - -- (BOOL)addGenericPassword: (NSString*) password account: (NSString*) account viewHint:(NSString*)viewHint { - return [self addGenericPassword:password account:account viewHint:viewHint expecting:errSecSuccess message:@"Add item to keychain with a viewhint"]; -} - -- (BOOL)deleteGenericPassword: (NSString*) account { - NSDictionary* query = @{(id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccount : account, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue,}; - - return errSecSuccess == SecItemDelete((__bridge CFDictionaryRef) query); -} - -- (BOOL)findGenericPassword: (NSString*) account expecting: (OSStatus) status { - NSDictionary *query = @{(id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccount : account, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - (id)kSecMatchLimit : (id)kSecMatchLimitOne,}; - - return status == SecItemCopyMatching((__bridge CFDictionaryRef) query, NULL); -} - -- (void)checkGenericPassword: (NSString*) password account: (NSString*) account { - NSDictionary *query = @{(id)kSecClass : (id)kSecClassGenericPassword, - (id)kSecAttrAccessGroup : @"com.apple.security.ckks", - (id)kSecAttrAccount : account, - (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, - (id)kSecMatchLimit : (id)kSecMatchLimitOne, - (id)kSecReturnData : (id)kCFBooleanTrue, - }; - CFTypeRef result = NULL; - - XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &result), "Finding item %@", account); - XCTAssertNotNil((__bridge id)result, "Received an item"); - - NSString* storedPassword = [[NSString alloc] initWithData: (__bridge NSData*) result encoding: NSUTF8StringEncoding]; - XCTAssertNotNil(storedPassword, "Password parsed as a password"); - - XCTAssertEqualObjects(storedPassword, password, "Stored password matches received password"); -} - -#pragma mark Tests - -- (void)testAddDelete { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - XCTAssert([self addGenericPassword:@"data" account:@"ck-test-adddelete"], @"Added single item"); - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAdd: states match after add"); - - XCTAssert([self deleteGenericPassword:@"ck-test-adddelete"], @"Deleted single item"); - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAdd: states match after delete"); -} - -- (void)testAddModDelete { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - [self addGenericPassword:@"data" account:@"ck-test-addmoddelete"]; - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMod: states match after add"); - - [self updateGenericPassword:@"otherdata" account:@"ck-test-addmoddelete"]; - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMod: states match after mod"); - - [self deleteGenericPassword:@"ck-test-addmoddelete"]; - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMod: states match after del"); -} - -- (void)testAddModDeleteImmediate { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - XCTAssert([self addGenericPassword:@"data" account:@"ck-test-addmoddeleteimmediate"], @"Added item"); - XCTAssert([self updateGenericPassword:@"otherdata" account:@"ck-test-addmoddeleteimmediate"], @"Modified item"); - XCTAssert([self deleteGenericPassword:@"ck-test-addmoddeleteimmediate"], @"Deleted item"); - - [self waitForEmptyOutgoingQueue:self.kcv]; - [self.kcv waitForFetchAndIncomingQueueProcessing]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMod: states match after immediate add/mod/delete"); -} - -- (void)testReceive { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - [self findGenericPassword:@"ck-test-receive" expecting:errSecItemNotFound]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testReceive: states match before receive"); - - CKRecord *record = [self createFakeRecord:self.zoneID recordName:@"b6050e4d-e7b7-4e4e-b318-825cacc34722" withAccount:@"ck-test-receive"]; - [self uploadRecords:@[record]]; - - [self.kcv notifyZoneChange:nil]; - [self.kcv waitForFetchAndIncomingQueueProcessing]; - - [self findGenericPassword:@"ck-test-receive" expecting:errSecSuccess]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testReceive: states match after receive"); -} - -- (void)testReceiveColliding { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - XCTAssert([self findGenericPassword:@"ck-test-receivecolliding" expecting:errSecItemNotFound], @"test item not yet in keychain"); - - // Conflicting items! This test does not care how conflict gets resolved, just that state is consistent after syncing - CKRecord *r1 = [self createFakeRecord:self.zoneID recordName:@"97576447-c6b8-47fe-8f00-64f5da49d538" withAccount:@"ck-test-receivecolliding"]; - CKRecord *r2 = [self createFakeRecord:self.zoneID recordName:@"c6b86447-9757-47fe-8f00-64f5da49d538" withAccount:@"ck-test-receivecolliding"]; - [self uploadRecords:@[r1,r2]]; - - // poke CKKS since we won't have a real CK notification - [self.kcv notifyZoneChange:nil]; - [self.kcv waitForFetchAndIncomingQueueProcessing]; - [self waitForEmptyOutgoingQueue:self.kcv]; - - XCTAssert([self findGenericPassword:@"ck-test-receivecolliding" expecting:errSecSuccess], @"Item present after download"); - // This will also flag an issue if the two conflicting items persist - XCTAssert([self compareLocalKeychainWithCloudKitState], @"Back in sync after processing incoming changes"); -} - -- (void)testAddMultipleDeleteAll { - [self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - XCTAssert([self addMultiplePasswords:@"data" account:@"ck-test-addmultipledeleteall" amount:5]); - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMultipleDeleteAll: states match after adds"); - - XCTAssert([self deleteMultiplePasswords:@"ck-test-addmultipledeleteall" amount:3]); - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMultipleDeleteAll: states match after deletes"); - - XCTAssert([self deleteGenericPassword:@"ck-test-addmultipledeleteall005"]); - XCTAssert([self deleteGenericPassword:@"ck-test-addmultipledeleteall004"]); - - [self waitForEmptyOutgoingQueue:self.kcv]; - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddMultipleDeleteAll: states match after deletes"); -} - -- (void)testAddLotsOfItems { - [ self startCKKSSubsystem]; - [self.kcv waitForKeyHierarchyReadiness]; - - XCTAssert([self addMultiplePasswords:@"data" account:@"ck-test-addlotsofitems" amount:250], @"Added a truckload of items"); - - XCTAssert([self waitForEmptyOutgoingQueue:self.kcv], @"Completed upload within %ld seconds", (long)self.queueTimeout); - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddLotsOfItems: states match after adding tons of items"); - - XCTAssert([self deleteMultiplePasswords:@"ck-test-addlotsofitems" amount:250], @"Got rid of a truckload of items"); - XCTAssert([self waitForEmptyOutgoingQueue:self.kcv], @"Completed deletions within %ld seconds",(long)self.queueTimeout); - - XCTAssert([self compareLocalKeychainWithCloudKitState], @"testAddLotsOfItems: states match after removing tons of items again"); -} - -#endif - -@end diff --git a/keychain/ckks/tests/CKKSConditionTests.m b/keychain/ckks/tests/CKKSConditionTests.m index 1c0c6bb2..df6bc28f 100644 --- a/keychain/ckks/tests/CKKSConditionTests.m +++ b/keychain/ckks/tests/CKKSConditionTests.m @@ -25,7 +25,6 @@ #import #import #import "keychain/ckks/CKKSCondition.h" -#import @interface CKKSConditionTests : XCTestCase @end diff --git a/keychain/ckks/tests/CKKSDeviceStateUploadTests.m b/keychain/ckks/tests/CKKSDeviceStateUploadTests.m index 8d0c019a..65f3d717 100644 --- a/keychain/ckks/tests/CKKSDeviceStateUploadTests.m +++ b/keychain/ckks/tests/CKKSDeviceStateUploadTests.m @@ -152,7 +152,7 @@ [op waitUntilFinished]; // And now, if the update is old enough, that'll work too - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry fromDatabase:self.accountStateTracker.ckdeviceID zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "No error fetching device state entry"); @@ -176,7 +176,7 @@ [cdse saveToDatabase:&error]; XCTAssertNil(error, "No error saving device state entry"); - return true; + return CKKSDatabaseTransactionCommit; }]; // And now the rate-limiting doesn't get in the way @@ -212,7 +212,7 @@ NSString* oldDeviceID = self.accountStateTracker.ckdeviceID; self.accountStateTracker.ckdeviceID = nil; - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry fromDatabase:oldDeviceID zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "No error fetching device state entry"); @@ -222,8 +222,6 @@ NSDate* m = record.modificationDate; XCTAssertNotNil(m, "Have modification date"); - - return true; }]; // It shouldn't try to upload a new CDSE; there's no device ID @@ -455,10 +453,10 @@ [self.keychainZone addToZone:[octagonOnly CKRecordWithZoneID:self.keychainZoneID]]; // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* cdses = [CKKSDeviceStateEntry allInZone:self.keychainZoneID error:&error]; XCTAssertNil(error, "No error fetching CDSEs"); @@ -519,8 +517,6 @@ XCTAssertEqualObjects(octagondevice.currentTLKUUID, zoneKeys.tlk.uuid, "correct tlk uuid"); XCTAssertEqualObjects(octagondevice.currentClassAUUID, zoneKeys.classA.uuid, "correct classA uuid"); XCTAssertEqualObjects(octagondevice.currentClassCUUID, zoneKeys.classC.uuid, "correct classC uuid"); - - return false; }]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -533,7 +529,6 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "CKKS entered waitfortlk"); - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateWaitForTLK, "CKKS entered waitfortlk"); __weak __typeof(self) weakSelf = self; [self expectCKModifyRecords: @{SecCKRecordDeviceStateType: [NSNumber numberWithInt:1]} @@ -629,13 +624,11 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "CKKS entered waitfortlk"); - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateWaitForTLK, "CKKS entered waitfortlk"); // And restart CKKS... self.keychainView = [[CKKSViewManager manager] restartZone: self.keychainZoneID.zoneName]; [self beginSOSTrustedViewOperation:self.keychainView]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "CKKS entered waitfortlk"); - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateWaitForTLK, "CKKS entered waitfortlk"); __weak __typeof(self) weakSelf = self; [self expectCKModifyRecords: @{SecCKRecordDeviceStateType: [NSNumber numberWithInt:1]} @@ -770,7 +763,8 @@ [self.keychainView updateDeviceState:false waitForKeyHierarchyInitialization:8*NSEC_PER_SEC ckoperationGroup:nil]; - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateFetch, "CKKS re-entered fetch"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateFetch] wait:20*NSEC_PER_SEC], "Key state should become fetch"); [self releaseCloudKitFetchHold]; OCMVerifyAllWithDelay(self.mockDatabase, 20); diff --git a/keychain/ckks/tests/CKKSFetchTests.m b/keychain/ckks/tests/CKKSFetchTests.m index 433a2b20..f1f97783 100644 --- a/keychain/ckks/tests/CKKSFetchTests.m +++ b/keychain/ckks/tests/CKKSFetchTests.m @@ -53,9 +53,7 @@ } } runBeforeFinished:^{}]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -122,9 +120,7 @@ } } runBeforeFinished:^{}]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -177,9 +173,7 @@ } } runBeforeFinished:^{}]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -225,7 +219,7 @@ }]; // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; // Wait for both fetches.... OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -277,7 +271,7 @@ [self expectCKFetch]; // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; @@ -287,7 +281,7 @@ // Now, edit the on-disk CKSE [self.keychainView halt]; - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; @@ -297,7 +291,7 @@ ckse.moreRecordsInCloudKit = YES; [ckse saveToDatabase: &error]; XCTAssertNil(error, "no error saving to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // CKKS should, upon restart, kick off a fetch starting from the previous checkpoint diff --git a/keychain/ckks/tests/CKKSLoggerTests.m b/keychain/ckks/tests/CKKSLoggerTests.m index 692f1a05..0c60d25e 100644 --- a/keychain/ckks/tests/CKKSLoggerTests.m +++ b/keychain/ckks/tests/CKKSLoggerTests.m @@ -179,7 +179,14 @@ static void _XCTAssertTimeDiffWithInterval(CKKSAnalyticsTests* self, const char* va_end(args); arg = [[NSString alloc] initWithFormat: format arguments: args]; } - [self recordFailureWithDescription: [comparison stringByAppendingString: arg] inFile: [NSString stringWithUTF8String: filename] atLine: line expected: YES]; + + XCTIssue* issue = [[XCTIssue alloc] initWithType:XCTIssueTypeAssertionFailure + compactDescription:[comparison stringByAppendingString: arg] + detailedDescription:nil + sourceCodeContext:[[XCTSourceCodeContext alloc] init] + associatedError:nil + attachments:@[]]; + [self recordIssue:issue]; } } @@ -190,24 +197,25 @@ static void _XCTAssertTimeDiffWithInterval(CKKSAnalyticsTests* self, const char* CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; [self.keychainZone addToZone: ckr]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - - [[[self.keychainView waitForFetchAndIncomingQueueProcessing] completionHandlerDidRunCondition] wait:4 * NSEC_PER_SEC]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + + [[self.injectedManager.zoneChangeFetcher inflightFetch] waitUntilFinished]; + CKKSResultOperation* op = [self.keychainView processIncomingQueue:false]; + [[op completionHandlerDidRunCondition] wait:4 * NSEC_PER_SEC]; NSDate* nowDate = [NSDate date]; /* * Check last sync date for class A */ - NSDate* syncADate = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassA inView:self.keychainView]; + NSDate* syncADate = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassA zoneName:self.keychainView.zoneName]; XCTAssertNotNil(syncADate, "Failed to get a last successful A sync date"); XCTAssertTimeDiffWithInterval(syncADate, nowDate, 15, "Last sync A date should be recent"); /* * Check last sync date for class C */ - NSDate *syncCDate = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassC inView:self.keychainView]; + NSDate *syncCDate = [[CKKSAnalytics logger] dateOfLastSuccessForEvent:CKKSEventProcessIncomingQueueClassC zoneName:self.keychainView.zoneName]; XCTAssertNotNil(syncCDate, "Failed to get a last successful C sync date"); XCTAssertTimeDiffWithInterval(syncCDate, nowDate, 15, "Last sync C date should be recent"); @@ -246,7 +254,7 @@ static void _XCTAssertTimeDiffWithInterval(CKKSAnalyticsTests* self, const char* for (NSInteger i = 0; i < 5; i++) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ CKKSAnalytics* logger = [CKKSAnalytics logger]; - [logger logSuccessForEvent:(CKKSAnalyticsFailableEvent*)@"test_event" inView:self.keychainView]; + [logger logSuccessForEvent:(CKKSAnalyticsFailableEvent*)@"test_event" zoneName:self.keychainView.zoneName]; dispatch_semaphore_signal(semaphore); }); } diff --git a/keychain/ckks/tests/CKKSManifestTests.m b/keychain/ckks/tests/CKKSManifestTests.m index fbd7f991..064e99cc 100644 --- a/keychain/ckks/tests/CKKSManifestTests.m +++ b/keychain/ckks/tests/CKKSManifestTests.m @@ -53,7 +53,7 @@ NSMutableArray* items = [[NSMutableArray alloc] init]; __weak __typeof(self) weakSelf = self; __block NSError* error = nil; - [self.keychainView dispatchSync:^bool(void) { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for (CKRecord* record in records) { CKKSMirrorEntry* mirrorEntry = [CKKSMirrorEntry tryFromDatabase:record.recordID.recordName zoneID:weakSelf.keychainZoneID error:&error]; XCTAssertNil(error, @"error encountered trying to generate CKKSMirrorEntry: %@", error); @@ -63,7 +63,7 @@ } } - return YES; + return CKKSDatabaseTransactionCommit; }]; return items; @@ -82,11 +82,11 @@ SFECKeyPair* keyPair = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]]; [CKKSManifestInjectionPointHelper registerEgoPeerID:@"MeMyselfAndI" keyPair:keyPair]; - // Always sync manifests, and never enforce them - SecCKKSSetSyncManifests(true); + // We've now disabled manifests. + SecCKKSSetSyncManifests(false); SecCKKSSetEnforceManifests(false); - XCTAssertTrue([CKKSManifest shouldSyncManifests], "Manifests syncing is enabled"); + XCTAssertFalse([CKKSManifest shouldSyncManifests], "Manifests syncing is disabled"); XCTAssertFalse([CKKSManifest shouldEnforceManifests], "Manifests enforcement is disabled"); NSError* error = nil; @@ -280,9 +280,7 @@ [self.keychainZone addToZone:record]; } - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; return query; @@ -329,12 +327,15 @@ - (void)testSaveManifestWithNilValues { - SFECKeyPair* keyPair = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]]; - CKKSManifest* manifest = [CKKSEgoManifest newFakeManifestForZone:@"SomeZone" withItemRecords:@[] currentItems:@{} signerID:@"BadBoy" keyPair:keyPair error:nil]; - [manifest nilAllIvars]; - XCTAssertNil(manifest.zoneID); - XCTAssertNil(manifest.signerID); - XCTAssertNoThrow([manifest saveToDatabase:nil]); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + SFECKeyPair* keyPair = [[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]]; + CKKSManifest* manifest = [CKKSEgoManifest newFakeManifestForZone:@"SomeZone" withItemRecords:@[] currentItems:@{} signerID:@"BadBoy" keyPair:keyPair error:nil]; + [manifest nilAllIvars]; + XCTAssertNil(manifest.zoneID); + XCTAssertNil(manifest.signerID); + XCTAssertNoThrow([manifest saveToDatabase:nil]); + return CKKSDatabaseTransactionRollback; + }]; } @end diff --git a/keychain/ckks/tests/CKKSMockSOSPresentAdapter.h b/keychain/ckks/tests/CKKSMockSOSPresentAdapter.h index 4eb48520..66d11d89 100644 --- a/keychain/ckks/tests/CKKSMockSOSPresentAdapter.h +++ b/keychain/ckks/tests/CKKSMockSOSPresentAdapter.h @@ -13,6 +13,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable) NSError* selfPeerError; @property (nullable) NSError* trustedPeersError; +@property BOOL aksLocked; + @property bool excludeSelfPeerFromTrustSet; @property SOSCCStatus circleStatus; @@ -21,6 +23,11 @@ NS_ASSUME_NONNULL_BEGIN @property CKKSSOSSelfPeer* selfPeer; @property NSMutableSet>* trustedPeers; +@property BOOL safariViewEnabled; + +@property BOOL ckks4AllStatus; +@property BOOL ckks4AllStatusIsSet; + @property (nullable) void (^updateOctagonKeySetListener)(id); - (instancetype)initWithSelfPeer:(CKKSSOSSelfPeer*)selfPeer diff --git a/keychain/ckks/tests/CKKSMockSOSPresentAdapter.m b/keychain/ckks/tests/CKKSMockSOSPresentAdapter.m index 7f8077ec..d1696e64 100644 --- a/keychain/ckks/tests/CKKSMockSOSPresentAdapter.m +++ b/keychain/ckks/tests/CKKSMockSOSPresentAdapter.m @@ -18,11 +18,15 @@ _essential = essential; _circleStatus = kSOSCCInCircle; + _safariViewEnabled = YES; _excludeSelfPeerFromTrustSet = false; _peerChangeListeners = [[CKKSListenerCollection alloc] initWithName:@"ckks-mock-sos"]; + _ckks4AllStatus = NO; + _ckks4AllStatusIsSet = NO; + _selfPeer = selfPeer; _trustedPeers = [trustedPeers mutableCopy]; } @@ -58,6 +62,13 @@ return nil; } + if(self.aksLocked) { + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecInteractionNotAllowed userInfo:nil]; + } + return nil; + } + if(self.sosEnabled && self.circleStatus == kSOSCCInCircle) { return self.selfPeer; } else { @@ -81,7 +92,7 @@ - (NSSet> * _Nullable)fetchTrustedPeers:(NSError * _Nullable __autoreleasing * _Nullable)error { if(self.trustedPeersError) { - if(*error) { + if(error) { *error = self.trustedPeersError; } return nil; @@ -102,11 +113,18 @@ } } -- (void)updateOctagonKeySetWithAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { +- (BOOL)updateOctagonKeySetWithAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { if(self.updateOctagonKeySetListener) { self.updateOctagonKeySetListener(currentSelfPeer); } - return; + return YES; +} + +- (BOOL)updateCKKS4AllStatus:(BOOL)status error:(NSError**)error +{ + self.ckks4AllStatus = status; + self.ckks4AllStatusIsSet = YES; + return YES; } - (void)registerForPeerChangeUpdates:(nonnull id)listener { @@ -140,4 +158,15 @@ return [self.trustedPeers setByAddingObject: s]; } +- (BOOL)safariViewSyncingEnabled:(NSError**)error +{ + // TODO: what happens if you call this when not in circle? + return self.safariViewEnabled; +} + +- (BOOL)preloadOctagonKeySetOnAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { + // No-op + return YES; +} + @end diff --git a/keychain/ckks/tests/CKKSOperationTests.m b/keychain/ckks/tests/CKKSOperationTests.m index 913a7901..b3c6e30d 100644 --- a/keychain/ckks/tests/CKKSOperationTests.m +++ b/keychain/ckks/tests/CKKSOperationTests.m @@ -616,6 +616,38 @@ XCTAssertFalse([group isPending], "group operation isn't pending, as it's cancelled"); } +- (void)testResultOperationDeepDependencyChain { + NSMutableArray* ops = [NSMutableArray array]; + + CKKSResultOperation* op = nil; + + for(int i = 0; i < 100; i++) { + op = [CKKSResultOperation named:[NSString stringWithFormat:@"operation-%d", i] withBlock:^{}]; + [op addNullableDependency:[ops lastObject]]; + + [ops addObject:op]; + } + + NSString* description = [op description]; + XCTAssertNotNil(description, "Should have received some description for the operation"); +} + +- (void)testGroupOperationDeepDependencyChain { + NSMutableArray* ops = [NSMutableArray array]; + + CKKSGroupOperation* op = nil; + + for(int i = 0; i < 100; i++) { + op = [CKKSGroupOperation named:[NSString stringWithFormat:@"operation-%d", i] withBlock:^{}]; + [op addNullableDependency:[ops lastObject]]; + + [ops addObject:op]; + } + + NSString* description = [op description]; + XCTAssertNotNil(description, "Should have received some description for the operation"); +} + @end diff --git a/keychain/ckks/tests/CKKSSOSTests.m b/keychain/ckks/tests/CKKSSOSTests.m index 7ac4dbac..c773c09f 100644 --- a/keychain/ckks/tests/CKKSSOSTests.m +++ b/keychain/ckks/tests/CKKSSOSTests.m @@ -70,6 +70,8 @@ [self saveFakeKeyHierarchyToLocalDatabase:self.manateeZoneID]; [self saveTLKMaterialToKeychain:self.manateeZoneID]; + [self startCKKSSubsystem]; + NSDictionary* piggyTLKs = [self SOSPiggyBackCopyFromKeychain]; [self deleteTLKMaterialFromKeychain:self.manateeZoneID]; @@ -86,6 +88,8 @@ [self putFakeDeviceStatusesInCloudKit]; [self saveTLKsToKeychain]; + [self startCKKSSubsystem]; + NSDictionary* piggyTLKs = [self SOSPiggyBackCopyFromKeychain]; [self deleteTLKMaterialsFromKeychain]; @@ -112,17 +116,6 @@ XCTAssertNil(error, "No error loading Home tlk from piggy contents"); } --(NSString*)fileForStorage -{ - static dispatch_once_t onceToken; - static NSString *tempPath = NULL; - dispatch_once(&onceToken, ^{ - tempPath = [[[[NSFileManager defaultManager] temporaryDirectory] URLByAppendingPathComponent:@"PiggyPacket"] path]; - - }); - return tempPath; -} - -(void)testPiggybackingData{ [self putFakeKeyHierachiesInCloudKit]; [self saveTLKsToKeychain]; @@ -154,8 +147,6 @@ NSData *initial = SOSPiggyCreateInitialSyncData(icloudidentities, tlks); XCTAssertNotNil(initial, "Initial not set"); - BOOL writeStatus = [initial writeToFile:[self fileForStorage] options:NSDataWritingAtomic error: nil]; - XCTAssertTrue(writeStatus, "had trouble writing to disk"); XCTAssertNotEqual((int)[initial length], 0, "initial sync data is greater than 0"); /* @@ -176,6 +167,44 @@ XCTAssertEqual([copiediCloudidentities count], [icloudidentities count], "ident count not same"); } + +- (void)testPiggybackingTLKRequest { + [self putFakeKeyHierachiesInCloudKit]; + [self saveTLKsToKeychain]; + + for(CKRecordZoneID* zoneID in self.ckksZones) { + [self expectCKKSTLKSelfShareUpload:zoneID]; + } + [self startCKKSSubsystem]; + [self waitForKeyHierarchyReadinesses]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // The "tlk request" piggybacking session calls SOSAccountCopyInitialSyncData + __block CFErrorRef cferror = NULL; + NSData* piggybackingData = (NSData*) CFBridgingRelease(SOSAccountCopyInitialSyncData(nil, kSOSInitialSyncFlagTLKsRequestOnly, &cferror)); + + XCTAssertEqual(cferror, NULL, "Should have no error fetching only the TLKs"); + XCTAssertNotNil(piggybackingData, "Should have received some sync data"); + + const uint8_t* der = [piggybackingData bytes]; + const uint8_t *der_end = der + [piggybackingData length]; + + NSDictionary *result = SOSPiggyCopyInitialSyncData(&der, der_end); + XCTAssertNotNil(result, "Should be able to parse the piggybacking data"); + + NSArray *copiedTLKs = result[@"tlks"]; + XCTAssertNotNil(copiedTLKs, "should have some tlks"); + XCTAssertEqual([copiedTLKs count], 1u, "piggybacking should have gotten 1 TLK"); + XCTAssertEqualObjects(copiedTLKs[0][@"srvr"], @"Passwords", "should have the passwords TLK only"); + NSData* keyData = copiedTLKs[0][@"v_Data"]; + XCTAssertNotNil(keyData, "Should have some key material"); + XCTAssertEqual([keyData length], 64, "Key material should be 64 bytes"); + + NSArray *copiediCloudidentities = result[@"idents"]; + XCTAssertNotNil(copiediCloudidentities, "idents not set"); + XCTAssertEqual([copiediCloudidentities count], 0, "Should have no icloud identities"); +} + -(void)testVerifyTLKSorting { char key[32*2] = {0}; NSArray *tlks = @[ @@ -250,7 +279,7 @@ // Verify that there are three local keys, and three local current key records __weak __typeof(self) weakSelf = self; - [self.manateeView dispatchSync: ^bool{ + [self.manateeView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -280,8 +309,6 @@ XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef)query, &result), "Found a syncable TLK"); XCTAssertNotNil((__bridge id) result, "Received a result from SecItemCopyMatching"); CFReleaseNull(result); - - return false; }]; } diff --git a/keychain/ckks/tests/CKKSSQLTests.m b/keychain/ckks/tests/CKKSSQLTests.m index 827a5c83..4361b474 100644 --- a/keychain/ckks/tests/CKKSSQLTests.m +++ b/keychain/ckks/tests/CKKSSQLTests.m @@ -30,7 +30,9 @@ #import "keychain/ckks/CKKS.h" #import "keychain/ckks/CKKSKey.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" #import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" #import "keychain/ckks/CKKSZoneStateEntry.h" #import "keychain/ckks/CKKSDeviceStateEntry.h" #import "keychain/ckks/CKKSRateLimiter.h" @@ -97,11 +99,14 @@ waitUntil:nil accessGroup:@"nope"]; - NSError* error = nil; - [one saveToDatabase:&error]; - [two saveToDatabase: &error]; - [three saveToDatabase: &error]; - XCTAssertNil(error, "no error saving ZoneStateEntries to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* error = nil; + [one saveToDatabase:&error]; + [two saveToDatabase: &error]; + [three saveToDatabase: &error]; + XCTAssertNil(error, "no error saving ZoneStateEntries to database"); + return CKKSDatabaseTransactionCommit; + }]; } - (void)testCKKSOutgoingQueueEntry { @@ -160,8 +165,12 @@ state:SecCKKSStateError waitUntil:[NSDate date] accessGroup:@"nope"]; - [other saveToDatabase:&nserror]; - XCTAssertNil(nserror, "no error occurred saving to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [other saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving to database"); + return CKKSDatabaseTransactionCommit; + }]; CKKSOutgoingQueueEntry * oqe = [CKKSOutgoingQueueEntry fromDatabase:testUUID state:@"unprocessed" zoneID:self.testZoneID error: &nserror]; XCTAssertNil(nserror, "no error occurred creating from database"); @@ -177,7 +186,12 @@ oqe.item.base64encitem = @"bW9yZW5vbnNlbnNlCg=="; oqe.item.encver = 1; - XCTAssertTrue([oqe saveToDatabase: &nserror], "saving to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [oqe saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving to database"); + return CKKSDatabaseTransactionCommit; + }]; CKKSOutgoingQueueEntry * oqe2 = [CKKSOutgoingQueueEntry fromDatabase:testUUID state:@"savedtocloud" zoneID:self.testZoneID error: &nserror]; XCTAssertNil(nserror, "no error occurred"); @@ -207,8 +221,15 @@ // Test row deletion nserror = nil; - [oqe2 deleteFromDatabase:&nserror]; - XCTAssertNil(nserror, "No NSError exists when deleting existing item"); + + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* deleteError = nil; + [oqe2 deleteFromDatabase:&deleteError]; + XCTAssertNil(deleteError, "no error occurred deleting existing item"); + return CKKSDatabaseTransactionCommit; + }]; + oqe2 = [CKKSOutgoingQueueEntry fromDatabase:testUUID state:@"savedtocloud" zoneID:self.testZoneID error: &nserror]; XCTAssertNil(oqe2, "Can't find a nonexisting object"); XCTAssertNotNil(nserror, "NSError exists when things break"); @@ -221,6 +242,47 @@ XCTAssertEqualObjects(other, other2, "loaded object is equal to object"); } +- (void)testOverwriteCKKSIncomingQueueEntry { + NSError* error = nil; + + CKKSItem* baseitem = [[CKKSItem alloc] initWithUUID: [[NSUUID UUID] UUIDString] + parentKeyUUID:[[NSUUID UUID] UUIDString] + zoneID:self.testZoneID + encItem:[@"nonsense" dataUsingEncoding:NSUTF8StringEncoding] + wrappedkey:[[CKKSWrappedAESSIVKey alloc]initWithBase64: @"KFfL58XtugiYNoD859EjG0StfrYd6eakm0CQrgX7iO+DEo4kio3WbEeA1kctCU0GaeTGsRFpbdy4oo6jXhVu7cZqB0svhUPGq55aGnszUjI="] + generationCount:0 + encver:0]; + CKKSIncomingQueueEntry* delete = [[CKKSIncomingQueueEntry alloc] initWithCKKSItem:baseitem + action:SecCKKSActionDelete + state:SecCKKSStateNew]; + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [delete saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving delete IQE to database"); + return CKKSDatabaseTransactionCommit; + }]; + + NSArray* entries = [CKKSIncomingQueueEntry all:&error]; + XCTAssertNil(error, "Should be no error fetching alll IQEs"); + XCTAssertEqual(entries.count, 1u, "Should be one entry"); + XCTAssertEqualObjects(entries[0].action, SecCKKSActionDelete, "Should have delete as an action"); + + CKKSIncomingQueueEntry* add = [[CKKSIncomingQueueEntry alloc] initWithCKKSItem:baseitem + action:SecCKKSActionAdd + state:SecCKKSStateNew]; + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [add saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving add IQE to database"); + return CKKSDatabaseTransactionCommit; + }]; + + entries = [CKKSIncomingQueueEntry all:&error]; + XCTAssertNil(error, "Should be no error fetching alll IQEs"); + XCTAssertEqual(entries.count, 1u, "Should be one entry"); + XCTAssertEqualObjects(entries[0].action, SecCKKSActionAdd, "Should have add as an action"); +} + -(void)testCKKSZoneStateEntrySQL { CKKSZoneStateEntry* zse = [[CKKSZoneStateEntry alloc] initWithCKZone:@"sqltest" zoneCreated:true @@ -228,6 +290,7 @@ changeToken:[@"nonsense" dataUsingEncoding:NSUTF8StringEncoding] moreRecordsInCloudKit:YES lastFetch:[NSDate date] + lastScan:[NSDate date] lastFixup:CKKSCurrentFixupNumber encodedRateLimiter:nil]; zse.rateLimiter = [[CKKSRateLimiter alloc] init]; @@ -238,6 +301,7 @@ changeToken:[@"nonsense" dataUsingEncoding:NSUTF8StringEncoding] moreRecordsInCloudKit:YES lastFetch:zse.lastFetchTime + lastScan:zse.lastLocalKeychainScanTime lastFixup:CKKSCurrentFixupNumber encodedRateLimiter:zse.encodedRateLimiter]; @@ -247,6 +311,7 @@ changeToken:[@"allnonsense" dataUsingEncoding:NSUTF8StringEncoding] moreRecordsInCloudKit:NO lastFetch:zse.lastFetchTime + lastScan:zse.lastLocalKeychainScanTime lastFixup:CKKSCurrentFixupNumber encodedRateLimiter:zse.encodedRateLimiter]; XCTAssertEqualObjects(zse, zseClone, "CKKSZoneStateEntry isEqual of equal objects seems sane"); @@ -257,8 +322,12 @@ XCTAssertNil(error, "No error trying to load nonexistent record"); XCTAssertNil(loaded, "No record saved in database"); - [zse saveToDatabase: &error]; - XCTAssertNil(error, "no error saving CKKSZoneStateEntry to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [zse saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving CKKSZoneStateEntry to database"); + return CKKSDatabaseTransactionCommit; + }]; loaded = [CKKSZoneStateEntry tryFromDatabase: @"sqltest" error:&error]; XCTAssertNil(error, "No error trying to load saved record"); @@ -278,6 +347,8 @@ // We only compare to the minute level, as that's enough to test the save+load. XCTAssert([[NSCalendar currentCalendar] isDate:zse.lastFetchTime equalToDate: loaded.lastFetchTime toUnitGranularity:NSCalendarUnitMinute], "lastFetchTime persisted through db save and load"); + XCTAssert([[NSCalendar currentCalendar] isDate:zse.lastLocalKeychainScanTime equalToDate:loaded.lastLocalKeychainScanTime toUnitGranularity:NSCalendarUnitMinute], + "lastLocalKeychainScanTime persisted through db save and load"); } -(void)testRoundtripCKKSDeviceStateEntry { @@ -297,9 +368,12 @@ zoneID:self.testZoneID encodedCKRecord:nil]; XCTAssertNotNil(cdse, "Constructor works"); - NSError* saveError = nil; - [cdse saveToDatabase:&saveError]; - XCTAssertNil(saveError, "No error saving cdse to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [cdse saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving cdse to database"); + return CKKSDatabaseTransactionCommit; + }]; NSError* loadError = nil; CKKSDeviceStateEntry* loadedCDSE = [CKKSDeviceStateEntry fromDatabase:testUUID zoneID:self.testZoneID error:&loadError]; @@ -376,8 +450,12 @@ currentkey:true]; XCTAssertNotNil(key, "could create key"); - [key saveToDatabase: &error]; - XCTAssertNil(error, "could save key to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [key saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving key to database"); + return CKKSDatabaseTransactionCommit; + }]; error = nil; CKKSKey* key2 = [CKKSKey fromDatabase:testUUID zoneID:self.testZoneID error:&error]; @@ -404,8 +482,13 @@ zoneID:self.testZoneID encodedCKRecord: testCKRecord currentkey: true]; - XCTAssertTrue([tlk saveToDatabase: &error], "TLK saved to database"); - XCTAssertNil(error, "no error saving TLK to database"); + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [tlk saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving TLK to database"); + return CKKSDatabaseTransactionCommit; + }]; CKKSKey* wrappedKey = [[CKKSKey alloc] initWrappedBy: tlk AESKey:[CKKSAESSIVKey randomKey:&error] @@ -415,8 +498,12 @@ zoneID:self.testZoneID encodedCKRecord:testCKRecord currentkey:true]; - XCTAssertTrue([wrappedKey saveToDatabase: &error], "key saved to database"); - XCTAssertNil(error, "no error saving key to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [wrappedKey saveToDatabase:&saveError]; + XCTAssertNil(saveError, "no error occurred saving key to database"); + return CKKSDatabaseTransactionCommit; + }]; NSString* secondUUID = @"8b2aeb7f-0000-0000-0000-70d5c728ebf7"; CKKSKey* secondtlk = [[CKKSKey alloc] initSelfWrappedWithAESKey:[[CKKSAESSIVKey alloc] initWithBase64: @"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="] @@ -426,8 +513,12 @@ zoneID:self.testZoneID encodedCKRecord:testCKRecord currentkey:true]; - XCTAssertTrue([secondtlk saveToDatabase: &error], "Second TLK saved to database"); - XCTAssertNil(error, "no error saving TLK to database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + XCTAssertTrue([secondtlk saveToDatabase:&saveError], "Second TLK saved to database"); + XCTAssertNil(saveError, "no error occurred saving second TLK to database"); + return CKKSDatabaseTransactionCommit; + }]; NSArray* tlks = [CKKSKey allWhere: @{@"UUID": @"8b2aeb7f-4af3-43e9-b6e6-70d5c728ebf7"} error: &error]; XCTAssertNotNil(tlks, "Returned some array from allWhere"); @@ -455,6 +546,12 @@ XCTAssertNil(error, "no error back from allWhere"); XCTAssertEqual([selfWrapped3 count], 1ul, "Should have received one rows"); XCTAssertEqualObjects([selfWrapped3[0] uuid], secondUUID, "Should received second TLK UUID"); + + NSArray* whereFound = [CKKSKey allWhere: @{@"uuid": [[CKKSSQLWhereIn alloc] initWithValues:@[tlk.uuid, wrappedKey.uuid, @"not-found"]]} error:&error]; + XCTAssertNil(error, "no error back from search"); + XCTAssertEqual([whereFound count], 2ul, "Should have received two rows"); + XCTAssertEqualObjects([whereFound[1] uuid], tlk.uuid, "Should received TLK UUID"); + XCTAssertEqualObjects([whereFound[0] uuid], wrappedKey.uuid, "Should received wrapped key UUID"); } - (void)testGroupBy { diff --git a/keychain/ckks/tests/CKKSServerValidationRecoveryTests.m b/keychain/ckks/tests/CKKSServerValidationRecoveryTests.m index acc1818d..2e800d88 100644 --- a/keychain/ckks/tests/CKKSServerValidationRecoveryTests.m +++ b/keychain/ckks/tests/CKKSServerValidationRecoveryTests.m @@ -143,11 +143,11 @@ self.keychainZone.currentDatabase[self.keychainZoneKeys.currentClassCPointer.storedCKRecord.recordID][SecCKRecordParentKeyRefKey] = oldClassCKey; self.keychainZoneKeys.currentClassCPointer.currentKeyUUID = oldClassCKey.recordID.recordName; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; // CKKS should then fix the pointers and give itself a new TLK share record, but not update any keys [self expectCKModifyKeyRecords:0 currentKeyPointerRecords:1 tlkShareRecords:1 zoneID:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // And then upload the item as usual @@ -210,7 +210,7 @@ [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; [self saveTLKMaterialToKeychain:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // And then use the 'new' key as it should diff --git a/keychain/ckks/tests/CKKSTLKSharingEncryptionTests.m b/keychain/ckks/tests/CKKSTLKSharingEncryptionTests.m index 67b08ac5..d22c68ae 100644 --- a/keychain/ckks/tests/CKKSTLKSharingEncryptionTests.m +++ b/keychain/ckks/tests/CKKSTLKSharingEncryptionTests.m @@ -27,6 +27,7 @@ #import "keychain/ckks/CKKS.h" #import "keychain/ckks/CKKSKey.h" #import "keychain/ckks/CKKSTLKShareRecord.h" +#import "keychain/ckks/CKKSSQLDatabaseObject.h" #import "keychain/ckks/CKKSPeer.h" #import "keychain/ckks/tests/CloudKitMockXCTest.h" @@ -58,13 +59,13 @@ viewList:self.managedViewList]; XCTAssertNotNil(self.localPeer, "Should be able to make a new local peer"); - self.remotePeer = [[CKKSSOSSelfPeer alloc] initWithSOSPeerID:@"remote" + self.remotePeer = [[CKKSSOSSelfPeer alloc] initWithSOSPeerID:@"remote1" encryptionKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] signingKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] viewList:self.managedViewList]; XCTAssertNotNil(self.remotePeer, "Should be able to make a new remote peer"); - self.remotePeer2 = [[CKKSSOSSelfPeer alloc] initWithSOSPeerID:@"remote" + self.remotePeer2 = [[CKKSSOSSelfPeer alloc] initWithSOSPeerID:@"remote2" encryptionKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] signingKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] viewList:self.managedViewList]; @@ -214,8 +215,12 @@ error:&error]; XCTAssertNil(error, "Should have been no error sharing a CKKSKey"); - [share saveToDatabase:&error]; - XCTAssertNil(error, "Shouldn't be an error saving a TLKShare record to the database"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [share saveToDatabase:&saveError]; + XCTAssertNil(saveError, "Shouldn't be an error saving a TLKShare record to the database"); + return CKKSDatabaseTransactionCommit; + }]; CKKSTLKShareRecord* loadedShare = [CKKSTLKShareRecord fromDatabase:self.tlk.uuid receiverPeerID:self.remotePeer.peerID @@ -237,6 +242,58 @@ XCTAssertEqualObjects(share, fromCKRecord, "TLK shares sent through CloudKit should be identical"); } +- (void)testKeyExtractFromTrustState { + NSError* error = nil; + CKKSTLKShareRecord* share = [CKKSTLKShareRecord share:self.tlk + as:self.remotePeer + to:self.localPeer + epoch:-1 + poisoned:0 + error:&error]; + XCTAssertNotNil(share, "Should have a TLKShare"); + XCTAssertNil(error, "Should have been no error sharing a CKKSKey from a remote peer to a local peer"); + + CKKSPeerProviderState* trustState = [[CKKSPeerProviderState alloc] initWithPeerProviderID:@"test-provider" + essential:YES + selfPeers:[[CKKSSelves alloc] initWithCurrent:self.localPeer allSelves:nil] + selfPeersError:nil + trustedPeers:[NSSet setWithArray:@[ + self.localPeer, + self.remotePeer, + self.remotePeer2, + ]] + trustedPeersError:nil]; + CKKSKey* shareExtraction = [share recoverTLK:self.localPeer + trustedPeers:trustState.currentTrustedPeers + error:&error]; + XCTAssertNotNil(shareExtraction, "Should be able to recover the share from the currently trusted peers"); + XCTAssertNil(error, "Should be no error extracting TLK"); + + BOOL extracted = [trustState unwrapKey:self.tlk + fromShares:@[share] + error:&error]; + + XCTAssertTrue(extracted, "Should be able to extract the TLK via a share"); + XCTAssertNil(error, "Should be no error extracting TLK"); + + CKKSPeerProviderState* remotePeer2TrustState = [[CKKSPeerProviderState alloc] initWithPeerProviderID:@"test-provider" + essential:YES + selfPeers:[[CKKSSelves alloc] initWithCurrent:self.remotePeer2 allSelves:nil] + selfPeersError:nil + trustedPeers:[NSSet setWithArray:@[ + self.localPeer, + self.remotePeer, + self.remotePeer2, + ]] + trustedPeersError:nil]; + + BOOL remotePeerExtracted = [remotePeer2TrustState unwrapKey:self.tlk + fromShares:@[share] + error:&error]; + XCTAssertFalse(remotePeerExtracted, "Should not be able to extract the TLK if there's no share to the self peer"); + XCTAssertNotNil(error, "Should be an error when failing to extract TLK"); +} + - (void)testKeyShareSignExtraFieldsInCKRecord { NSError* error = nil; CKKSTLKShareRecord* share = [CKKSTLKShareRecord share:self.tlk @@ -282,8 +339,13 @@ // And verify that saving to disk and reloading is successful share2.storedCKRecord = record; XCTAssert([share2 verifySignature:share2.signature verifyingPeer:self.localPeer error:&error], "Signature with extra data should verify"); - [share2 saveToDatabase:&error]; - XCTAssertNil(error, "No error saving share2 to database"); + + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* saveError = nil; + [share2 saveToDatabase:&saveError]; + XCTAssertNil(saveError, "No error saving share2 to database"); + return CKKSDatabaseTransactionCommit; + }]; CKKSTLKShareRecord* loadedShare2 = [CKKSTLKShareRecord tryFromDatabaseFromCKRecordID:record.recordID error:&error]; XCTAssertNil(error, "No error loading loadedShare2 from database"); diff --git a/keychain/ckks/tests/CKKSTLKSharingTests.m b/keychain/ckks/tests/CKKSTLKSharingTests.m index ece1aebd..1c2cb802 100644 --- a/keychain/ckks/tests/CKKSTLKSharingTests.m +++ b/keychain/ckks/tests/CKKSTLKSharingTests.m @@ -134,7 +134,7 @@ // Verify that there are three local keys, and three local current key records __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -147,8 +147,6 @@ NSArray* currentkeys = [CKKSCurrentKeyPointer all:&error]; XCTAssertNil(error, "no error fetching current keys"); XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database"); - - return false; }]; } @@ -183,7 +181,7 @@ // Verify that there are three local keys, and three local current key records __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -196,8 +194,6 @@ NSArray* currentkeys = [CKKSCurrentKeyPointer all:&error]; XCTAssertNil(error, "no error fetching current keys"); XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database"); - - return false; }]; } @@ -250,7 +246,7 @@ // Verify that making a new share will have the old share's change tag __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSyncWithAccountKeys: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -272,8 +268,6 @@ XCTAssertNotNil(cloudKitRecord.recordChangeTag, "Existing record should have a change tag"); XCTAssertEqualObjects(cloudKitRecord.recordChangeTag, newRecord.recordChangeTag, "Change tags on existing and new records should match"); - - return false; }]; } @@ -308,31 +302,28 @@ CKRecord* shareCKRecord = [share CKRecordWithZoneID: self.keychainZoneID]; XCTAssertNotNil(shareCKRecord, "Should have been able to create a CKRecord"); [self.keychainZone addToZone:shareCKRecord]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* blockerror = nil; CKKSTLKShareRecord* localshare = [CKKSTLKShareRecord tryFromDatabaseFromCKRecordID:shareCKRecord.recordID error:&blockerror]; XCTAssertNil(blockerror, "Shouldn't error finding TLKShare record in database"); XCTAssertNotNil(localshare, "Should be able to find a TLKShare record in database"); - return true; }]; // Delete the record in CloudKit... [self.keychainZone deleteCKRecordIDFromZone:shareCKRecord.recordID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Should be gone now. - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* blockerror = nil; CKKSTLKShareRecord* localshare = [CKKSTLKShareRecord tryFromDatabaseFromCKRecordID:shareCKRecord.recordID error:&blockerror]; XCTAssertNil(blockerror, "Shouldn't error trying to find non-existent TLKShare record in database"); XCTAssertNil(localshare, "Shouldn't be able to find a TLKShare record in database"); - - return true; }]; } @@ -352,7 +343,7 @@ [self expectCKModifyKeyRecords:0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; [self putTLKSharesInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 zoneID:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); @@ -424,7 +415,7 @@ [self waitForCKModifications]; // Now, delete all the TLK Shares, so CKKS will upload them again - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; [CKKSTLKShareRecord deleteAll:self.keychainZoneID error:&error]; XCTAssertNil(error, "Shouldn't be an error deleting all TLKShares"); @@ -436,7 +427,7 @@ } } - return true; + return CKKSDatabaseTransactionCommit; }]; // Restart. We expect an upload of 3 TLK shares. @@ -467,7 +458,7 @@ [self expectCKModifyKeyRecords: 0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; // Trigger a notification - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -502,7 +493,7 @@ [self saveTLKMaterialToKeychain:self.keychainZoneID]; // Trigger a notification - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); @@ -572,7 +563,7 @@ // The CKKS subsystem should go into waitfortlk, since it doesn't trust this peer, but the peer is active [self startCKKSSubsystem]; - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "Key state should become ready"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], "Key state should become waitfortlk"); } - (void)testAcceptSharedTLKOnTrustSetAdditionOfSharer { @@ -631,7 +622,7 @@ // step 2: add a new peer who already has a share; no share should be created [self putTLKShareInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 to:self.remotePeer2 zoneID:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // CKKS should not upload a tlk share for this peer @@ -796,7 +787,7 @@ }]; [self putTLKSharesInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 zoneID:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); @@ -1123,7 +1114,7 @@ NSMutableArray*>* keysetOps = [NSMutableArray array]; for(CKKSKeychainView* view in self.ckksViews) { XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:40*NSEC_PER_SEC], @"key state should enter 'waitfortlkcreation' (view %@)", view); - [keysetOps addObject: [view findKeySet]]; + [keysetOps addObject: [view findKeySet:NO]]; } // Now that we've kicked them all off, wait for them to not crash @@ -1246,7 +1237,9 @@ [self.keychainView endTrustedOperation]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], "Key state should become 'waitfortrust'"); - [self.keychainView beginTrustedOperation:@[self.mockSOSAdapter, brokenAdapter] suggestTLKUpload:self.suggestTLKUpload]; + [self.keychainView beginTrustedOperation:@[self.mockSOSAdapter, brokenAdapter] + suggestTLKUpload:self.suggestTLKUpload + requestPolicyCheck:self.requestPolicyCheck]; // CKKS should ignore the non-essential and broken peer adapter XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become 'ready'"); @@ -1269,13 +1262,31 @@ // Spin up Octagon. We expect an upload of 3 TLK shares, this time for the octagon peer [self expectCKModifyKeyRecords: 0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; - [self.keychainView beginTrustedOperation:@[self.mockSOSAdapter, self.mockOctagonAdapter] suggestTLKUpload:self.suggestTLKUpload]; + [self.keychainView beginTrustedOperation:@[self.mockSOSAdapter, self.mockOctagonAdapter] + suggestTLKUpload:self.suggestTLKUpload + requestPolicyCheck:self.requestPolicyCheck]; [self.mockOctagonAdapter sendTrustedPeerSetChangedUpdate]; OCMVerifyAllWithDelay(self.mockDatabase, 20); XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); } +- (void)testQuiesceOnTrustLossDuringInitialFetch { + // Test starts with no keys in CKKS database, but one in our fake CloudKit. + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putTLKSharesInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 zoneID:self.keychainZoneID]; + + [self holdCloudKitFetches]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateFetch] wait:20*NSEC_PER_SEC], "Key state should become 'fetch'"); + + [self endSOSTrustedOperationForAllViews]; + + [self releaseCloudKitFetchHold]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], "Key state should become 'waitfortrust'"); +} + @end #endif // OCTAGON diff --git a/keychain/ckks/tests/CKKSTests+API.m b/keychain/ckks/tests/CKKSTests+API.m index 10235c42..18e3f588 100644 --- a/keychain/ckks/tests/CKKSTests+API.m +++ b/keychain/ckks/tests/CKKSTests+API.m @@ -213,8 +213,9 @@ [self waitForCKModifications]; OCMVerifyAllWithDelay(self.mockDatabase, 40); + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; self.keychainView.holdOutgoingQueueOperation = [CKKSGroupOperation named:@"outgoing-hold" withBlock: ^{ - secnotice("ckks", "releasing outgoing-queue hold"); + ckksnotice_global("ckks", "releasing outgoing-queue hold"); }]; for(size_t count = 0; count < 150; count++) { @@ -241,8 +242,6 @@ [blockExpectation fulfill]; }), @"_SecItemAddAndNotifyOnSync succeeded"); - // Release the hounds - [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; XCTestExpectation* firstQueueOperation = [self expectationWithDescription: @"found the item in the first queue iteration"]; [self expectCKModifyItemRecords:SecCKKSOutgoingQueueItemsAtOnce @@ -256,13 +255,19 @@ }]; [self expectCKModifyItemRecords:51 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; - [self waitForExpectationsWithTimeout:5.0 handler:nil]; + // Release the hounds + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; + + [self waitForExpectations:@[blockExpectation, firstQueueOperation] timeout:20]; + OCMVerifyAllWithDelay(self.mockDatabase, 10); } - (void)testAddAndNotifyOnSyncFailure { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); + [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Due to item UUID selection, this item will be added with UUID 50184A35-4480-E8BA-769B-567CF72F1EC0. @@ -371,7 +376,7 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.loggedIn wait:20*NSEC_PER_SEC], "CKKS should log in"); - [self.keychainView.zoneSetupOperation waitUntilFinished]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateFetch] wait:20*NSEC_PER_SEC], @"Should have reached key state 'fetch', but no further"); NSMutableDictionary* query = [@{ (id)kSecClass : (id)kSecClassGenericPassword, @@ -447,7 +452,7 @@ // When the policy is loaded, the item should upload and the callback should fire [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; - [self.injectedManager setSyncingViews:self.managedViewList sortingPolicy:self.viewSortingPolicyForManagedViewList]; + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; self.keychainView = [self.injectedManager findView:self.keychainZoneID.zoneName]; [self.injectedManager beginCloudKitOperationOfAllViews]; @@ -459,6 +464,67 @@ [self waitForExpectations:@[blockExpectation] timeout:5]; } +- (void)testAddAndNotifyOnSyncReaddAtSameUUIDAfterDeleteItem { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; // Make life easy for this test. + + __block CKRecordID* itemRecordID = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + itemRecordID = record.recordID; + return YES; + }]; + + [self startCKKSSubsystem]; + + // Let things shake themselves out. + [self.keychainView waitForKeyHierarchyReadiness]; + [self waitForCKModifications]; + + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, + (id)kSecAttrAccount : @"testaccount", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, + (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + + XCTestExpectation* blockExpectation = [self expectationWithDescription: @"callback occurs"]; + + XCTAssertEqual(errSecSuccess, _SecItemAddAndNotifyOnSync((__bridge CFDictionaryRef) query, NULL, ^(bool didSync, CFErrorRef error) { + XCTAssertTrue(didSync, "Item synced properly"); + XCTAssertNil((__bridge NSError*)error, "No error syncing item"); + + [blockExpectation fulfill]; + }), @"_SecItemAddAndNotifyOnSync succeeded"); + + OCMVerifyAllWithDelay(self.mockDatabase, 10); + + [self waitForExpectations:@[blockExpectation] timeout:5]; + + // And the item is deleted + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + [self deleteGenericPassword:@"testaccount"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the item is readded. It should come back to its previous UUID. + XCTAssertNotNil(itemRecordID, "Should have an item record ID"); + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + XCTAssertEqualObjects(itemRecordID.recordName, record.recordID.recordName, "Uploaded item UUID should match previous upload"); + return YES; + }]; + XCTestExpectation* blockExpectation2 = [self expectationWithDescription: @"callback occurs"]; + XCTAssertEqual(errSecSuccess, _SecItemAddAndNotifyOnSync((__bridge CFDictionaryRef) query, NULL, ^(bool didSync, CFErrorRef error) { + XCTAssertTrue(didSync, "Item synced properly"); + XCTAssertNil((__bridge NSError*)error, "No error syncing item"); + + [blockExpectation2 fulfill]; + }), @"_SecItemAddAndNotifyOnSync succeeded"); + + OCMVerifyAllWithDelay(self.mockDatabase, 10); + [self waitForExpectations:@[blockExpectation2] timeout:5]; +} + - (void)testPCSUnencryptedFieldsAdd { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. @@ -666,7 +732,7 @@ [self.keychainZone addToZone: record]; // Trigger a notification - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; CFTypeRef item = NULL; @@ -721,6 +787,7 @@ [self.keychainZone addToZone:[cipheritem CKRecordWithZoneID: recordID.zoneID]]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword, @@ -779,6 +846,7 @@ [self.keychainZone addToZone:[cipheritem CKRecordWithZoneID: recordID.zoneID]]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword, @@ -860,21 +928,25 @@ [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; [self saveTLKMaterialToKeychainSimulatingSOS:self.keychainZoneID]; - // Spin up CKKS subsystem. + // Spin up CKKS subsystem. It should fetch once. + [self expectCKFetch]; [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.loggedIn wait:500*NSEC_PER_MSEC], "Should have been told of a 'login' event on startup"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should arrive at 'waitfortrust''"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + NSData* changeTokenData = [[[NSUUID UUID] UUIDString] dataUsingEncoding:NSUTF8StringEncoding]; CKServerChangeToken* changeToken = [[CKServerChangeToken alloc] initWithData:changeTokenData]; - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.keychainView.zoneName]; ckse.changeToken = changeToken; NSError* error = nil; [ckse saveToDatabase:&error]; XCTAssertNil(error, "No error saving new zone state to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // after the reset, CKKS should refetch what's available @@ -883,12 +955,11 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"local reset callback occurs"]; [self.injectedManager rpcResetLocal:nil reply:^(NSError* result) { XCTAssertNil(result, "no error resetting local"); - secnotice("ckks", "Received a rpcResetLocal callback"); + ckksnotice_global("ckks", "Received a rpcResetLocal callback"); - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.keychainView.zoneName]; XCTAssertNotEqualObjects(changeToken, ckse.changeToken, "Change token is reset"); - return true; }]; [resetExpectation fulfill]; @@ -905,6 +976,9 @@ [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; [self beginSOSTrustedViewOperation:self.keychainView]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at 'ready''"); + [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem:[self checkClassABlock:self.keychainZoneID message:@"Object was encrypted under class A key in hierarchy"]]; [self addGenericPassword:@"asdf" account:@"account-class-A" @@ -915,6 +989,35 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testResetLocalWhileLoggedOut { + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + self.accountStatus = CKAccountStatusNoAccount; + [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; + self.silentFetchesAllowed = false; + + // Test starts with local TLK and key hierarchy in our fake cloudkit + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self saveTLKMaterialToKeychainSimulatingSOS:self.keychainZoneID]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.loggedOut wait:20*NSEC_PER_SEC], "CKKS should positively log out"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], @"Key state should arrive at 'loggedout'"); + + // Can we reset local data while logged out? + XCTestExpectation* resetExpectation = [self expectationWithDescription: @"local reset callback occurs"]; + [self.injectedManager rpcResetLocal:nil reply:^(NSError* result) { + XCTAssertNil(result, "no error resetting local"); + ckksnotice_global("ckks", "Received a rpcResetLocal callback"); + + [resetExpectation fulfill]; + }]; + + [self waitForExpectations:@[resetExpectation] timeout:20]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], @"Key state should arrive at 'loggedout'"); +} + -(void)testResetLocalMultipleTimes { // Test starts with nothing in database, but one in our fake CloudKit. [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; @@ -991,6 +1094,7 @@ [self addGenericPassword: @"data" account: @"account-delete-me"]; OCMVerifyAllWithDelay(self.mockDatabase, 20); [self waitForCKModifications]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); // During the reset, Octagon will upload the key hierarchy, and then CKKS will upload the class C item [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; @@ -998,7 +1102,7 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; @@ -1018,6 +1122,8 @@ expecting:errSecSuccess message:@"Adding class A item"]; OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); } - (void)testResetCloudKitZoneCloudKitRejects { @@ -1054,7 +1160,7 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; @@ -1124,7 +1230,6 @@ [self waitForExpectations:@[resetExpectation] timeout:20]; - XCTAssertTrue([outgoingOp isCancelled], "old stuck ProcessOutgoingQueue should be cancelled"); OCMVerifyAllWithDelay(self.mockDatabase, 20); // And adding another item works too @@ -1136,6 +1241,8 @@ expecting:errSecSuccess message:@"Adding class A item"]; OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertTrue([outgoingOp isFinished], "old ProcessOutgoingQueue should be finished"); } /* @@ -1212,16 +1319,21 @@ XCTAssertNotNil(self.keychainZone.currentDatabase, "Zone exists"); XCTAssertNotNil(self.keychainZone.currentDatabase[ckr.recordID], "An item exists in the fake zone"); + // Make the zone, so we know if it was deleted + self.keychainZone.flag = true; + XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; [self waitForExpectations:@[resetExpectation] timeout:20]; - XCTAssertNil(self.keychainZone.currentDatabase, "No zone anymore!"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], "CKKS entered 'waitfortlkcreation'"); + + XCTAssertFalse(self.keychainZone.flag, "Zone was deleted at some point"); OCMVerifyAllWithDelay(self.mockDatabase, 20); // Now log in, and see what happens! It should create the zone again and upload a whole new key hierarchy @@ -1431,6 +1543,48 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testRPCKnownBadStateWhenNoCloudKit { + self.accountStatus = CKAccountStatusNoAccount; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered loggedout"); + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + + [self.ckksControl rpcKnownBadState:@"keychain" reply:^(CKKSKnownBadState result) { + XCTAssertEqual(result, CKKSKnownStateNoCloudKitAccount, "State should be 'no cloudkit account'"); + [callbackOccurs fulfill]; + }]; + + [self waitForExpectations:@[callbackOccurs] timeout:20]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testRPCKnownBadStateWhenNoTrust { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], "CKKS entered waitfortrust"); + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + + [self.ckksControl rpcKnownBadState:@"keychain" reply:^(CKKSKnownBadState result) { + XCTAssertEqual(result, CKKSKnownStateWaitForOctagon, "State should be 'waitforoctagon'"); + [callbackOccurs fulfill]; + }]; + + [self waitForExpectations:@[callbackOccurs] timeout:20]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + - (void)testRPCKnownBadStateWhenTLKsMissing { // Bring CKKS up in waitfortlk [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; @@ -1605,10 +1759,18 @@ - (void)testRpcStatusIsFastDuringError { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. - self.keychainFetchError = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecInternalError description:@"injected keychain failure"]; - - // Let CKKS come up; it should enter 'error' + // Let CKKS come up, then force it into error [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + + OctagonStateTransitionOperation* op = [OctagonStateTransitionOperation named:@"enter" entering:SecCKKSZoneKeyStateError]; + OctagonStateTransitionRequest* request = [[OctagonStateTransitionRequest alloc] init:@"enter-wait-for-trust" + sourceStates:[NSSet setWithArray:[CKKSZoneKeyStateMap() allKeys]] + serialQueue:self.keychainView.queue + timeout:10 * NSEC_PER_SEC + transitionOp:op]; + [self.keychainView.stateMachine handleExternalRequest:request]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateError] wait:20*NSEC_PER_SEC], "CKKS entered 'error'"); // Fire off the status RPC; it should return immediately @@ -1629,6 +1791,108 @@ [self waitForExpectations:@[callbackOccurs] timeout:20]; } +- (void)testResetLocalAPIWakesDaemon { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:[self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; + [self addGenericPassword:@"data" account:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + + // Now, simulate a restart: all views suddenly go missing from the ViewManager + [self.injectedManager clearAllViews]; + [self.injectedManager resetSyncingPolicy]; + [self.injectedManager beginCloudKitOperationOfAllViews]; + + // And a reset-local API call wakes the daemon + // The policy arrives after 500ms + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (0.5 * NSEC_PER_SEC)), dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; + self.ckksViews = [NSMutableSet setWithArray:[self.injectedManager.views allValues]]; + self.keychainView = [self.injectedManager findView:@"keychain"]; + [self beginSOSTrustedOperationForAllViews]; + }); + + XCTestExpectation* resetExpectation = [self expectationWithDescription: @"local reset callback occurs"]; + [self.injectedManager rpcResetLocal:self.keychainZoneID.zoneName reply:^(NSError* result) { + XCTAssertNil(result, "no error resetting local"); + [resetExpectation fulfill]; + }]; + + [self waitForExpectations:@[resetExpectation] timeout:20]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testPushAPIWakesDaemon { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:[self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; + [self addGenericPassword:@"data" account:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + + // Now, simulate a restart: all views suddenly go missing from the ViewManager + [self.injectedManager clearAllViews]; + [self.injectedManager resetSyncingPolicy]; + [self.injectedManager beginCloudKitOperationOfAllViews]; + + // And a fetch API call wakes the daemon + // The policy arrives after 500msx + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (0.5 * NSEC_PER_SEC)), dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; + self.ckksViews = [NSMutableSet setWithArray:[self.injectedManager.views allValues]]; + [self beginSOSTrustedOperationForAllViews]; + }); + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + [self.ckksControl rpcPushOutgoingChanges:nil reply:^(NSError * _Nullable error) { + XCTAssertNil(error, "Should have received no error"); + [callbackOccurs fulfill]; + }]; + + [self waitForExpectations:@[callbackOccurs] timeout:60]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testFetchAPIWakesDaemon { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:[self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; + [self addGenericPassword:@"data" account:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + + // Now, simulate a restart: all views suddenly go missing from the ViewManager + [self.injectedManager clearAllViews]; + [self.injectedManager resetSyncingPolicy]; + [self.injectedManager beginCloudKitOperationOfAllViews]; + + // And a fetch API call wakes the daemon + // The policy arrives after 500ms + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (0.5 * NSEC_PER_SEC)), dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; + self.ckksViews = [NSMutableSet setWithArray:[self.injectedManager.views allValues]]; + [self beginSOSTrustedOperationForAllViews]; + }); + + XCTestExpectation* callbackOccurs = [self expectationWithDescription:@"callback-occurs"]; + [self.ckksControl rpcFetchAndProcessChanges:nil reply:^(NSError * _Nullable error) { + XCTAssertNil(error, "Should have received no error"); + [callbackOccurs fulfill]; + }]; + + [self waitForExpectations:@[callbackOccurs] timeout:20]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + @end #endif // OCTAGON diff --git a/keychain/ckks/tests/CKKSTests+Coalesce.m b/keychain/ckks/tests/CKKSTests+Coalesce.m index b4964441..1006a9e8 100644 --- a/keychain/ckks/tests/CKKSTests+Coalesce.m +++ b/keychain/ckks/tests/CKKSTests+Coalesce.m @@ -96,25 +96,119 @@ [self waitForCKModifications]; // Okay, now the delete/add. Note that this is not a coalescing operation, since the new item - // will have a completely different UUID, and so will delete the old record and upload the new one. + // has different contents. (This test used to upload the item to a different UUID, but no longer). + + self.keychainView.holdOutgoingQueueOperation = [CKKSResultOperation named:@"hold-outgoing-queue" + withBlock:^{}]; - [self.keychainView.operationQueue waitUntilAllOperationsAreFinished]; - self.keychainView.operationQueue.suspended = YES; [self deleteGenericPassword: account]; - [self addGenericPassword: @"data" account: account]; + [self addGenericPassword: @"data_new_contents" account: account]; + + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID + checkItem:[self checkPasswordBlock:self.keychainZoneID account:account password:@"data_new_contents"]]; - [self expectCKModifyRecords:@{SecCKRecordItemType: [NSNumber numberWithUnsignedInteger: 1], - SecCKRecordCurrentKeyType: [NSNumber numberWithUnsignedInteger: 1], - SecCKRecordDeviceStateType: [NSNumber numberWithUnsignedInteger: 1], - } - deletedRecordTypeCounts:@{SecCKRecordItemType: [NSNumber numberWithUnsignedInteger: 1]} - zoneID:self.keychainZoneID - checkModifiedRecord:nil - runAfterModification:nil]; - self.keychainView.operationQueue.suspended = NO; + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testCoalesceReceiveModifyWhileDeletingItem { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + + NSString* account = @"account-delete-me"; + + [self addGenericPassword:@"data" account:account]; + + // We expect a single record to be uploaded. + __block CKRecord* itemRecord = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID + checkItem:^BOOL(CKRecord * _Nonnull record) { + itemRecord = record; + return YES; + }]; + + [self startCKKSSubsystem]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + // Now, we receive a modification from CK, but then delete the item locally before processing the IQE. + + XCTAssertNotNil(itemRecord, "Should have a record for the uploaded item"); + NSMutableDictionary* contents = [[self decryptRecord:itemRecord] mutableCopy]; + contents[@"v_Data"] = [@"updated" dataUsingEncoding:NSUTF8StringEncoding]; + + CKRecord* recordUpdate = [self newRecord:itemRecord.recordID withNewItemData:contents]; + [self.keychainZone addCKRecordToZone:recordUpdate]; + + self.keychainView.holdIncomingQueueOperation = [NSBlockOperation blockOperationWithBlock:^{}]; + + // Ensure we wait for the whole fetch + NSOperation* fetchOp = [self.keychainView.zoneChangeFetcher requestSuccessfulFetch:CKKSFetchBecauseTesting]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + + [fetchOp waitUntilFinished]; + + // now, delete the item + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + [self deleteGenericPassword:account]; + + [self.operationQueue addOperation:self.keychainView.holdIncomingQueueOperation]; + + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the item shouldn't be present, since it was deleted via API after the item was fetched + [self findGenericPassword:account expecting:errSecItemNotFound]; +} + +- (void)testCoalesceReceiveDeleteWhileModifyingItem { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + + NSString* account = @"account-delete-me"; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); + + __block CKRecord* itemRecord = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID + checkItem:^BOOL(CKRecord * _Nonnull record) { + itemRecord = record; + return YES; + }]; + + [self addGenericPassword:@"data" account:account]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + // Ensure we fetch again, to prime the delete (due to insufficient mock CK) + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + // Now, we receive a delete from CK, but after we modify the item locally + self.keychainView.holdOutgoingQueueOperation = [NSBlockOperation blockOperationWithBlock:^{}]; + + XCTAssertNotNil(itemRecord, "Should have an item record from the upload"); + [self.keychainZone deleteCKRecordIDFromZone:itemRecord.recordID]; + [self updateGenericPassword:@"new-password" account:account]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self findGenericPassword:account expecting:errSecItemNotFound]; + + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; + + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the item shouldn't be present, since it was deleted via CK after the API change + [self findGenericPassword:account expecting:errSecItemNotFound]; +} + @end #endif diff --git a/keychain/ckks/tests/CKKSTests+CurrentPointerAPI.m b/keychain/ckks/tests/CKKSTests+CurrentPointerAPI.m index e2b7c753..e740a001 100644 --- a/keychain/ckks/tests/CKKSTests+CurrentPointerAPI.m +++ b/keychain/ckks/tests/CKKSTests+CurrentPointerAPI.m @@ -228,7 +228,7 @@ CFReleaseNull(cfresult); if(![actualSHA1 isEqual:sha1]) { - secnotice("ckks", "SHA1s don't match, but why?"); + ckksnotice_global("ckks", "SHA1s don't match, but why?"); } XCTestExpectation* otherSetCurrentExpectation = [self expectationWithDescription: @"callback occurs"]; @@ -572,7 +572,7 @@ // Ensure that receiving the current item pointer generates a notification keychainChanged = [self expectChangeForView:self.keychainZoneID.zoneName]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self waitForExpectations:@[keychainChanged] timeout:8]; @@ -591,7 +591,7 @@ keychainChanged = [self expectChangeForView:self.keychainZoneID.zoneName]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self waitForExpectations:@[keychainChanged] timeout:8]; @@ -656,7 +656,7 @@ CKRecord* currentPointerRecord = self.keychainZone.currentDatabase[currentPointerRecordID]; XCTAssertNotNil(currentPointerRecord, "Found record in CloudKit at expected UUID"); - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self fetchCurrentPointer:false persistentRef:persistentRef]; @@ -666,7 +666,8 @@ // Another machine comes along and deletes the pointer! [self.keychainZone deleteCKRecordIDFromZone: currentPointerRecordID]; - [self.keychainView notifyZoneChange:nil]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self waitForExpectations:@[keychainChanged] timeout:8]; @@ -826,11 +827,11 @@ modifiedRecord[SecCKRecordServerWasCurrent] = [NSNumber numberWithInteger:10]; [self.keychainZone addToZone:modifiedRecord]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Check that the number is on the CKKSMirrorEntry - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; CKKSMirrorEntry* ckme = [CKKSMirrorEntry fromDatabase:@"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID error:&error]; @@ -838,8 +839,6 @@ XCTAssertNotNil(ckme, "Received a ckme"); XCTAssertEqual(ckme.wasCurrent, 10u, "Properly received wasCurrent"); - - return true; }]; } @@ -1067,7 +1066,7 @@ [self.keychainZone addToZone: mismatchedRecord]; self.keychainView.holdIncomingQueueOperation = [CKKSResultOperation named:@"hold-incoming" withBlock:^{ - secnotice("ckks", "Releasing process incoming queue hold"); + ckksnotice_global("ckks", "Releasing process incoming queue hold"); }]; NSData* firstItemData = [@"asdf" dataUsingEncoding:NSUTF8StringEncoding]; @@ -1143,6 +1142,7 @@ [self waitForExpectations:@[setCurrentExpectation] timeout:20]; // Reissue a fetch and find the new persistent ref and sha1 for the item at this UUID + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // The conflicting item update should have won diff --git a/keychain/ckks/tests/CKKSTests+ForwardCompatibility.m b/keychain/ckks/tests/CKKSTests+ForwardCompatibility.m new file mode 100644 index 00000000..26824680 --- /dev/null +++ b/keychain/ckks/tests/CKKSTests+ForwardCompatibility.m @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2020 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@ + */ + +#if OCTAGON + +#import +#import +#import + +#import +#import +#import + +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/tests/CKKSTests.h" +#import "keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h" +#import "keychain/ckks/tests/CloudKitMockXCTest.h" +#import "keychain/ckks/tests/MockCloudKit.h" + +@interface CloudKitKeychainForwardCompatibilityTests : CloudKitKeychainSyncingTestsBase +@property CKRecordZoneID* unknownZoneID; +@property CKRecordZoneID* passwordsZoneID; +@property CKKSKeychainView* passwordsView; + +@property TPSyncingPolicy* originalPolicy; +@property TPSyncingPolicy* originalPolicyPlusUnknownVwht; +@property TPSyncingPolicy* allItemsToPasswordsPolicy; +@end + +@implementation CloudKitKeychainForwardCompatibilityTests + +- (void)setUp { + [super setUp]; + + self.passwordsZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"Passwords" ownerName:CKCurrentUserDefaultName]; + self.unknownZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"unknown-zone" ownerName:CKCurrentUserDefaultName]; + + self.zones[self.passwordsZoneID] = [[FakeCKZone alloc] initZone:self.passwordsZoneID]; + + self.originalPolicy = self.viewSortingPolicyForManagedViewList; + + + NSMutableArray* newRules = [self.originalPolicy.keyViewMapping mutableCopy]; + TPPBPolicyKeyViewMapping* unknownVwhtMapping = [[TPPBPolicyKeyViewMapping alloc] init]; + unknownVwhtMapping.view = self.keychainZoneID.zoneName; + unknownVwhtMapping.matchingRule = [TPDictionaryMatchingRule fieldMatch:@"vwht" + fieldRegex:[NSString stringWithFormat:@"^%@$", self.unknownZoneID.zoneName]]; + [newRules insertObject:unknownVwhtMapping atIndex:0]; + + self.originalPolicyPlusUnknownVwht = [[TPSyncingPolicy alloc] initWithModel:@"test-policy" + version:[[TPPolicyVersion alloc] initWithVersion:2 hash:@"fake-policy-for-views-with-unknown-view"] + viewList:self.originalPolicy.viewList + userControllableViews:self.originalPolicy.userControllableViews + syncUserControllableViews:self.originalPolicy.syncUserControllableViews + viewsToPiggybackTLKs:self.originalPolicy.viewsToPiggybackTLKs + keyViewMapping:newRules]; + + TPPBPolicyKeyViewMapping* passwordsVwhtMapping = [[TPPBPolicyKeyViewMapping alloc] init]; + passwordsVwhtMapping.view = self.passwordsZoneID.zoneName; + passwordsVwhtMapping.matchingRule = [TPDictionaryMatchingRule trueMatch]; + + self.allItemsToPasswordsPolicy = [[TPSyncingPolicy alloc] initWithModel:@"test-policy" + version:[[TPPolicyVersion alloc] initWithVersion:2 hash:@"fake-policy-for-views-with-passwords-view"] + viewList:[NSSet setWithArray:@[self.keychainView.zoneName, self.passwordsZoneID.zoneName]] + userControllableViews:self.originalPolicy.userControllableViews + syncUserControllableViews:self.originalPolicy.syncUserControllableViews + viewsToPiggybackTLKs:self.originalPolicy.viewsToPiggybackTLKs + keyViewMapping:@[passwordsVwhtMapping]]; +} + +- (void)setPolicyAndWaitForQuiescence:(TPSyncingPolicy*)policy policyIsFresh:(BOOL)policyIsFresh { + [self.injectedManager setCurrentSyncingPolicy:policy policyIsFresh:policyIsFresh]; + self.ckksViews = [NSMutableSet setWithArray:[[self.injectedManager views] allValues]]; + [self beginSOSTrustedOperationForAllViews]; + + // And wait for everything to enter a resting state + for(CKKSKeychainView* view in self.ckksViews) { + XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + [view waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [view waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + } +} + +- (void)testReceiveItemForWrongView { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + NSString* wrongZoneAccount = @"wrong-zone"; + NSDictionary* item = [self fakeRecordDictionary:wrongZoneAccount zoneID:self.unknownZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.keychainZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:item]; + [self.keychainZone addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + [self findGenericPassword:wrongZoneAccount expecting:errSecItemNotFound]; + + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + + NSError* zoneError = nil; + NSInteger count = [CKKSIncomingQueueEntry countByState:SecCKKSStateMismatchedView zone:self.keychainView.zoneID error:&zoneError]; + XCTAssertNil(zoneError, "should be no error counting all IQEs"); + XCTAssertEqual(count, 1, "Should be one mismatched IQE"); +} + +- (void)testConflictingItemInWrongView { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + self.passwordsView = [self.injectedManager findView:@"Passwords"]; + XCTAssertNotNil(self.passwordsView, @"Policy created a passwords view"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + XCTAssertEqual(0, [self.passwordsView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + NSDictionary* item = [self fakeRecordDictionary:@"account-delete-me" zoneID:self.passwordsZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.passwordsZoneID]; + CKRecordID* ckr2id = [[CKRecordID alloc] initWithRecordName:@"FFFF8D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.keychainZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:item]; + + NSMutableDictionary* item2 = [item mutableCopy]; + item2[@"v_Data"] = @"wrongview"; + CKRecord* ckr2 = [self newRecord:ckr2id withNewItemData:item2]; + + // Receive the passwords item first + [self.zones[self.passwordsZoneID] addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.passwordsView waitForFetchAndIncomingQueueProcessing]; + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + [self.zones[self.keychainZoneID] addToZone:ckr2]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // THe view should ask for an update, and receive one + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + // And we have ignored the change in the other view + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the item is then deleted + [self.zones[self.keychainZoneID] deleteCKRecordIDFromZone:ckr2id]; + OCMExpect([self.requestPolicyCheck trigger]); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + // The password should still exist + [self checkGenericPassword:@"data" account:@"account-delete-me"]; +} + +- (void)testConflictingItemInWrongViewWithLowerUUID { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + self.passwordsView = [self.injectedManager findView:@"Passwords"]; + XCTAssertNotNil(self.passwordsView, @"Policy created a passwords view"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + XCTAssertEqual(0, [self.passwordsView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + NSDictionary* item = [self fakeRecordDictionary:@"account-delete-me" zoneID:self.passwordsZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.passwordsZoneID]; + CKRecordID* ckr2id = [[CKRecordID alloc] initWithRecordName:@"00008D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.keychainZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:item]; + + NSMutableDictionary* item2 = [item mutableCopy]; + item2[@"v_Data"] = @"wrongview"; + CKRecord* ckr2 = [self newRecord:ckr2id withNewItemData:item2]; + + // Receive the passwords item first + [self.zones[self.passwordsZoneID] addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.passwordsView waitForFetchAndIncomingQueueProcessing]; + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + [self.zones[self.keychainZoneID] addToZone:ckr2]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // THe view should ask for an update, and receive one + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + // And the item is then deleted + [self.zones[self.keychainZoneID] deleteCKRecordIDFromZone:ckr2id]; + OCMExpect([self.requestPolicyCheck trigger]); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + // The password should still exist + [self checkGenericPassword:@"data" account:@"account-delete-me"]; +} + +- (void)testConflictingItemInWrongViewWithSameUUID { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + self.passwordsView = [self.injectedManager findView:@"Passwords"]; + XCTAssertNotNil(self.passwordsView, @"Policy created a passwords view"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + XCTAssertEqual(0, [self.passwordsView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + NSDictionary* item = [self fakeRecordDictionary:@"account-delete-me" zoneID:self.passwordsZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.passwordsZoneID]; + CKRecordID* ckr2id = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.keychainZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:item]; + + NSMutableDictionary* item2 = [item mutableCopy]; + item2[@"v_Data"] = @"wrongview"; + CKRecord* ckr2 = [self newRecord:ckr2id withNewItemData:item2]; + + // Receive the passwords item first + [self.zones[self.passwordsZoneID] addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.passwordsView waitForFetchAndIncomingQueueProcessing]; + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + [self.zones[self.keychainZoneID] addToZone:ckr2]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // THe view should ask for a policy update, and receive one + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self checkGenericPassword:@"data" account:@"account-delete-me"]; + + // And the item is then deleted + [self.zones[self.keychainZoneID] deleteCKRecordIDFromZone:ckr2id]; + OCMExpect([self.requestPolicyCheck trigger]); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + // The password should still exist + [self checkGenericPassword:@"data" account:@"account-delete-me"]; +} + +- (void)testReceiveItemForFuturePolicy { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + NSString* wrongZoneAccount = @"wrong-zone"; + NSDictionary* item = [self fakeRecordDictionary:wrongZoneAccount zoneID:self.unknownZoneID]; + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" zoneID:self.keychainZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:item]; + [self.keychainZone addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + [self findGenericPassword:wrongZoneAccount expecting:errSecItemNotFound]; + + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + + // Now, Octagon discovers that there's a new policy that allows this item in the keychain view + TPSyncingPolicy* currentPolicy = self.injectedManager.policy; + XCTAssertNotNil(currentPolicy, "should have a current policy"); + + [self setPolicyAndWaitForQuiescence:self.originalPolicyPlusUnknownVwht policyIsFresh:YES]; + + [self findGenericPassword:wrongZoneAccount expecting:errSecSuccess]; +} + +- (void)testHandleItemMovedBetweenViewsBeforePolicyChange { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + // A password is created and uploaded out of the keychain view. + __block CKRecord* itemCKRecord = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + itemCKRecord = record; + return YES; + }]; + NSString* itemAccount = @"account-delete-me"; + [self addGenericPassword:@"data" account:itemAccount viewHint:self.keychainZoneID.zoneName]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertNotNil(itemCKRecord, "Should have some CKRecord for the added item"); + + // Update etag as well + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // Another device shows up, changes the item sync policy, and moves the item over into the passwords view. + + NSDictionary* itemContents = [self decryptRecord:itemCKRecord]; + XCTAssertNotNil(itemContents, "should have some item contents"); + + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:itemCKRecord.recordID.recordName zoneID:self.passwordsZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:itemContents]; + [self.zones[self.passwordsZoneID] addToZone:ckr]; + + TPSyncingPolicy* currentPolicy = self.injectedManager.policy; + XCTAssertNotNil(currentPolicy, "should have a current policy"); + + // In this test, we receive the deletion, and then the policy change adding the Passwords view + [self.keychainZone deleteCKRecordIDFromZone:itemCKRecord.recordID]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self findGenericPassword:itemAccount expecting:errSecItemNotFound]; + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + + // And once passwords syncs, the item should appear again + [self findGenericPassword:itemAccount expecting:errSecSuccess]; +} + +- (void)testHandleItemMovedBetweenViewsAfterPolicyChange { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + // A password is created and uploaded out of the keychain view. + __block CKRecord* itemCKRecord = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + itemCKRecord = record; + return YES; + }]; + NSString* itemAccount = @"account-delete-me"; + [self addGenericPassword:@"data" account:itemAccount viewHint:self.keychainZoneID.zoneName]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertNotNil(itemCKRecord, "Should have some CKRecord for the added item"); + + // Update etag as well + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // Another device shows up, changes the item sync policy, and moves the item over into the Passwords view. + // But, in this case, we receive the item delete in the Keychain view after we've synced the item in the Passwords view + + NSDictionary* itemContents = [self decryptRecord:itemCKRecord]; + XCTAssertNotNil(itemContents, "should have some item contents"); + + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:itemCKRecord.recordID.recordName zoneID:self.passwordsZoneID]; + CKRecord* ckr = [self newRecord:ckrid withNewItemData:itemContents]; + [self.zones[self.passwordsZoneID] addToZone:ckr]; + + TPSyncingPolicy* currentPolicy = self.injectedManager.policy; + XCTAssertNotNil(currentPolicy, "should have a current policy"); + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + + CKKSKeychainView* passwordsView = [self.injectedManager findView:self.passwordsZoneID.zoneName]; + XCTAssertNotNil(passwordsView, @"Should have a passwords view"); + + // And once Passwords syncs, the item should appear again + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + + // And now we receive the delete in the keychain view. The item should still exist! + [self.keychainZone deleteCKRecordIDFromZone:itemCKRecord.recordID]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + + // Keychain View should have asked for a policy set + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + [self.injectedManager setCurrentSyncingPolicy:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + + NSError* zoneError = nil; + NSInteger count = [CKKSIncomingQueueEntry countByState:SecCKKSStateMismatchedView zone:self.keychainView.zoneID error:&zoneError]; + XCTAssertNil(zoneError, "should be no error counting all IQEs"); + XCTAssertEqual(count, 0, "Should be no remaining mismatched IQEs"); +} + +- (void)testMoveItemUploadedToOldZone { + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMExpect([self.requestPolicyCheck trigger]); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self createAndSaveFakeKeyHierarchy:self.passwordsZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + [self setPolicyAndWaitForQuiescence:self.allItemsToPasswordsPolicy policyIsFresh:NO]; + + // Now, someone uploads an item to the keychain view. We should move it to the passwords view + CKRecord* ckr = [self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" withAccount:@"account0"]; + [self.keychainZone addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // The keychain view should request a policy refetch + OCMVerifyAllWithDelay(self.requestPolicyCheck, 10); + + // Note that ideally, we'd remove the old item from CloudKit. But, other devices which participate in CKKS4All + // might not have this forward-compatiblity change, and will treat this as a deletion. If they process this deletion, + // then sync the resulting tombstone to a third SOS device, then receive the addition in the 'right' view, and then the + // tombstone syncs back to the CKKS4All devices, then we might end up deleting the item across the account. + // Until enough internal folk have moved onto builds with this forward-compat change, we can't issue these deletes. + //[self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + + // The item should be reuploaded to Passwords, though. + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.passwordsZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + return [record.recordID.recordName isEqualToString:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; + }]; + + [self.injectedManager setCurrentSyncingPolicy:self.allItemsToPasswordsPolicy policyIsFresh:YES]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the keychain item should still exist + [self findGenericPassword:@"account0" expecting:errSecSuccess]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/tests/CKKSTests+ItemSyncChoice.m b/keychain/ckks/tests/CKKSTests+ItemSyncChoice.m new file mode 100644 index 00000000..7ec26bf1 --- /dev/null +++ b/keychain/ckks/tests/CKKSTests+ItemSyncChoice.m @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2020 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@ + */ + +#if OCTAGON + +#import +#import +#import + +#import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/ckks/CKKS.h" +#import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSOutgoingQueueEntry.h" +#import "keychain/ckks/CloudKitCategories.h" +#import "keychain/ckks/tests/CKKSTests.h" +#import "keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h" +#import "keychain/ckks/tests/CloudKitMockXCTest.h" +#import "keychain/ckks/tests/MockCloudKit.h" + +@interface CloudKitKeychainSyncingItemSyncChoiceTests : CloudKitKeychainSyncingTestsBase +@property CKKSSOSSelfPeer* remotePeer1; +@end + +@implementation CloudKitKeychainSyncingItemSyncChoiceTests + +- (size_t)outgoingQueueSize:(CKKSKeychainView*)view { + __block size_t result = 0; + + [view dispatchSyncWithReadOnlySQLTransaction:^{ + NSError* zoneError = nil; + NSArray* entries = [CKKSOutgoingQueueEntry all:view.zoneID error:&zoneError]; + XCTAssertNil(zoneError, "should be no error fetching all OQEs"); + + result = (size_t)entries.count; + }]; + return result; +} + +- (size_t)incomingQueueSize:(CKKSKeychainView*)view { + __block size_t result = 0; + + [view dispatchSyncWithReadOnlySQLTransaction:^{ + NSError* zoneError = nil; + NSArray* entries = [CKKSIncomingQueueEntry all:view.zoneID error:&zoneError]; + XCTAssertNil(zoneError, "should be no error fetching all IQEs"); + + result = (size_t)entries.count; + }]; + return result; +} + +- (void)setUp { + [super setUp]; + + self.remotePeer1 = [[CKKSSOSSelfPeer alloc] initWithSOSPeerID:@"remote-peer1" + encryptionKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] + signingKey:[[SFECKeyPair alloc] initRandomKeyPairWithSpecifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384]] + viewList:self.managedViewList]; +} + +- (void)testAddItemToPausedView { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + [self addGenericPassword:@"data" account:@"account-delete-me"]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + XCTAssertEqual(1, [self outgoingQueueSize:self.keychainView], "There should be one pending item in the outgoing queue"); + + // and again + [self addGenericPassword:@"data" account:@"account-delete-me-2"]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + XCTAssertEqual(2, [self outgoingQueueSize:self.keychainView], "There should be two pending item in the outgoing queue"); + + // When syncing is enabled, these items should sync + [self expectCKModifyItemRecords:2 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED] + policyIsFresh:NO]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testReceiveItemToPausedView { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + [self findGenericPassword: @"account0" expecting:errSecItemNotFound]; + + [self.keychainZone addToZone:[self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D00" withAccount:@"account0"]]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + XCTAssertEqual(1, [self incomingQueueSize:self.keychainView], "There should be one pending item in the incoming queue"); + + [self.keychainZone addToZone:[self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-0000-5A507ACB2D00" withAccount:@"account1"]]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + XCTAssertEqual(2, [self incomingQueueSize:self.keychainView], "There should be two pending item in the incoming queue"); + + [self findGenericPassword:@"account0" expecting:errSecItemNotFound]; + [self findGenericPassword:@"account1" expecting:errSecItemNotFound]; + + // When syncing is enabled, these items should sync + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED] + policyIsFresh:NO]; + + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + [self findGenericPassword:@"account0" expecting:errSecSuccess]; + [self findGenericPassword:@"account1" expecting:errSecSuccess]; +} + +- (void)testAcceptKeyHierarchyWhilePaused { + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self saveTLKMaterialToKeychain:self.keychainZoneID]; + [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should have become ready"); +} + +- (void)testUploadSelfTLKShare { + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + // Test starts with no keys in CKKS database, but one in our fake CloudKit. + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + + // Test also starts with the TLK shared to all trusted peers from peer1 + [self.mockSOSAdapter.trustedPeers addObject:self.remotePeer1]; + [self putTLKSharesInCloudKit:self.keychainZoneKeys.tlk from:self.remotePeer1 zoneID:self.keychainZoneID]; + + // The CKKS subsystem should accept the keys, and share the TLK back to itself + [self expectCKModifyKeyRecords:0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); + + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testSendNewTLKSharesOnTrustSetAddition { + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + // step 1: add a new peer; we should share the TLK with them + // start with no trusted peers + [self.mockSOSAdapter.trustedPeers removeAllObjects]; + + [self startCKKSSubsystem]; + [self performOctagonTLKUpload:self.ckksViews]; + + [self expectCKModifyKeyRecords:0 currentKeyPointerRecords:0 tlkShareRecords:1 zoneID:self.keychainZoneID]; + [self.mockSOSAdapter.trustedPeers addObject:self.remotePeer1]; + [self.mockSOSAdapter sendTrustedPeerSetChangedUpdate]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + // and just double-check that no syncing is occurring + [self addGenericPassword:@"data" account:@"account-delete-me"]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + XCTAssertEqual(1, [self outgoingQueueSize:self.keychainView], "There should be one pending item in the outgoing queue"); +} + +- (void)testAddAndNotifyOnSyncDuringPausedOperation { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should have become ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView setCurrentSyncingPolicy:[self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet setWithObject:self.keychainView.zoneName] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED] + policyIsFresh:NO]; + + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlock, + (id)kSecAttrAccount : @"testaccount", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrSyncViewHint : self.keychainView.zoneName, + (id)kSecValueData : (id) [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + + XCTestExpectation* blockExpectation = [self expectationWithDescription: @"callback occurs"]; + + XCTAssertEqual(errSecSuccess, _SecItemAddAndNotifyOnSync((__bridge CFDictionaryRef) query, NULL, ^(bool didSync, CFErrorRef cferror) { + XCTAssertFalse(didSync, "Item did not sync"); + + NSError* error = (__bridge NSError*)cferror; + XCTAssertNotNil(error, "Error syncing item"); + XCTAssertEqual(error.domain, CKKSErrorDomain, "Error domain was CKKSErrorDomain"); + XCTAssertEqual(error.code, CKKSErrorViewIsPaused, "Error code is 'view is paused'"); + + [blockExpectation fulfill]; + }), @"_SecItemAddAndNotifyOnSync succeeded"); + + OCMVerifyAllWithDelay(self.mockDatabase, 10); + + [self waitForExpectationsWithTimeout:5.0 handler:nil]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ckks/tests/CKKSTests+MultiZone.m b/keychain/ckks/tests/CKKSTests+MultiZone.m index 0823b71d..acc9d41e 100644 --- a/keychain/ckks/tests/CKKSTests+MultiZone.m +++ b/keychain/ckks/tests/CKKSTests+MultiZone.m @@ -20,6 +20,7 @@ #import "keychain/ckks/CKKSKey.h" #import "keychain/ckks/CKKSOutgoingQueueEntry.h" #import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSStates.h" #import "keychain/ckks/CKKSSynchronizeOperation.h" #import "keychain/ckks/CKKSViewManager.h" #import "keychain/ckks/CKKSZoneStateEntry.h" @@ -53,12 +54,12 @@ - (NSSet*)managedViewList { NSMutableSet* parentSet = [[super managedViewList] mutableCopy]; - [parentSet addObject:@"SafariPasswords"]; + [parentSet addObject:@"Passwords"]; return parentSet; } // Make a policy as normal for most views, but Passwords is special -- (TPPolicy*)viewSortingPolicyForManagedViewList +- (TPSyncingPolicy*)viewSortingPolicyForManagedViewList { NSMutableArray* rules = [NSMutableArray array]; @@ -67,7 +68,7 @@ mapping.view = viewName; // The real passwords view is on com.appple.cfnetwork, but for these tests, let's just use the sbd agrp (because of how the entitlements are specified) - if([viewName isEqualToString:@"SafariPasswords"]) { + if([viewName isEqualToString:@"Passwords"]) { mapping.matchingRule = [TPDictionaryMatchingRule fieldMatch:@"agrp" fieldRegex:[NSString stringWithFormat:@"^com\\.apple\\.sbd$"]]; } else { @@ -78,12 +79,14 @@ [rules addObject:mapping]; } - TPPolicy* policy = [TPPolicy policyWithModelToCategory:@[] - categoriesByView:@{} - introducersByCategory:@{} - keyViewMapping:rules - unknownRedactions:NO - version:[[TPPolicyVersion alloc] initWithVersion:1 hash:@"fake-policy-for-views"]]; + NSSet* viewList = [self managedViewList]; + TPSyncingPolicy* policy = [[TPSyncingPolicy alloc] initWithModel:@"test-policy" + version:[[TPPolicyVersion alloc] initWithVersion:1 hash:@"fake-policy-for-views"] + viewList:viewList + userControllableViews:[NSSet set] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED + viewsToPiggybackTLKs:[viewList containsObject:@"Passwords"] ? [NSSet setWithObject:@"Passwords"] : [NSSet set] + keyViewMapping:rules]; return policy; } @@ -155,10 +158,10 @@ [self.ckksViews addObject:self.limitedView]; [self.ckksZones addObject:self.limitedZoneID]; - self.passwordsZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"SafariPasswords" ownerName:CKCurrentUserDefaultName]; + self.passwordsZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"Passwords" ownerName:CKCurrentUserDefaultName]; self.passwordsZone = [[FakeCKZone alloc] initZone: self.passwordsZoneID]; self.zones[self.passwordsZoneID] = self.passwordsZone; - self.passwordsView = [[CKKSViewManager manager] findOrCreateView:@"SafariPasswords"]; + self.passwordsView = [[CKKSViewManager manager] findOrCreateView:@"Passwords"]; XCTAssertNotNil(self.passwordsView, "should have a passwords ckks view"); XCTAssertNotNil(self.passwordsView, "CKKSViewManager created the Passwords view"); [self.ckksViews addObject:self.passwordsView]; @@ -166,7 +169,7 @@ // These tests, at least, will use the policy codepaths! [self.injectedManager setOverrideCKKSViewsFromPolicy:YES]; - [self.injectedManager setSyncingViews:self.managedViewList sortingPolicy:self.viewSortingPolicyForManagedViewList]; + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; } + (void)tearDown { @@ -525,6 +528,10 @@ [self waitForKeyHierarchyReadinesses]; [self.passwordsView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + // Ensure that we catch up to the newest CK change token so our fake cloudkit will notice the delete at fetch time + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.passwordsView waitForFetchAndIncomingQueueProcessing]; + // Now, the item is deleted. Do we properly remove it? CKRecord* itemRecord = nil; for(CKRecord* record in [self.passwordsZone.currentDatabase allValues]) { @@ -545,12 +552,14 @@ CFTypeRef item = NULL; XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should still exist"); - XCTAssertNotNil((__bridge id)item, "No item should have been found"); + XCTAssertNotNil((__bridge id)item, "An item should have been found"); CFReleaseNull(item); // Now, the item is deleted. The passwords view should delete the local item, even though it has the wrong 'vwht' on disk. + XCTAssertNotNil(self.passwordsZone.currentDatabase[itemRecord.recordID], "Record should exist in fake CK"); [self.passwordsZone deleteCKRecordIDFromZone:itemRecord.recordID]; - [self.passwordsView notifyZoneChange:nil]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.passwordsView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should no longer exist"); @@ -611,11 +620,8 @@ [self saveFakeKeyHierarchiesToLocalDatabase]; // Make life easy for this test. [self startCKKSSubsystem]; - for(CKRecordZoneID* zoneID in self.ckksZones) { - [self expectCKKSTLKSelfShareUpload:zoneID]; - } - [self waitForKeyHierarchyReadinesses]; + [self.engramView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; [self findGenericPassword:@"account-delete-me" expecting:errSecItemNotFound]; @@ -625,10 +631,15 @@ XCTestExpectation* engramChanged = [self expectChangeForView:self.engramZoneID.zoneName]; XCTestExpectation* pcsChanged = [self expectChangeForView:@"PCS"]; + self.silentFetchesAllowed = false; + [self expectCKFetch]; + // Trigger a notification (with hilariously fake data) - [self.engramView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); [self.engramView waitForFetchAndIncomingQueueProcessing]; + [self findGenericPassword:@"account-delete-me" expecting:errSecSuccess]; [self waitForExpectations:@[engramChanged] timeout:1]; @@ -660,14 +671,12 @@ [self expectCKFetch]; // one to fail with a CKErrorChangeTokenExpired error [self expectCKFetch]; // and one to succeed - [self.manateeView dispatchSyncWithAccountKeys: ^bool { - [self.manateeView _onqueueKeyStateMachineRequestFetch]; - return true; - }]; + [self.manateeView.stateMachine handleFlag:CKKSFlagFetchRequested]; XCTAssertEqual(0, [self.manateeView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS should enter 'ready'"); - [self.manateeView waitForFetchAndIncomingQueueProcessing]; + // Don't cause another fetch, because the machinery might not be ready + [self.manateeView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -710,7 +719,7 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-all-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; @@ -764,7 +773,7 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-all-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; @@ -820,7 +829,7 @@ XCTestExpectation* resetExpectation = [self expectationWithDescription: @"reset callback occurs"]; [self.injectedManager rpcResetCloudKit:nil reason:@"reset-test" reply:^(NSError* result) { XCTAssertNil(result, "no error resetting cloudkit"); - secnotice("ckks", "Received a resetCloudKit callback"); + ckksnotice_global("ckks", "Received a resetCloudKit callback"); [resetExpectation fulfill]; }]; @@ -912,15 +921,15 @@ self.manateeZone.limitFetchTo = manateeChangeToken1; // Attempt to trigger simultaneous key state resyncs. This is a horrible hack... - [self.manateeView dispatchSyncWithAccountKeys:^bool { + [self.manateeView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ self.manateeView.keyStateFullRefetchRequested = YES; - [self.manateeView _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; + [self.manateeView _onqueuePokeKeyStateMachine]; + return CKKSDatabaseTransactionCommit; }]; - [self.healthView dispatchSyncWithAccountKeys:^bool { + [self.healthView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ self.healthView.keyStateFullRefetchRequested = YES; - [self.healthView _onqueueAdvanceKeyStateMachineToState:nil withError:nil]; - return true; + [self.healthView _onqueuePokeKeyStateMachine]; + return CKKSDatabaseTransactionCommit; }]; OCMVerifyAllWithDelay(self.mockDatabase, 20); diff --git a/keychain/ckks/tests/CKKSTests.m b/keychain/ckks/tests/CKKSTests.m index 8baf53aa..a25f962f 100644 --- a/keychain/ckks/tests/CKKSTests.m +++ b/keychain/ckks/tests/CKKSTests.m @@ -44,12 +44,12 @@ #import "keychain/ckks/CKKSKey.h" #import "keychain/ckks/CKKSOutgoingQueueEntry.h" #import "keychain/ckks/CKKSIncomingQueueEntry.h" +#import "keychain/ckks/CKKSStates.h" #import "keychain/ckks/CKKSSynchronizeOperation.h" #import "keychain/ckks/CKKSViewManager.h" #import "keychain/ckks/CKKSZoneStateEntry.h" #import "keychain/ckks/CKKSManifest.h" #import "keychain/ckks/CKKSAnalytics.h" -#import "keychain/ckks/CKKSHealKeyHierarchyOperation.h" #import "keychain/ckks/CKKSZoneChangeFetcher.h" #import "keychain/categories/NSError+UsefulConstructors.h" #import "keychain/ckks/CKKSPeer.h" @@ -57,6 +57,7 @@ #import "keychain/ckks/tests/MockCloudKit.h" #import "keychain/ckks/tests/CKKSTests.h" +#import "keychain/ot/ObjCImprovements.h" #import // break abstraction @@ -89,24 +90,56 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } -- (void)testActiveTLKS { +- (void)testActiveTLKs { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. // We expect a single record to be uploaded. [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; [self startCKKSSubsystem]; - [self addGenericPassword: @"data" account: @"account-delete-me"]; OCMVerifyAllWithDelay(self.mockDatabase, 20); - NSDictionary* tlks = [[CKKSViewManager manager] activeTLKs]; + NSError* localError = nil; + NSArray* tlks = [[CKKSViewManager manager] currentTLKsFilteredByPolicy:NO error:&localError]; + XCTAssertNil(localError, "Should have no error fetching current TLKs"); + + XCTAssertEqual([tlks count], (NSUInteger)1, "Should have one TLK"); + XCTAssertEqualObjects(tlks[0].zoneID.zoneName, @"keychain", "should have a TLK for keychain"); - XCTAssertEqual([tlks count], (NSUInteger)1, "One TLK"); - XCTAssertNotNil(tlks[@"keychain"], "keychain have a UUID"); + XCTAssertEqualObjects(tlks[0].uuid, self.keychainZoneKeys.tlk.uuid, "should have the TLK matching cloudkit"); } +- (void)testActiveTLKsWhenMissing { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], @"Key state should have arrived at waitfortlk"); + + NSError* localError = nil; + NSArray* tlks = [[CKKSViewManager manager] currentTLKsFilteredByPolicy:NO error:&localError]; + XCTAssertNil(localError, "Should have no error fetching current TLKs"); + + XCTAssertEqual([tlks count], (NSUInteger)0, "Should have zero TLKs"); +} + +- (void)testActiveTLKsWhenLocked { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + + self.aksLockState = true; + [self.lockStateTracker recheck]; + + NSError* localError = nil; + NSArray* tlks = [[CKKSViewManager manager] currentTLKsFilteredByPolicy:NO error:&localError]; + XCTAssertNotNil(localError, "Should have an error fetching current TLKs"); + + XCTAssertEqual([tlks count], (NSUInteger)0, "Should have zero TLKs"); +} - (void)testAddMultipleItems { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. @@ -135,13 +168,14 @@ [self.keychainView waitUntilAllOperationsAreFinished]; + // We expect an upload of the added item, once CKKS finds the UUID-less item and fixes it + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + SecCKKSTestSetDisableAutomaticUUID(true); [self addGenericPassword: @"data" account: @"account-delete-me-no-UUID" expecting:errSecSuccess message: @"Add item (no UUID) to keychain"]; - SecCKKSTestSetDisableAutomaticUUID(false); - // We then expect an upload of the added item - [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; + [self findGenericPassword:@"account-delete-me-no-UUID" expecting:errSecSuccess]; OCMVerifyAllWithDelay(self.mockDatabase, 20); } @@ -228,7 +262,7 @@ // Stop the reencrypt operation from happening self.keychainView.holdReencryptOutgoingItemsOperation = [CKKSGroupOperation named:@"reencrypt-hold" withBlock: ^{ - secnotice("ckks", "releasing reencryption hold"); + ckksnotice_global("ckks", "releasing reencryption hold"); }]; // The cloudkit operation finishes, letting the next OQO proceed (and set up the reencryption operation) @@ -241,7 +275,7 @@ // Pause outgoing queue operations to ensure the reencryption operation runs first self.keychainView.holdOutgoingQueueOperation = [CKKSGroupOperation named:@"outgoing-hold" withBlock: ^{ - secnotice("ckks", "releasing outgoing-queue hold"); + ckksnotice_global("ckks", "releasing outgoing-queue hold"); }]; // Run the reencrypt items operation to completion. @@ -277,7 +311,7 @@ // Stop the reencrypt operation from happening self.keychainView.holdReencryptOutgoingItemsOperation = [CKKSGroupOperation named:@"reencrypt-hold" withBlock: ^{ - secnotice("ckks", "releasing reencryption hold"); + ckksnotice_global("ckks", "releasing reencryption hold"); }]; // The cloudkit operation finishes, letting the next OQO proceed (and set up the reencryption operation) @@ -337,7 +371,7 @@ [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. NSString* account = @"fake-account"; - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:@"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID]; @@ -350,7 +384,7 @@ [oqe saveToDatabase:&error]; XCTAssertNil(error, "Shouldn't error saving new OQE to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; NSError *error = NULL; @@ -416,6 +450,35 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testDeleteItemAndReaddAtSameUUID { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded. + __block CKRecordID* itemRecordID = nil; + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + itemRecordID = record.recordID; + return YES; + }]; + [self addGenericPassword:@"data" account:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // We expect a single record to be deleted. + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + [self deleteGenericPassword:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // And the item is readded. It should come back to its previous UUID. + XCTAssertNotNil(itemRecordID, "Should have an item record ID"); + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID checkItem:^BOOL(CKRecord * _Nonnull record) { + XCTAssertEqualObjects(itemRecordID.recordName, record.recordID.recordName, "Uploaded item UUID should match previous upload"); + return YES; + }]; + [self addGenericPassword:@"data" account:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + - (void)testDeleteItemImmediatelyAfterModify { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. NSString* account = @"account-delete-me"; @@ -447,6 +510,68 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testDeleteItemDuringAddUpload { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + NSString* account = @"account-delete-me"; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:10*NSEC_PER_SEC], @"key state should enter 'ready'"); + + // We expect a single record to be uploaded. But, while that's happening, delete it via the API. + + XCTestExpectation *deleteBlock = [self expectationWithDescription:@"delete block called"]; + + WEAKIFY(self); + self.keychainZone.blockBeforeWriteOperation = ^() { + STRONGIFY(self); + [self deleteGenericPassword:account]; + self.keychainZone.blockBeforeWriteOperation = nil; + [deleteBlock fulfill]; + }; + + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + + // This should cause a deletion + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + [self addGenericPassword:@"data" account:account]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self waitForExpectations: @[deleteBlock] timeout:5]; +} + +- (void)testDeleteItemDuringModificationUpload { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + NSString* account = @"account-delete-me"; + + [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:10*NSEC_PER_SEC], @"key state should enter 'ready'"); + + // We expect a single record to be uploaded. + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + [self addGenericPassword: @"data" account: account]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // We expect a single modification record to be uploaded, and want to delete the item while the upload is ongoing + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID + checkItem:[self checkPasswordBlock:self.keychainZoneID account:account password:@"otherdata"]]; + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + + XCTestExpectation *deleteBlock = [self expectationWithDescription:@"delete block called"]; + + WEAKIFY(self); + self.keychainZone.blockBeforeWriteOperation = ^() { + STRONGIFY(self); + [self deleteGenericPassword:account]; + self.keychainZone.blockBeforeWriteOperation = nil; + [deleteBlock fulfill]; + }; + + [self updateGenericPassword:@"otherdata" account:account]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self waitForExpectations: @[deleteBlock] timeout:5]; +} + - (void)testDeleteItemAfterFetchAfterModify { [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. NSString* account = @"account-delete-me"; @@ -470,24 +595,23 @@ // Right now, the write in CloudKit is pending. Place a hold on outgoing queue processing // Place a hold on processing the outgoing queue. - CKKSResultOperation* blockOutgoing = [CKKSResultOperation operationWithBlock:^{ - secnotice("ckks", "Outgoing queue hold released."); + self.keychainView.holdOutgoingQueueOperation = [CKKSResultOperation named:@"outgoing-queue-hold" + withBlock:^{ + ckksnotice_global("ckks", "Outgoing queue hold released."); }]; - blockOutgoing.name = @"outgoing-queue-hold"; - CKKSResultOperation* outgoingQueueOperation = [self.keychainView processOutgoingQueueAfter:blockOutgoing ckoperationGroup:nil]; [self deleteGenericPassword:account]; - [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; // Release the CK modification hold //[self releaseCloudKitModificationHold]; // And cause a fetch + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; - [self.operationQueue addOperation:blockOutgoing]; - [outgoingQueueOperation waitUntilFinished]; + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); } @@ -516,16 +640,16 @@ [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; // Ensure nothing is in the outgoing queue - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* uuids = [CKKSOutgoingQueueEntry allUUIDs:self.keychainZoneID error:&error]; XCTAssertNil(error, "should be no error fetching uuids"); XCTAssertEqual(uuids.count, 0u, "There should be zero OQEs"); - return false; }]; // And a simple fetch doesn't bring it back + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword:account expecting:errSecItemNotFound]; @@ -555,13 +679,15 @@ CFTypeRef item = NULL; XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should not yet exist"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); + CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; [self.keychainZone addToZone: ckr]; // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; + XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should exist now"); } @@ -591,9 +717,7 @@ } } - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; - + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword: @"account0" expecting:errSecSuccess]; @@ -634,13 +758,44 @@ [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil];; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should exist now"); [self waitForCKModifications]; XCTAssertNil(self.keychainZone.currentDatabase[ckr2.recordID], "Correct record was deleted from CloudKit"); + + // And the local item should have ckr's UUID + [self checkGenericPasswordStoredUUID:ckr.recordID.recordName account:@"account-delete-me"]; +} + +- (void)testReceiveCorruptedItem { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + [self startCKKSSubsystem]; + + [self findGenericPassword:@"account-delete-me" expecting:errSecItemNotFound]; + + CKRecord* ckr = [self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; + + // I don't know of any codepaths that cause this, but it apparently has happened. + ckr[SecCKRecordWrappedKeyKey] = nil; + [self.keychainZone addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // The item still shouldn't exist, because it was corrupted in flight + [self findGenericPassword:@"account-delete-me" expecting:errSecItemNotFound]; + + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ + NSError* error = nil; + NSArray* iqes = [CKKSIncomingQueueEntry all:&error]; + XCTAssertNil(error, "No error loading IQEs"); + XCTAssertNotNil(iqes, "Could load IQEs"); + XCTAssertEqual(iqes.count, 1u, "Incoming queue has one item"); + XCTAssertEqualObjects(iqes[0].state, SecCKKSStateNew, "Item state should be 'new'"); + }]; } -(void)testReceiveItemDelete { @@ -651,30 +806,143 @@ (id)kSecAttrAccessGroup : @"com.apple.security.ckks", (id)kSecAttrAccount : @"account-delete-me", (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecReturnAttributes : @YES, (id)kSecMatchLimit : (id)kSecMatchLimitOne, }; - CFTypeRef item = NULL; - XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should not yet exist"); + CFTypeRef cfitem = NULL; + XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &cfitem), "item should not yet exist"); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName: @"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; [self.keychainZone addToZone: ckr]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; - XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should exist now"); - CFReleaseNull(item); + XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &cfitem), "item should exist now"); + + NSDictionary* item = (NSDictionary*) CFBridgingRelease(cfitem); + cfitem = NULL; + NSDate* itemModificationDate = item[(id)kSecAttrModificationDate]; + XCTAssertNotNil(itemModificationDate, "Should have a modification date"); // Trigger a delete [self.keychainZone deleteCKRecordIDFromZone: [ckr recordID]]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; - XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should no longer exist"); + XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &cfitem), "item should no longer exist"); + CFReleaseNull(cfitem); + + // Now, double-check the tombstone. Its modification date should be derived from the item's mdat. + NSDictionary *tombquery = @{(id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : @"account-delete-me", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrTombstone : @YES, + (id)kSecReturnAttributes : @YES, + (id)kSecMatchLimit : (id)kSecMatchLimitOne,}; + + CFTypeRef cfref = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)tombquery, &cfref); + XCTAssertEqual(status, errSecSuccess, "Should have found a tombstone"); + + NSDictionary* tombstone = (NSDictionary*)CFBridgingRelease(cfref); + XCTAssertNotNil(tombstone, "Should have found a tombstone"); + + NSDate* tombstoneModificationDate = tombstone[(id)kSecAttrModificationDate]; + XCTAssertEqual([tombstoneModificationDate compare:itemModificationDate], NSOrderedDescending, "tombstone should be later than item"); + + NSTimeInterval tombestoneDelta = [tombstoneModificationDate timeIntervalSinceDate:itemModificationDate]; + XCTAssertGreaterThan(tombestoneDelta, 0, "Delta should be positive"); + XCTAssertLessThan(tombestoneDelta, 5, "tombstone mdat should be no later than 5s after item mdat"); + + // And just as a sanity, mdat is already far ago, right? + NSTimeInterval itemDelta = [[NSDate date] timeIntervalSinceDate:itemModificationDate]; + XCTAssertGreaterThan(itemDelta, 10, "item mdat should at least 10s in the past"); +} + +- (void)testReceiveTombstoneItem { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + [self startCKKSSubsystem]; + + NSString* account = @"account-delete-me"; + + CKRecord* ckr = [self createFakeTombstoneRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" account:account]; + [self.keychainZone addToZone:ckr]; + + // This device should delete the tombstone entry + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + // The tombstone shouldn't exist + NSDictionary *tombquery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : account, + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecReturnAttributes : @YES, + (id)kSecAttrTombstone : @YES, + }; + + CFTypeRef cftype = NULL; + XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef)tombquery, &cftype), "item should not exist now"); + XCTAssertNil((__bridge id)cftype, "Should have found no tombstones"); + + // And the delete should occur + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ + NSError* error = nil; + NSArray* uuids = [CKKSIncomingQueueEntry allUUIDs:self.keychainZoneID + error:&error]; + XCTAssertNil(error, "should be no error fetching uuids"); + XCTAssertEqual(uuids.count, 0u, "There should be zero IQEs"); + }]; +} + +- (void)testReceiveItemDeleteAndReaddAtDifferentUUIDInSameFetch { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + [self startCKKSSubsystem]; + + NSString* itemAccount = @"account-delete-me"; + [self findGenericPassword:itemAccount expecting:errSecItemNotFound]; + + NSString* uuidOriginalItem = @"7B598D31-F9C5-481E-98AC-5A507ACB2D85"; + NSString* uuidGreater = @"7B598D31-FFFF-FFFF-98AC-5A507ACB2D85"; + + CKRecord* ckr = [self createFakeRecord:self.keychainZoneID recordName:uuidOriginalItem]; + CKRecord* ckrGreater = [self createFakeRecord:self.keychainZoneID recordName:uuidGreater]; + + [self.keychainZone addToZone:ckr]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + [self checkGenericPasswordStoredUUID:uuidOriginalItem account:itemAccount]; + + // Now, the item is deleted and re-added with a greater UUID + [self.keychainZone deleteCKRecordIDFromZone:[ckr recordID]]; + [self.keychainZone addToZone:ckrGreater]; + + // This node should not upload anything. + [[self.mockDatabase reject] addOperation:[OCMArg any]]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; + + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + + // Item should still exist. + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + [self checkGenericPasswordStoredUUID:uuidGreater account:itemAccount]; } -(void)testReceiveItemPhantomDelete { @@ -691,13 +959,13 @@ CFTypeRef item = NULL; XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should not yet exist"); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName: @"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; [self.keychainZone addToZone: ckr]; - // Trigger a notification (with hilariously fake data) - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should exist now"); @@ -709,7 +977,7 @@ [self.keychainZone deleteCKRecordIDFromZone: [ckr recordID]]; // and add another, incorrect IQE - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ // Inefficient, but hey, it works CKRecord* record = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-FFFF-FFFF-5A507ACB2D85"]; CKKSItem* fakeItem = [[CKKSItem alloc] initWithCKRecord: record]; @@ -721,22 +989,21 @@ NSError* error = nil; XCTAssert([iqe saveToDatabase: &error], "Saved fake IQE to database"); XCTAssertNil(error, "No error saving fake IQE to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should no longer exist"); // The incoming queue should be empty - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* iqes = [CKKSIncomingQueueEntry all:&error]; XCTAssertNil(error, "No error loading IQEs"); XCTAssertNotNil(iqes, "Could load IQEs"); XCTAssertEqual(iqes.count, 0u, "Incoming queue is empty"); - return false; }]; } @@ -748,23 +1015,21 @@ [self.keychainView waitUntilAllOperationsAreFinished]; // Place a hold on processing the outgoing queue. - CKKSResultOperation* blockOutgoing = [CKKSResultOperation operationWithBlock:^{ - secnotice("ckks", "Outgoing queue hold released."); + self.keychainView.holdOutgoingQueueOperation = [CKKSResultOperation named:@"outgoing-queue-hold" + withBlock:^{ + ckksnotice_global("ckks", "Outgoing queue hold released."); }]; - blockOutgoing.name = @"outgoing-queue-hold"; - CKKSResultOperation* outgoingQueueOperation = [self.keychainView processOutgoingQueueAfter:blockOutgoing ckoperationGroup:nil]; - CKKSResultOperation* blockIncoming = [CKKSResultOperation operationWithBlock:^{ - secnotice("ckks", "Incoming queue hold released."); + self.keychainView.holdIncomingQueueOperation = [CKKSResultOperation named:@"incoming-queue-hold" + withBlock:^{ + ckksnotice_global("ckks", "Incoming queue hold released."); }]; - blockIncoming.name = @"incoming-queue-hold"; - CKKSResultOperation* incomingQueueOperation = [self.keychainView processIncomingQueue:false after: blockIncoming]; [self addGenericPassword:@"localchange" account:@"account-delete-me"]; // Pull out the new item's UUID. __block NSString* itemUUID = nil; - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* uuids = [CKKSOutgoingQueueEntry allUUIDs:self.keychainZoneID ?: [[CKRecordZoneID alloc] initWithZoneName:@"keychain" ownerName:CKCurrentUserDefaultName] @@ -774,21 +1039,20 @@ itemUUID = uuids[0]; XCTAssertNotNil(itemUUID, "Have a UUID for our new item"); - return false; }]; [self.keychainZone addToZone: [self createFakeRecord: self.keychainZoneID recordName: itemUUID]]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [[self.keychainView.zoneChangeFetcher requestSuccessfulFetch:CKKSFetchBecauseTesting] waitUntilFinished]; // Allow the outgoing queue operation to proceed - [self.operationQueue addOperation:blockOutgoing]; - [outgoingQueueOperation waitUntilFinished]; + [self.operationQueue addOperation:self.keychainView.holdOutgoingQueueOperation]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; // Allow the incoming queue operation to proceed - [self.operationQueue addOperation:blockIncoming]; - [incomingQueueOperation waitUntilFinished]; + [self.operationQueue addOperation:self.keychainView.holdIncomingQueueOperation]; + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; [self checkGenericPassword:@"data" account:@"account-delete-me"]; @@ -803,15 +1067,16 @@ [self.keychainView waitUntilAllOperationsAreFinished]; // Place a hold on processing the outgoing queue. + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; self.keychainView.holdOutgoingQueueOperation = [CKKSResultOperation named:@"outgoing-queue-hold" withBlock:^{ - secnotice("ckks", "Outgoing queue hold released."); + ckksnotice_global("ckks", "Outgoing queue hold released."); }]; [self addGenericPassword:@"localchange" account:@"account-delete-me"]; // Pull out the new item's UUID. __block NSString* itemUUID = nil; - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* uuids = [CKKSOutgoingQueueEntry allUUIDs:self.keychainZoneID ?: [[CKRecordZoneID alloc] initWithZoneName:@"keychain" ownerName:CKCurrentUserDefaultName] @@ -821,7 +1086,6 @@ itemUUID = uuids[0]; XCTAssertNotNil(itemUUID, "Have a UUID for our new item"); - return false; }]; // Add a second item: this item should be uploaded after the failure of the first item @@ -898,6 +1162,7 @@ ckr[@"server_new_server_field"] = future_server_field; [self.keychainZone addToZone:ckr]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword, @@ -967,6 +1232,7 @@ [self.keychainZone addToZone:[cipheritem CKRecordWithZoneID: recordID.zoneID]]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword, @@ -990,19 +1256,147 @@ XCTAssertEqualObjects(newRecord[SecCKRecordEncryptionVersionKey], [NSNumber numberWithInteger:(int) CKKSItemEncryptionVersion2], "Uploaded using encv2"); } +- (void)testLocalUpdateToTombstoneItem { + // Some CKKS clients may accidentally upload entries with tomb=1. + // We should delete these items with extreme predjudice. + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded. + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + [self addGenericPassword: @"data" account: @"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // We expect a single record to be deleted. + [self expectCKDeleteItemRecords: 1 zoneID:self.keychainZoneID]; + [self deleteGenericPassword:@"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // Now, SOS comes along and updates the tombstone + // CKKS should _not_ try to upload a tombstone + NSDictionary *tombquery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : @"account-delete-me", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + (id)kSecAttrTombstone : @YES, + }; + + NSDictionary* update = @{ + (id)kSecAttrModificationDate : [NSDate date], + }; + + __block CFErrorRef cferror = NULL; + kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { + bool ok = kc_transaction_type(dbt, kSecDbExclusiveRemoteSOSTransactionType, &cferror, ^bool { + OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)tombquery, (__bridge CFDictionaryRef)update); + XCTAssertEqual(status, errSecSuccess, "Should have been able to update a tombstone"); + + return true; + }); + return ok; + }); + + XCTAssertNil((__bridge NSError*)cferror, "Should be no error updating a tombstone"); + + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; +} + +- (void)testIgnoreUpdateToModificationDateItem { + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; + [self startCKKSSubsystem]; + + // We expect a single record to be uploaded. + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + [self addGenericPassword:@"data" account: @"account-delete-me"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // Nothing more should be uploaded + NSDictionary *query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : @"account-delete-me", + (id)kSecAttrSynchronizable : (id)kCFBooleanTrue, + }; + + NSDictionary* update = @{ + (id)kSecAttrModificationDate : [NSDate date], + }; + + __block CFErrorRef cferror = NULL; + kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { + bool ok = kc_transaction_type(dbt, kSecDbExclusiveRemoteSOSTransactionType, &cferror, ^bool { + OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update); + XCTAssertEqual(status, errSecSuccess, "Should have been able to update the item"); + + return true; + }); + return ok; + }); + + XCTAssertNil((__bridge NSError*)cferror, "Should be no error updating just the mdat"); + + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; +} + - (void)testUploadPagination { - [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; // Make life easy for this test. + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + [self saveTLKMaterialToKeychain:self.keychainZoneID]; + [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; for(size_t count = 0; count < 250; count++) { [self addGenericPassword: @"data" account: [NSString stringWithFormat:@"account-delete-me-%03lu", count]]; } - [self startCKKSSubsystem]; - [self expectCKModifyItemRecords: SecCKKSOutgoingQueueItemsAtOnce currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; [self expectCKModifyItemRecords: SecCKKSOutgoingQueueItemsAtOnce currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; [self expectCKModifyItemRecords: 50 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; + [self startCKKSSubsystem]; + + // For the next 5 seconds, try to add and then find an item. Each attempt should be fairly quick: no long multisecond pauses while CKKS Scans + NSTimeInterval elapsed = 0; + uint64_t count = 0; + while(elapsed < 10) { + NSDate* begin = [NSDate now]; + + NSString* account = [NSString stringWithFormat:@"non-syncable-%d", (int)count]; + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : account, + (id)kSecAttrSynchronizable : @NO, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecValueData : [@"asdf" dataUsingEncoding:NSUTF8StringEncoding], + }; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess, @"Should be able to add nonsyncable item"); + ckksnotice("ckkstest", self.keychainView, "SecItemAdd of %@ successful", account); + + NSDictionary *findQuery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : account, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecMatchLimit : (id)kSecMatchLimitOne, + }; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)findQuery, NULL), errSecSuccess, "Finding item %@", account); + ckksnotice("ckkstest", self.keychainView, "SecItemCopyMatching of %@ successful", account); + + NSDate* end = [NSDate now]; + NSTimeInterval delta = [end timeIntervalSinceDate:begin]; + + XCTAssertLessThan(delta, 2, @"Keychain API should respond in two seconds"); + ckksnotice("ckkstest", self.keychainView, "SecItemAdd/SecItemCopyMatching pair of %@ took %.4fs", account, delta); + + usleep(10000); // sleep for 10ms, to let some other things get done + + // And retake the time elasped for the overall count + elapsed += [[NSDate now] timeIntervalSinceDate:begin]; + count += 1; + } + OCMVerifyAllWithDelay(self.mockDatabase, 40); } @@ -1028,7 +1422,7 @@ for(CKKSKeychainView* view in self.ckksViews) { XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:40*NSEC_PER_SEC], @"key state should enter 'waitfortlkcreation' (view %@)", view); - [keysetOps addObject: [view findKeySet]]; + [keysetOps addObject: [view findKeySet:NO]]; } // Now that we've kicked them all off, wait for them to resolve (and nudge each one, as if a key was saved) @@ -1037,7 +1431,10 @@ CKKSCondition* viewProcess = view.keyHierarchyConditions[SecCKKSZoneKeyStateProcess]; [view keyStateMachineRequestProcess]; - XCTAssertNotEqual(0, [viewProcess wait:500*NSEC_PER_MSEC], "CKKS should not reprocess the key hierarchy, even if nudged"); + + // Since we do need to leave SecCKKSZoneKeyStateWaitForTLKUpload if a fetch occurs with new keys, make sure we do the right thing + XCTAssertEqual(0, [viewProcess wait:10*NSEC_PER_MSEC], "CKKS should reprocess the key hierarchy when nudged"); + XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKUpload] wait:40*NSEC_PER_SEC], @"key state should re-enter 'waitfortlkupload'"); } // The views should remain in waitfortlkcreation, and not go through process into an error @@ -1049,41 +1446,130 @@ [keysetOp waitUntilFinished]; XCTAssertNil(keysetOp.error, "Should be no error fetching keyset from CKKS"); - NSArray* records = [self putKeySetInCloudKit:keysetOp.keyset]; - [keyHierarchyRecords addObjectsFromArray:records]; - } + NSArray* records = [self putKeySetInCloudKit:keysetOp.keyset]; + [keyHierarchyRecords addObjectsFromArray:records]; + } + + // Tell our views about our shiny new records! + for(CKKSKeychainView* view in self.ckksViews) { + [view receiveTLKUploadRecords: keyHierarchyRecords]; + } + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); +} + + +- (void)testReceiveChangedKeySetFromWaitingForTLKUpload { + // Test starts with nothing in database. CKKS should get into the "please upload my keys" state + + [self startCKKSSubsystem]; + + // After each zone arrives in WaitForTLKCreation, new keys are uploaded + for(CKKSKeychainView* view in self.ckksViews) { + XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:40*NSEC_PER_SEC], @"key state should enter 'waitfortlkcreation' (view %@)", view); + } + + for(CKKSKeychainView* view in self.ckksViews) { + [self putFakeKeyHierarchyInCloudKit:view.zoneID]; + [self putFakeDeviceStatusInCloudKit:view.zoneID]; + } + + // If we ask the zones for their keysets, they should return the local set ready for upload + NSMutableArray*>* keysetOps = [NSMutableArray array]; + + for(CKKSKeychainView* view in self.ckksViews) { + [keysetOps addObject:[view findKeySet:NO]]; + } + + for(CKKSResultOperation* keysetOp in keysetOps) { + [keysetOp waitUntilFinished]; + XCTAssertNil(keysetOp.error, "Should be no error fetching keyset from CKKS"); + + CKRecordZoneID* zoneID = [[CKRecordZoneID alloc] initWithZoneName:keysetOp.zoneName + ownerName:CKCurrentUserDefaultName]; + ZoneKeys* zk = self.keys[zoneID]; + XCTAssertNotNil(zk, "Should have new zone keys for zone %@", keysetOp.zoneName); + XCTAssertNotEqualObjects(keysetOp.keyset.currentTLKPointer.currentKeyUUID, zk.tlk.uuid, "Fetched TLK and CK TLK should be different"); + } + + // Now, find the keysets again, asking for a fetch this time + NSMutableArray*>* fetchedKeysetOps = [NSMutableArray array]; + + for(CKKSKeychainView* view in self.ckksViews) { + [fetchedKeysetOps addObject:[view findKeySet:YES]]; + } + + for(CKKSResultOperation* keysetOp in fetchedKeysetOps) { + [keysetOp waitUntilFinished]; + XCTAssertNil(keysetOp.error, "Should be no error fetching keyset from CKKS"); + + CKRecordZoneID* zoneID = [[CKRecordZoneID alloc] initWithZoneName:keysetOp.zoneName + ownerName:CKCurrentUserDefaultName]; + ZoneKeys* zk = self.keys[zoneID]; + XCTAssertNotNil(zk, "Should have new zone keys for zone %@", keysetOp.zoneName); + XCTAssertEqualObjects(keysetOp.keyset.currentTLKPointer.currentKeyUUID, zk.tlk.uuid, "Fetched TLK and CK TLK should now match"); + } +} + +- (void)testProvideKeysetFromNoTrust { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortrust'"); + + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; + [keysetOp timeout:20*NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; + + XCTAssertNil(keysetOp.error, "Should be no error fetching a keyset"); +} + +- (void)testProvideKeysetFromNoTrustWithRefetch { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortrust'"); + + self.silentFetchesAllowed = false; + [self expectCKFetch]; + + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:YES]; + [keysetOp timeout:20*NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; - // Tell our views about our shiny new records! - for(CKKSKeychainView* view in self.ckksViews) { - [view receiveTLKUploadRecords: keyHierarchyRecords]; - } - OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertNil(keysetOp.error, "Should be no error fetching a keyset"); - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); } -- (void)testProvideKeysetFromNoTrust { +- (void)testProvideKeysetAfterReceivingTLKInNoTrust { + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; [self startCKKSSubsystem]; - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortlkcreation'"); - // I'm not sure how CKKS ends up in 'waitfortrust' without a keyset, so force that state - // In 52301278, it occurred with some complex interaction of zone deletions, fetches, and trust operations - [self.keychainView dispatchSyncWithAccountKeys:^bool{ - [self.keychainView _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForTrust withError:nil]; - return true; - }]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortrust'"); - CKKSResultOperation* keysetOp = [self.keychainView findKeySet]; + // This isn't necessarily SOS, but perhaps SBD. + [self saveTLKMaterialToKeychainSimulatingSOS:self.keychainZoneID]; + + // Still ends up in waitfortrust... + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortrust'"); + + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; [keysetOp timeout:20*NSEC_PER_SEC]; [keysetOp waitUntilFinished]; XCTAssertNil(keysetOp.error, "Should be no error fetching a keyset"); + XCTAssertNotNil(keysetOp.keyset, "Should have a keyset"); + XCTAssertNotNil(keysetOp.keyset.tlk, "Should have a TLK"); } -// This test no longer is very interesting, since Octagon needs to handle lock states, not CKKS... - (void)testUploadInitialKeyHierarchyAfterLockedStart { // 'Lock' the keybag self.aksLockState = true; @@ -1091,14 +1577,27 @@ [self startCKKSSubsystem]; - // Wait for the key hierarchy state machine to get stuck waiting for the unlock dependency. No uploads should occur. XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], @"Key state should get stuck in waitfortlkcreation"); + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; + + // Wait for the key hierarchy state machine to get stuck waiting for the unlock dependency. No uploads should occur. + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForUnlock] wait:20*NSEC_PER_SEC], @"Key state should get stuck in waitforunlock"); + // After unlock, the key hierarchy should be created. self.aksLockState = false; [self.lockStateTracker recheck]; - [self performOctagonTLKUpload:self.ckksViews]; + [keysetOp timeout:10 * NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; + XCTAssertNil(keysetOp.error, @"Should be no error performing keyset op"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKUpload] wait:20*NSEC_PER_SEC], @"Key state should enter 'waitfortlkupload'"); + + NSArray* keyHierarchyRecords = [self putKeySetInCloudKit:keysetOp.keyset]; + [self.keychainView receiveTLKUploadRecords:keyHierarchyRecords]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should enter 'ready'"); // We expect a single class C record to be uploaded. [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; @@ -1107,6 +1606,55 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); } +- (void)testExitWaitForTLKUploadIfTLKsCreated { + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], @"Key state should get stuck in waitfortlkcreation"); + + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; + + [keysetOp timeout:10 * NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; + XCTAssertNil(keysetOp.error, @"Should be no error performing keyset op"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKUpload] wait:20*NSEC_PER_SEC], @"Key state should enter 'waitfortlkupload'"); + + // But another device beats us to it! + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLK] wait:20*NSEC_PER_SEC], @"Key state should enter 'waitfortlk'"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + +- (void)testExitWaitForTLKUploadIfTLKsCreatedWhileNoTrust { + self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; + [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], @"Key state should get stuck in waitfortlkcreation"); + + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; + + [keysetOp timeout:10 * NSEC_PER_SEC]; + [keysetOp waitUntilFinished]; + XCTAssertNil(keysetOp.error, @"Should be no error performing keyset op"); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKUpload] wait:20*NSEC_PER_SEC], @"Key state should enter 'waitfortlkupload'"); + + // But another device beats us to it! + [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; + [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should enter 'waitfortrust'"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); +} + - (void)testLockImmediatelyAfterUploadingInitialKeyHierarchy { __weak __typeof(self) weakSelf = self; @@ -1158,7 +1706,7 @@ // Now, another device comes along and creates the hierarchy; we download it; and it and sends us the TLK [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [[self.keychainView.zoneChangeFetcher requestSuccessfulFetch:CKKSFetchBecauseTesting] waitUntilFinished]; self.aksLockState = false; @@ -1173,6 +1721,7 @@ [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; [self addGenericPassword: @"data" account: @"account-delete-me"]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should become 'ready'"); OCMVerifyAllWithDelay(self.mockDatabase, 20); } @@ -1377,7 +1926,7 @@ [self putFakeDeviceStatusInCloudKit:self.keychainZoneID]; // Also, CKKS _should_ be able to return the key hierarchy if asked before it starts - CKKSResultOperation* keysetOp = [self.keychainView findKeySet]; + CKKSResultOperation* keysetOp = [self.keychainView findKeySet:NO]; NSDateComponents* offset = [[NSDateComponents alloc] init]; [offset setDay:-5]; @@ -1481,7 +2030,7 @@ // Verify that there are three local keys, and three local current key records __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -1494,8 +2043,6 @@ NSArray* currentkeys = [CKKSCurrentKeyPointer all: &error]; XCTAssertNil(error, "no error fetching current keys"); XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database"); - - return false; }]; } @@ -1560,7 +2107,7 @@ // Verify that there are three local keys, and three local current key records __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -1573,8 +2120,6 @@ NSArray* currentkeys = [CKKSCurrentKeyPointer all: &error]; XCTAssertNil(error, "no error fetching current keys"); XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database"); - - return false; }]; } @@ -1585,6 +2130,8 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should become 'ready'"); + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword:@"classCItem" expecting:errSecItemNotFound]; @@ -1598,10 +2145,8 @@ XCTAssertNotNil(self.keychainZoneKeys.classA, "Have class A key for zone"); XCTAssertNotNil(self.keychainZoneKeys.classC, "Have class C key for zone"); - [self.keychainView dispatchSyncWithAccountKeys: ^bool { - [self.keychainView _onqueueKeyStateMachineRequestProcess]; - return true; - }]; + [self.keychainView.stateMachine handleFlag:CKKSFlagKeyStateProcessRequested]; + // And ensure we end up back in 'readypendingunlock': we have the keys, we're just locked now [self.keychainView waitForOperationsOfClass:[CKKSProcessReceivedKeysOperation class]]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReadyPendingUnlock] wait:20*NSEC_PER_SEC], @"Key state should become 'readypendingunlock'"); @@ -1609,7 +2154,9 @@ [self.keychainZone addToZone: [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" withAccount:@"classCItem" key:self.keychainZoneKeys.classC]]; [self.keychainZone addToZone: [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-FFFF-FFFF-FFFF-5A507ACB2D85" withAccount:@"classAItem" key:self.keychainZoneKeys.classA]]; - CKKSResultOperation* op = [self.keychainView waitForFetchAndIncomingQueueProcessing]; + CKKSResultOperation* op = self.keychainView.resultsOfNextProcessIncomingQueueOperation; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; + [self.keychainView waitForFetchAndIncomingQueueProcessing]; // The processing op should NOT error, even though it didn't manage to process the classA item XCTAssertNil(op.error, "no error while failing to process a class A item"); @@ -1677,22 +2224,21 @@ [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; [self saveTLKMaterialToKeychain:self.keychainZoneID]; - // Trigger a notification - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; // Make life easy on this test; testAcceptKeyConflictAndUploadReencryptedItem will check the case when we don't receive the notification [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Just in extra case of threading issues, force a reexamination of the key hierarchy - [self.keychainView dispatchSyncWithAccountKeys: ^bool { - [self.keychainView _onqueueAdvanceKeyStateMachineToState: nil withError: nil]; - return true; + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + [self.keychainView _onqueuePokeKeyStateMachine]; + return CKKSDatabaseTransactionCommit; }]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should become 'ready'"); // Verify that there are six local keys, and three local current key records - [self.keychainView dispatchSync: ^bool{ + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -1716,14 +2262,13 @@ XCTFail("Unknown key class: %@", key.keyclass); } } - - return false; }]; // We expect a single record to be uploaded. [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; // TODO: remove this by writing code for item reencrypt after key arrival + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self addGenericPassword: @"data" account: @"account-delete-me-rolled-key"]; @@ -1740,6 +2285,8 @@ [self startCKKSSubsystem]; [self.keychainView waitUntilAllOperationsAreFinished]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); + // We expect a single record to be uploaded. [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; @@ -1747,6 +2294,7 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); [self waitForCKModifications]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); [self rollFakeKeyHierarchyInCloudKit:self.keychainZoneID]; @@ -1874,15 +2422,13 @@ [self waitForCKModifications]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); // CKKS should not roll the keys while progressing back to 'ready', but it will fetch once self.silentFetchesAllowed = false; [self expectCKFetch]; - [self.keychainView dispatchSyncWithAccountKeys: ^bool { - [self.keychainView _onqueueKeyStateMachineRequestFetch]; - return true; - }]; + [self.keychainView.stateMachine handleFlag:CKKSFlagFetchRequested]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should have returned to ready"); OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -1896,6 +2442,7 @@ // Spin up CKKS subsystem. [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); [self.keychainView waitForFetchAndIncomingQueueProcessing]; // just to be sure it's fetched // Items should upload. @@ -1928,6 +2475,7 @@ // Spin up CKKS subsystem. [self startCKKSSubsystem]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'"); [self.keychainView waitForFetchAndIncomingQueueProcessing]; // just to be sure it's fetched // Items should upload. @@ -1946,8 +2494,9 @@ XCTAssertNotEqualObjects(currentClassC.etag, self.keychainZone.currentDatabase[currentClassCID].etag, "Etag should have changed"); // Add another item. This write should fail, then CKKS should recover without rolling the key hierarchy or issuing a fetch. + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; self.keychainView.holdOutgoingQueueOperation = [CKKSGroupOperation named:@"outgoing-hold" withBlock: ^{ - secnotice("ckks", "releasing outgoing-queue hold"); + ckksnotice_global("ckks", "releasing outgoing-queue hold"); }]; self.silentFetchesAllowed = false; @@ -2046,6 +2595,28 @@ XCTAssertTrue(self.keychainZone.flag, "Keychain zone shouldn't have been reset"); } +- (void)testOnboardOldItemMatchingExistingCKKSItem { + [self createAndSaveFakeKeyHierarchy: self.keychainZoneID]; + + NSString* itemAccount = @"account-delete-me"; + [self addGenericPassword:@"password" account:itemAccount]; + + CKRecord* ckr = [self createFakeRecord:self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; + [self.keychainZone addToZone:ckr]; + + [self startCKKSSubsystem]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should have become ready"); + + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; + + [self findGenericPassword:itemAccount expecting:errSecSuccess]; + + // And, the local item should now match the UUID downloaded from CKKS + [self checkGenericPasswordStoredUUID:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" account:itemAccount]; +} + - (void)testResync { // We need to set up a desynced situation to test our resync. // First, let CKKS start up and send several items to CloudKit (that we'll then desync!) @@ -2061,13 +2632,15 @@ [self addGenericPassword: @"data" account: @"third"]; [self addGenericPassword: @"data" account: @"fourth"]; [self addGenericPassword: @"data" account: @"fifth"]; - NSUInteger passwordCount = 5u; + [self addGenericPassword: @"data" account: @"sixth"]; + NSUInteger passwordCount = 6u; [self checkGenericPassword: @"data" account: @"first"]; [self checkGenericPassword: @"data" account: @"second"]; [self checkGenericPassword: @"data" account: @"third"]; [self checkGenericPassword: @"data" account: @"fourth"]; [self checkGenericPassword: @"data" account: @"fifth"]; + [self checkGenericPassword: @"data" account: @"sixth"]; [self expectCKModifyItemRecords: passwordCount currentKeyPointerRecords: 1 zoneID:self.keychainZoneID]; @@ -2091,7 +2664,7 @@ XCTAssertNotNil(deleteAccount, "received an account for the local delete object"); __weak __typeof(self) weakSelf = self; - [self.keychainView dispatchSync:^bool{ + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -2110,7 +2683,7 @@ [iqe deleteFromDatabase: &error]; } XCTAssertNil(error, "no error removing IQE"); - return true; + return CKKSDatabaseTransactionCommit; }]; // For the second record, delete all traces of it from CloudKit. @@ -2153,6 +2726,16 @@ [self checkGenericPassword:@"newpassword" account:localDataChangedAccount]; SecCKKSEnable(); + // The sixth record matches what's in CloudKit, but the local UUID has changed (and CKKS didn't notice, for whatever reason) + CKRecord* uuidMismatch = items[5]; + NSMutableDictionary* uuidMisMatchDictionary = [[self decryptRecord:uuidMismatch] mutableCopy]; + NSString* uuidMismatchAccount = uuidMisMatchDictionary[(__bridge id)kSecAttrAccount]; + NSString* newUUID = @"55463F83-3AAE-462D-B95F-2FA6AD088980"; + SecCKKSDisable(); + [self setGenericPasswordStoredUUID:newUUID account:uuidMismatchAccount]; + [self checkGenericPasswordStoredUUID:newUUID account:uuidMismatchAccount]; + SecCKKSEnable(); + // To make this more challenging, CK returns the refetch in multiple batches. This shouldn't affect the resync... CKServerChangeToken* ck1 = self.keychainZone.currentChangeToken; self.silentFetchesAllowed = false; @@ -2170,7 +2753,7 @@ self.keychainZone.limitFetchTo = ck1; self.keychainZone.limitFetchError = [[CKPrettyError alloc] initWithDomain:CKErrorDomain code:CKErrorNetworkFailure userInfo:@{CKErrorRetryAfterKey : [NSNumber numberWithInt:4]}]; - // The sixth record gets magically added to CloudKit, but CKKS has never heard of it + // The seventh record gets magically added to CloudKit, but CKKS has never heard of it // (emulates a lost record on the client, but that CloudKit already believes it's sent the record for) // Expected outcome: added to local keychain NSString* remoteOnlyAccount = @"remote-only"; @@ -2185,6 +2768,7 @@ ckksnotice("ckksresync", self.keychainView, "Remote data changed: %@ %@", remoteDataChanged.recordID.recordName, remoteDataChangedAccount); ckksnotice("ckksresync", self.keychainView, "in-sync: %@ %@", items[3].recordID.recordName, insyncAccount); ckksnotice("ckksresync", self.keychainView, "local update: %@ %@", items[4].recordID.recordName, localDataChangedAccount); + ckksnotice("ckksresync", self.keychainView, "uuid mismatch: %@ %@", items[5].recordID.recordName, uuidMismatchAccount); ckksnotice("ckksresync", self.keychainView, "Remote only: %@ %@", ckr.recordID.recordName, remoteOnlyAccount); CKKSSynchronizeOperation* resyncOperation = [self.keychainView resyncWithCloud]; @@ -2201,6 +2785,7 @@ [self findGenericPassword: remoteDataChangedAccount expecting: errSecSuccess]; [self findGenericPassword: insyncAccount expecting: errSecSuccess]; [self findGenericPassword: localDataChangedAccount expecting: errSecSuccess]; + [self findGenericPassword: uuidMismatchAccount expecting: errSecSuccess]; [self findGenericPassword: remoteOnlyAccount expecting: errSecSuccess]; [self checkGenericPassword: @"data" account: deleteAccount]; @@ -2208,9 +2793,12 @@ [self checkGenericPassword: @"CloudKitWins" account: remoteDataChangedAccount]; [self checkGenericPassword: @"data" account: insyncAccount]; [self checkGenericPassword:@"data" account:localDataChangedAccount]; + [self checkGenericPassword:@"data" account:uuidMismatchAccount]; [self checkGenericPassword: @"data" account: remoteOnlyAccount]; - [self.keychainView dispatchSync:^bool{ + [self checkGenericPasswordStoredUUID:uuidMismatch.recordID.recordName account:uuidMismatchAccount]; + + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ __strong __typeof(weakSelf) strongSelf = weakSelf; XCTAssertNotNil(strongSelf, "self exists"); @@ -2239,7 +2827,6 @@ ckme = [CKKSMirrorEntry tryFromDatabase:ckr.recordID.recordName zoneID:strongSelf.keychainZoneID error:&error]; XCTAssertNil(error); XCTAssertNotNil(ckme); - return true; }]; } @@ -2263,6 +2850,8 @@ [self startCKKSSubsystem]; OCMVerifyAllWithDelay(self.mockDatabase, 20); [self waitForCKModifications]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Now, place an item in the outgoing queue @@ -2306,19 +2895,23 @@ CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" withAccount:@"fourth"]; [self.keychainZone addToZone:ckr]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; // Now, where are we.... CKKSScanLocalItemsOperation* scanLocal = [self.keychainView scanLocalItems:@"test-scan"]; - [scanLocal waitUntilFinished]; - - XCTAssertEqual(scanLocal.missingLocalItemsFound, 1u, "Should have found one missing item"); + // This operation will wait for the CKKSOutgoingQueue operation (currently held writing to cloudkit) to finish before beginning // Allow everything to proceed [self releaseCloudKitModificationHold]; + + [scanLocal waitUntilFinished]; + XCTAssertEqual(scanLocal.missingLocalItemsFound, 1u, "Should have found one missing item"); + [self.operationQueue addOperation:self.keychainView.holdIncomingQueueOperation]; OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; // And ensure that all four items are present again @@ -2343,6 +2936,8 @@ [self startCKKSSubsystem]; OCMVerifyAllWithDelay(self.mockDatabase, 20); [self waitForCKModifications]; + + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; @@ -2370,6 +2965,47 @@ [self findGenericPassword: @"second" expecting: errSecSuccess]; } +- (void)testEnsureScanOccursOnNextStartIfCancelled { + // We want to set up a situation where a CKKSScanLocalItemsOperation is cancelled by daemon quitting. + NSString* itemAccount = @"first"; + [self addGenericPassword:@"data" account:itemAccount]; + [self addGenericPassword:@"data" account:@"second"]; + + // We're going to pretend that the scan doesn't happen due to daemon restart + SecCKKSSetTestSkipScan(true); + + [self createAndSaveFakeKeyHierarchy:self.keychainZoneID]; // Make life easy for this test. + + [self startCKKSSubsystem]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + // CKKS should perform normally if new items are added + [self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + [self addGenericPassword:@"found" account:@"after-setup"]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + // Now, simulate a restart + SecCKKSSetTestSkipScan(false); + + [self expectCKModifyItemRecords:2 currentKeyPointerRecords:1 zoneID:self.keychainZoneID]; + + [self.keychainView halt]; + self.keychainView = [[CKKSViewManager manager] restartZone:self.keychainZoneID.zoneName]; + [self.keychainView beginCloudKitOperation]; + [self beginSOSTrustedViewOperation:self.keychainView]; + + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self findGenericPassword:@"first" expecting:errSecSuccess]; + [self findGenericPassword:@"second" expecting:errSecSuccess]; +} + - (void)testResyncLocal { [self putFakeKeyHierarchyInCloudKit:self.keychainZoneID]; [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; @@ -2469,6 +3105,9 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + // Tear down the CKKS object and disallow fetches [self.keychainView halt]; self.silentFetchesAllowed = false; @@ -2478,11 +3117,13 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertFalse(self.keychainView.initiatedLocalScan, "Should not have initiated a local items scan due to a restart with a recent fetch"); + // Okay, cool, rad, now let's set the date to be very long ago and check that there's positively a fetch [self.keychainView halt]; self.silentFetchesAllowed = false; - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; @@ -2492,7 +3133,7 @@ ckse.lastFetchTime = [NSDate distantPast]; [ckse saveToDatabase: &error]; XCTAssertNil(error, "no error saving to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; [self expectCKFetch]; @@ -2500,6 +3141,108 @@ [self beginSOSTrustedViewOperation:self.keychainView]; [self.keychainView waitForKeyHierarchyReadiness]; OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertFalse(self.keychainView.initiatedLocalScan, "Should not have initiated a local items scan due to a restart (when we haven't fetched in a while, but did scan recently)"); + + // Now restart again, but cause a scan to occur + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; + XCTAssertNil(error, "no error pulling ckse from database"); + XCTAssertNotNil(ckse, "received a ckse"); + + ckse.lastLocalKeychainScanTime = [NSDate distantPast]; + [ckse saveToDatabase:&error]; + XCTAssertNil(error, "no error saving to database"); + return CKKSDatabaseTransactionCommit; + }]; + + [self.keychainView halt]; + self.keychainView = [[CKKSViewManager manager] restartZone: self.keychainZoneID.zoneName]; + [self beginSOSTrustedViewOperation:self.keychainView]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + XCTAssertTrue(self.keychainView.initiatedLocalScan, "Should have initiated a local items scan due to 24-hr notification"); +} + +- (void)testFetchAndScanOn24HrNotification { + // Every 24 hrs, CKKS should fetch if there hasn't been a fetch in a while. + [self startCKKSSubsystem]; + [self performOctagonTLKUpload:self.ckksViews]; + + [self waitForCKModifications]; + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + // We now get the 24-hr notification. Set this bit for later checking + XCTAssertTrue(self.keychainView.initiatedLocalScan, "Should have initiated a local items scan during bringup"); + self.keychainView.initiatedLocalScan = NO; + + self.silentFetchesAllowed = false; + + [self.keychainView xpc24HrNotification]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + XCTAssertFalse(self.keychainView.initiatedLocalScan, "Should not have initiated a local items scan due to a 24-hr notification with a recent fetch"); + + // Okay, cool, rad, now let's set the last local-keychain-scan date to be very long ago and retry + // This shouldn't fetch, but it should scan the local keychain + self.silentFetchesAllowed = false; + + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; + XCTAssertNil(error, "no error pulling ckse from database"); + XCTAssertNotNil(ckse, "received a ckse"); + + ckse.lastLocalKeychainScanTime = [NSDate distantPast]; + [ckse saveToDatabase:&error]; + XCTAssertNil(error, "no error saving to database"); + return CKKSDatabaseTransactionCommit; + }]; + + [self.keychainView xpc24HrNotification]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + XCTAssertTrue(self.keychainView.initiatedLocalScan, "Should have initiated a local items scan due to 24-hr notification"); + self.keychainView.initiatedLocalScan = false; + + // And check that the fetch occurs as well + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + NSError* error = nil; + CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; + XCTAssertNil(error, "no error pulling ckse from database"); + XCTAssertNotNil(ckse, "received a ckse"); + + ckse.lastFetchTime = [NSDate distantPast]; + [ckse saveToDatabase:&error]; + XCTAssertNil(error, "no error saving to database"); + return CKKSDatabaseTransactionCommit; + }]; + + [self expectCKFetch]; + [self.keychainView xpc24HrNotification]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should arrive at ready"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + + XCTAssertFalse(self.keychainView.initiatedLocalScan, "Should not have initiated a local items scan due to 24-hr notification (if we've done one recently)"); } - (void)testRecoverFromZoneCreationFailure { @@ -2830,6 +3573,7 @@ [self waitForCKModifications]; [self.keychainView waitUntilAllOperationsAreFinished]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" withAccount:@"account0"]; @@ -2844,10 +3588,8 @@ }), @"Deleting local keys"); SecCKKSTestSetDisableKeyNotifications(false); - // Trigger a notification (with hilariously fake data) [self.keychainZone addToZone: ckr]; - [self.keychainView notifyZoneChange:nil]; - [self.keychainView waitForFetchAndIncomingQueueProcessing]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword: @"account0" expecting:errSecSuccess]; @@ -2879,12 +3621,13 @@ // Trigger a notification (with hilariously fake data) [self.keychainZone addToZone: ckr]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should return to 'ready'"); + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Do this again, to allow for non-atomic key state machinery switching [self findGenericPassword: @"account0" expecting:errSecSuccess]; @@ -2922,6 +3665,7 @@ XCTAssertNil(error, "Should be no error deleting old key material from keychain"); [self.keychainZone addToZone:ckrAddedLater]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword:accountShouldExist expecting:errSecSuccess]; @@ -2967,6 +3711,7 @@ [self.lockStateTracker recheck]; [self.keychainZone addToZone:ckrAddedLater]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Item should still not exist due to the lock state.... @@ -3077,7 +3822,7 @@ [self waitForCKModifications]; // Now, delete most of the key records are from on-disk, but the change token is not changed - [self.keychainView dispatchSync:^bool{ + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.keychainZoneID]; XCTAssertNotNil(keyset.currentTLKPointer, @"should be a TLK pointer"); @@ -3102,7 +3847,7 @@ [keyset.classC deleteFromDatabase:&error]; XCTAssertNil(error, "Should be no error deleting classC from database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // A restart should realize there's an issue, and pause for help @@ -3161,7 +3906,6 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered ready"); - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateReady, "CKKS entered ready"); // Network is unavailable [self.reachabilityTracker setNetworkReachability:false]; @@ -3174,6 +3918,7 @@ // Say network is available [self.reachabilityTracker setNetworkReachability:true]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword:@"account-delete-me" expecting:errSecSuccess]; @@ -3193,7 +3938,6 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateInitializing] wait:20*NSEC_PER_SEC], "CKKS entered initializing"); - XCTAssertEqualObjects(self.keychainView.keyHierarchyState, SecCKKSZoneKeyStateInitializing, "CKKS entered initializing"); // Now, save the TLK to the keychain (to simulate it coming in later via SOS). [self expectCKKSTLKSelfShareUpload:self.keychainZoneID]; @@ -3217,6 +3961,8 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:8*NSEC_PER_SEC], "CKKS entered ready"); + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + // Network is now unavailable [self.reachabilityTracker setNetworkReachability:false]; @@ -3308,7 +4054,7 @@ [self expectCKFetch]; // and one to succeed // Trigger a fake change notification - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -3330,7 +4076,7 @@ [self saveTLKMaterialToKeychainSimulatingSOS:self.keychainZoneID]; // Save a new device state record with some fake etag - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ CKKSDeviceStateEntry* cdse = [[CKKSDeviceStateEntry alloc] initForDevice:self.ckDeviceID osVersion:@"fake-record" lastUnlockTime:[NSDate date] @@ -3354,7 +4100,7 @@ [cdse saveToDatabase:&error]; XCTAssertNil(error, @"No error saving cdse to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // Spin up CKKS subsystem. @@ -3382,7 +4128,7 @@ CKRecord* ckr = [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85"]; [self.keychainZone addToZone:ckr]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword:@"account-delete-me" expecting:errSecSuccess]; @@ -3425,7 +4171,7 @@ // We expect CKKS to recreate the zone, then have octagon reupload the keys, and then the class C item upload [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self performOctagonTLKUpload:self.ckksViews]; @@ -3472,7 +4218,7 @@ // We expect CKKS to reset itself and recover, then have octagon upload the keys, and then the class C item upload [self expectCKModifyItemRecords: 1 currentKeyPointerRecords: 1 zoneID:self.keychainZoneID checkItem: [self checkClassCBlock:self.keychainZoneID message:@"Object was encrypted under class C key in hierarchy"]]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self performOctagonTLKUpload:self.ckksViews]; OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -3526,7 +4272,6 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); [self addGenericPassword: @"data" account: @"account-delete-me"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; // simulate a NSNotification callback (but still logged out) self.accountStatus = CKAccountStatusNoAccount; @@ -3536,7 +4281,6 @@ [self addGenericPassword: @"data" account: @"account-delete-me-2"]; [self addGenericPassword: @"data" account: @"account-delete-me-3"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // Test that there are no items in the database (since we never logged in) @@ -3558,11 +4302,10 @@ [self.accountStateTracker notifyCKAccountStatusChangeAndWaitForSignal]; OCMVerifyAllWithDelay(self.mockDatabase, 20); - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS should enter 'loggedout'"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForCloudKitAccountStatus] wait:20*NSEC_PER_SEC], "CKKS should enter 'waitforcloudkitaccount'"); // There should be no uploads, even when we save keychain items and enter/exit circle [self addGenericPassword: @"data" account: @"account-delete-me"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; @@ -3574,7 +4317,6 @@ [self beginSOSTrustedViewOperation:self.keychainView]; [self addGenericPassword: @"data" account: @"account-delete-me-3"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // Test that there are no items in the database (since we never were in an HSA2 account) @@ -3617,7 +4359,6 @@ OCMVerifyAllWithDelay(self.mockDatabase, 20); [self addGenericPassword: @"data" account: @"account-delete-me"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], "CKKS entered 'waitfortlkcreation'"); @@ -3631,7 +4372,6 @@ [self addGenericPassword: @"data" account: @"account-delete-me-2"]; [self addGenericPassword: @"data" account: @"account-delete-me-3"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // Test that there are no items in the database (since we never logged in) @@ -3644,6 +4384,7 @@ [self startCKKSSubsystem]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should have arrived at ready"); + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; // But then, trust departs self.mockSOSAdapter.circleStatus = kSOSCCNotInCircle; @@ -3689,7 +4430,6 @@ // No writes yet, since we're not in circle XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:20*NSEC_PER_SEC], "CKKS entered 'waitfortlkcreation'"); - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; self.mockSOSAdapter.circleStatus = kSOSCCInCircle; [self.accountStateTracker notifyCircleStatusChangeAndWaitForSignal]; @@ -3830,7 +4570,14 @@ [self checkNoCKKSData: self.keychainView]; // Force zone into error state - self.keychainView.keyHierarchyState = SecCKKSZoneKeyStateError; + OctagonStateTransitionOperation* transitionOp = [OctagonStateTransitionOperation named:@"enter" entering:SecCKKSZoneKeyStateError]; + OctagonStateTransitionRequest* request = [[OctagonStateTransitionRequest alloc] init:@"enter-wait-for-trust" + sourceStates:[NSSet setWithArray:[CKKSZoneKeyStateMap() allKeys]] + serialQueue:self.keychainView.queue + timeout:10 * NSEC_PER_SEC + transitionOp:transitionOp]; + [self.keychainView.stateMachine handleExternalRequest:request]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateError] wait:20*NSEC_PER_SEC], "CKKS entered 'error'"); self.accountStatus = CKAccountStatusAvailable; [self.accountStateTracker notifyCKAccountStatusChangeAndWaitForSignal]; @@ -3847,6 +4594,8 @@ [op addDependency:self.keychainView.keyStateReadyDependency]; [self.operationQueue addOperation:op]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); + XCTAssertEqual(0, [self.keychainView.loggedIn wait:2000*NSEC_PER_MSEC], "Should have been told of a 'login'"); XCTAssertNotEqual(0, [self.keychainView.loggedOut wait:100*NSEC_PER_MSEC], "'logout' event should be reset"); XCTAssertEqual(0, [self.keychainView.accountStateKnown wait:50*NSEC_PER_MSEC], "CKK should know the account state"); @@ -3877,14 +4626,15 @@ XCTAssertEqual(0, [self.keychainView.loggedOut wait:20*NSEC_PER_SEC], "Should have been told of a 'logout'"); XCTAssertNotEqual(0, [self.keychainView.loggedIn wait:50*NSEC_PER_MSEC], "'login' event should be reset"); XCTAssertEqual(0, [self.keychainView.accountStateKnown wait:50*NSEC_PER_MSEC], "CKK should know the account state"); - [self checkNoCKKSData: self.keychainView]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered 'logged out'"); + [self checkNoCKKSData:self.keychainView]; // There should be no further uploads, even when we save keychain items [self addGenericPassword: @"data" account: @"account-delete-me-2"]; [self addGenericPassword: @"data" account: @"account-delete-me-3"]; - [self.keychainView waitUntilAllOperationsAreFinished]; + [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; + [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); // Also, fetches shouldn't occur @@ -3909,7 +4659,7 @@ // And fetching still works! [self.keychainZone addToZone: [self createFakeRecord: self.keychainZoneID recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D00" withAccount:@"account0"]]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; [self findGenericPassword: @"account0" expecting:errSecSuccess]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); @@ -3926,8 +4676,8 @@ // Add a keychain item, and make sure it doesn't upload yet. [self addGenericPassword: @"data" account: @"account-delete-me"]; - [self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]]; - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered 'loggedout'"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForCloudKitAccountStatus] wait:20*NSEC_PER_SEC], "CKKS entered 'waitforcloudkitaccount'"); + XCTAssertNotEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:1*NSEC_PER_SEC], "CKKS shouldn't have entered 'waitforcloudkitaccount'"); OCMVerifyAllWithDelay(self.mockDatabase, 20); @@ -4017,15 +4767,9 @@ // CKKS shouldn't decide to poke its state machine, but it should still send the notification XCTestExpectation* viewChangeNotification = [self expectChangeForView:self.keychainZoneID.zoneName]; - // Reject all attempts to trigger a state machine update - id pokeKeyStateMachineScheduler = OCMClassMock([CKKSNearFutureScheduler class]); - OCMReject([pokeKeyStateMachineScheduler trigger]); - self.keychainView.pokeKeyStateMachineScheduler = pokeKeyStateMachineScheduler; - [self addGenericPassword: @"data" account: @"account-delete-me-2"]; [self waitForExpectations:@[viewChangeNotification] timeout:8]; - [pokeKeyStateMachineScheduler stopMocking]; } - (void)testUploadSyncableItemsAddedWhileUntrusted { @@ -4043,8 +4787,6 @@ [self addGenericPassword: @"data" account: @"account-delete-me-2"]; - sleep(2); - NSError* error = nil; NSDictionary* currentOQEs = [CKKSOutgoingQueueEntry countsByStateInZone:self.keychainZoneID error:&error]; XCTAssertNil(error, "Should be no error counting OQEs"); @@ -4090,7 +4832,7 @@ XCTAssertNil(error, "Should be no error counting OQEs"); XCTAssertEqual(0, currentOQEs.count, "Should be no OQEs"); - [self.injectedManager setSyncingViews:self.managedViewList sortingPolicy:self.viewSortingPolicyForManagedViewList]; + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; self.keychainView = [self.injectedManager findView:self.keychainZoneID.zoneName]; // end of daemon restart @@ -4120,7 +4862,7 @@ [self addGenericPassword: @"data" account: @"account-delete-me-2"]; XCTAssertNotEqual(0, [self.keychainView.accountStateKnown wait:100*NSEC_PER_MSEC], "CKKS should still have no idea what the account state is"); XCTAssertEqual(self.keychainView.accountStatus, CKKSAccountStatusUnknown, "Account status should be unknown"); - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered 'logged out'"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForCloudKitAccountStatus] wait:20*NSEC_PER_SEC], "CKKS entered 'waitforcloudkitaccount'"); [self.keychainView beginCloudKitOperation]; @@ -4149,7 +4891,7 @@ [self updateGenericPassword:@"newdata" account: @"account-delete-me-2"]; XCTAssertNotEqual(0, [self.keychainView.accountStateKnown wait:100*NSEC_PER_MSEC], "CKKS should still have no idea what the account state is"); XCTAssertEqual(self.keychainView.accountStatus, CKKSAccountStatusUnknown, "Account status should be unknown"); - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered 'logged out'"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForCloudKitAccountStatus] wait:20*NSEC_PER_SEC], "CKKS entered 'waitforcloudkitaccount'"); [self.keychainView beginCloudKitOperation]; @@ -4178,7 +4920,7 @@ [self deleteGenericPassword:@"account-delete-me-2"]; XCTAssertNotEqual(0, [self.keychainView.accountStateKnown wait:100*NSEC_PER_MSEC], "CKKS should still have no idea what the account state is"); XCTAssertEqual(self.keychainView.accountStatus, CKKSAccountStatusUnknown, "Account status should be unknown"); - XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateLoggedOut] wait:20*NSEC_PER_SEC], "CKKS entered 'logged out'"); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForCloudKitAccountStatus] wait:20*NSEC_PER_SEC], "CKKS entered 'waitforcloudkitaccount'"); [self.keychainView beginCloudKitOperation]; @@ -4204,6 +4946,7 @@ [self startCKKSSubsystem]; [self waitForExpectations: @[operationRun] timeout:20]; + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'"); } - (void)testCKKSControlBringup { @@ -4286,11 +5029,11 @@ } [self measureBlock:^{ - [self.keychainView dispatchSyncWithAccountKeys:^bool{ + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ for(CKRecord* record in tlkShareRecords) { [self.keychainView _onqueueCKRecordChanged:record resync:false]; } - return true; + return CKKSDatabaseTransactionCommit; }]; }]; } @@ -4307,7 +5050,7 @@ [self saveTLKMaterialToKeychainSimulatingSOS:self.keychainZoneID]; - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; XCTAssertNotEqual(0, [fetcherCondition wait:(3 * NSEC_PER_SEC)], "not supposed to get a fetch data"); diff --git a/keychain/ckks/tests/CloudKitKeychainSyncingFixupTests.m b/keychain/ckks/tests/CloudKitKeychainSyncingFixupTests.m index e0701910..dea65b2a 100644 --- a/keychain/ckks/tests/CloudKitKeychainSyncingFixupTests.m +++ b/keychain/ckks/tests/CloudKitKeychainSyncingFixupTests.m @@ -49,7 +49,7 @@ - (void)testNoFixupOnInitialStart { id mockFixups = OCMClassMock([CKKSFixups class]); - OCMReject([[[mockFixups stub] ignoringNonObjectArgs] fixup:0 for:[OCMArg any]]); + [[[mockFixups reject] ignoringNonObjectArgs] fixup:0 for:[OCMArg any]]; [self startCKKSSubsystem]; [self performOctagonTLKUpload:self.ckksViews]; @@ -118,13 +118,13 @@ CKRecord* currentPointerRecord2 = self.keychainZone.currentDatabase[currentPointerRecordID2]; XCTAssertNotNil(currentPointerRecord2, "Found record in CloudKit at expected UUID"); - [self.keychainView notifyZoneChange:nil]; + [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil]; [self.keychainView waitForFetchAndIncomingQueueProcessing]; // Tear down the CKKS object [self.keychainView halt]; - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ // Edit the zone state entry to have no fixups NSError* error = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; @@ -146,7 +146,7 @@ XCTAssertEqual(cip3.identifier, @"garbage", "Identifier is what we thought it was"); [cip3 saveToDatabase:&error]; XCTAssertNil(error, "no error saving to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; self.silentFetchesAllowed = false; @@ -165,7 +165,7 @@ [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; OCMVerifyAllWithDelay(self.mockDatabase, 20); - [self.keychainView dispatchSync: ^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ // The zone state entry should be up the most recent fixup level NSError* error = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:self.keychainZoneID.zoneName error:&error]; @@ -187,12 +187,11 @@ } [self waitForExpectations:@[foundCIP2] timeout:0.1]; - return true; }]; } - (void)setFixupNumber:(CKKSFixup)newFixup ckks:(CKKSKeychainView*)ckks { - [ckks dispatchSync: ^bool { + [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ // Edit the zone state entry to have no fixups NSError* error = nil; CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry fromDatabase:ckks.zoneID.zoneName error:&error]; @@ -203,7 +202,7 @@ ckse.lastFixup = newFixup; [ckse saveToDatabase: &error]; XCTAssertNil(error, "no error saving to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; } @@ -218,6 +217,8 @@ [self waitForCKModifications]; OCMVerifyAllWithDelay(self.mockDatabase, 20); + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); + // Tear down the CKKS object [self.keychainView halt]; [self setFixupNumber:CKKSFixupRefetchCurrentItemPointers ckks:self.keychainView]; @@ -256,7 +257,6 @@ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForFixupOperation] wait:20*NSEC_PER_SEC], "Key state should become waitforfixup"); - self.silentFetchesAllowed = true; [self releaseCloudKitFetchHold]; XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "Key state should become ready"); @@ -266,12 +266,11 @@ XCTAssertNil(self.keychainView.lastFixupOperation.error, "Shouldn't have been any error performing fixup"); // and check that the share made it - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* blockerror = nil; CKKSTLKShareRecord* localshare = [CKKSTLKShareRecord tryFromDatabaseFromCKRecordID:shareCKRecord.recordID error:&blockerror]; XCTAssertNil(blockerror, "Shouldn't error finding new TLKShare record in database"); XCTAssertNotNil(localshare, "Should be able to find a new TLKShare record in database"); - return true; }]; } @@ -313,7 +312,7 @@ [self deleteGenericPassword:@"first"]; // Corrupt the second item's CKMirror entry to only contain system fields in the CKRecord portion (to emulate early CKKS behavior) - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSMirrorEntry* ckme = [CKKSMirrorEntry fromDatabase:secondRecordID.recordName zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "Should have no error pulling second CKKSMirrorEntry from database"); @@ -324,7 +323,7 @@ [ckme saveToDatabase:&error]; XCTAssertNil(error, "No error saving system-fielded CKME back to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // Now, restart CKKS, but place a hold on the fixup operation @@ -367,7 +366,7 @@ // Modify the sqlite DB to simulate how earlier verions would save these records - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ NSError* error = nil; CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry fromDatabase:self.remoteSOSOnlyPeer.peerID zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "Should have no error pulling CKKSDeviceStateEntry from database"); @@ -379,7 +378,7 @@ [cdse saveToDatabase:&error]; XCTAssertNil(error, "No error saving modified CDSE back to database"); - return true; + return CKKSDatabaseTransactionCommit; }]; // Tear down the CKKS object @@ -402,17 +401,59 @@ [self.keychainView waitForOperationsOfClass:[CKKSIncomingQueueOperation class]]; // And all CDSEs should have an octagon peer ID again! - [self.keychainView dispatchSync:^bool { + [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry fromDatabase:self.remoteSOSOnlyPeer.peerID zoneID:self.keychainZoneID error:&error]; XCTAssertNil(error, "Should have no error pulling CKKSDeviceStateEntry from database"); XCTAssertNotNil(cdse.octagonPeerID, "CDSE should have an octagon peer ID"); XCTAssertNotNil(cdse.octagonStatus, "CDSE should have an octagon status"); - return false; }]; } +- (void)testFixupDeletesTombstoneEntries { + [self startCKKSSubsystem]; + [self performOctagonTLKUpload:self.ckksViews]; + + XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"Key state should become 'ready'"); + OCMVerifyAllWithDelay(self.mockDatabase, 20); + [self waitForCKModifications]; + + // The CKKS stack now rejects tombstone items. So, let's inject one out of band. + + [self.keychainView halt]; + + [self setFixupNumber:CKKSFixupResaveDeviceStateEntries ckks:self.keychainView]; + + CKRecord* ckr = [self createFakeTombstoneRecord:self.keychainZoneID + recordName:@"7B598D31-F9C5-481E-98AC-5A507ACB2D85" + account:@"account-delete-me"]; + [self.keychainZone addToZone:ckr]; + + [self.keychainView dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{ + CKKSMirrorEntry* ckme = [[CKKSMirrorEntry alloc] initWithCKRecord:ckr]; + NSError* error = nil; + [ckme saveToDatabase:&error]; + + XCTAssertNil(error, "Should be no error saving the CKME to the database"); + return CKKSDatabaseTransactionCommit; + }]; + + // Now, restart CKKS. The bad record should be deleted. + [self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID]; + + self.keychainView = [[CKKSViewManager manager] restartZone:self.keychainZoneID.zoneName]; + [self beginSOSTrustedViewOperation:self.keychainView]; + + // Deletions should occur + OCMVerifyAllWithDelay(self.mockDatabase, 20); + + [self.keychainView.lastFixupOperation waitUntilFinished]; + XCTAssertNil(self.keychainView.lastFixupOperation.error, "Shouldn't have been any error performing fixup"); + + [self findGenericPassword:@"account-delete-me" expecting:errSecItemNotFound]; +} + @end #endif // OCTAGON diff --git a/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h b/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h index f64abed9..1b01318e 100644 --- a/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h +++ b/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h @@ -29,7 +29,6 @@ #import "keychain/ckks/CKKSCurrentKeyPointer.h" #import "keychain/ckks/CKKSItem.h" #import "keychain/ckks/tests/CKKSMockSOSPresentAdapter.h" -#import "keychain/ot/proto/generated_source/OTAccountMetadataClassC.h" #import "keychain/ot/OTCuttlefishAccountStateHolder.h" #include "OSX/sec/Security/SecItemShim.h" @@ -51,7 +50,6 @@ NS_ASSUME_NONNULL_BEGIN @interface CloudKitKeychainSyncingMockXCTest : CloudKitMockXCTest @property CKKSControl* ckksControl; -@property OTCuttlefishAccountStateHolder *accountMetaDataStore; @property (nullable) id mockCKKSKeychainBackedKey; @property (nullable) NSError* keychainFetchError; @@ -62,8 +60,9 @@ NS_ASSUME_NONNULL_BEGIN // Set this to false after calling -setUp if you want to initialize the views yourself @property bool automaticallyBeginCKKSViewCloudKitOperation; -// Fill this in before allowing initialization to use your own mock instead of a default stub +// Fill these in before allowing initialization to use your own mock instead of a default stub @property id suggestTLKUpload; +@property id requestPolicyCheck; @property NSMutableSet* ckksViews; @property NSMutableSet* ckksZones; @@ -122,14 +121,19 @@ NS_ASSUME_NONNULL_BEGIN withAccount:(NSString* _Nullable)account key:(CKKSKey* _Nullable)key; +- (CKRecord*)createFakeTombstoneRecord:(CKRecordZoneID*)zoneID recordName:(NSString*)recordName account:(NSString*)account; + - (CKKSItem*)newItem:(CKRecordID*)recordID withNewItemData:(NSDictionary*) dictionary key:(CKKSKey*)key; - (CKRecord*)newRecord:(CKRecordID*)recordID withNewItemData:(NSDictionary*)dictionary; - (CKRecord*)newRecord:(CKRecordID*)recordID withNewItemData:(NSDictionary*)dictionary key:(CKKSKey*)key; - (NSDictionary*)decryptRecord:(CKRecord*)record; +- (void)addItemToCloudKitZone:(NSDictionary*)itemDict recordName:(NSString*)recordName zoneID:(CKRecordZoneID*)zoneID; + // Do keychain things: - (void)addGenericPassword:(NSString*)password account:(NSString*)account; - (void)addGenericPassword:(NSString*)password account:(NSString*)account viewHint:(NSString* _Nullable)viewHint; +- (void)addGenericPassword:(NSString*)password account:(NSString*)account accessGroup:(NSString*)accessGroup; - (void)addGenericPassword:(NSString*)password account:(NSString*)account viewHint:(NSString* _Nullable)viewHint @@ -158,6 +162,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)findGenericPassword:(NSString*)account expecting:(OSStatus)status; - (void)checkGenericPassword:(NSString*)password account:(NSString*)account; +- (void)checkGenericPasswordStoredUUID:(NSString*)uuid account:(NSString*)account; +- (void)setGenericPasswordStoredUUID:(NSString*)uuid account:(NSString*)account; + - (void)createClassCItemAndWaitForUpload:(CKRecordZoneID*)zoneID account:(NSString*)account; - (void)createClassAItemAndWaitForUpload:(CKRecordZoneID*)zoneID account:(NSString*)account; diff --git a/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.m b/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.m index f7edec83..44da3423 100644 --- a/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.m +++ b/keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.m @@ -23,11 +23,15 @@ #if OCTAGON +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" #import +#pragma clang diagnostic pop #import "keychain/ckks/tests/CloudKitMockXCTest.h" #import "keychain/ckks/tests/CloudKitKeychainSyncingMockXCTest.h" +#import "keychain/securityd/SecItemSchema.h" #import "keychain/securityd/SecItemServer.h" #import "keychain/securityd/SecItemDb.h" @@ -106,6 +110,9 @@ self.suggestTLKUpload = OCMClassMock([CKKSNearFutureScheduler class]); OCMStub([self.suggestTLKUpload trigger]); + self.requestPolicyCheck = OCMClassMock([CKKSNearFutureScheduler class]); + OCMStub([self.requestPolicyCheck trigger]); + // If a subclass wants to fill these in before calling setUp, fine. self.ckksZones = self.ckksZones ?: [NSMutableSet set]; self.ckksViews = self.ckksViews ?: [NSMutableSet set]; @@ -140,15 +147,12 @@ OCMStub([mockConnection remoteObjectProxyWithErrorHandler:[OCMArg any]]).andCall(self, @selector(injectedManager)); self.ckksControl = [[CKKSControl alloc] initWithConnection:mockConnection]; XCTAssertNotNil(self.ckksControl, "Should have received control object"); - - self.accountMetaDataStore = OCMPartialMock([[OTCuttlefishAccountStateHolder alloc]init]); - OCMStub([self.accountMetaDataStore loadOrCreateAccountMetadata:[OCMArg anyObjectRef]]).andCall(self, @selector(loadOrCreateAccountMetadata:)); } - (void)tearDown { - // Make sure the key state machine won't be poked after teardown + // Make sure the key state machines won't continue for(CKKSKeychainView* view in self.ckksViews) { - [view.pokeKeyStateMachineScheduler cancel]; + [view.stateMachine haltOperation]; } [self.ckksViews removeAllObjects]; @@ -158,8 +162,6 @@ [self.mockCKKSKeychainBackedKey stopMocking]; self.mockCKKSKeychainBackedKey = nil; - [((id)self.accountMetaDataStore) stopMocking]; - self.remoteSOSOnlyPeer = nil; } @@ -185,7 +187,9 @@ [view beginCloudKitOperation]; } - [view beginTrustedOperation:@[self.mockSOSAdapter] suggestTLKUpload:self.suggestTLKUpload]; + [view beginTrustedOperation:@[self.mockSOSAdapter] + suggestTLKUpload:self.suggestTLKUpload + requestPolicyCheck:self.requestPolicyCheck]; } - (void)endSOSTrustedOperationForAllViews { @@ -259,6 +263,7 @@ NSError* error = nil; ZoneKeys* zonekeys = [[ZoneKeys alloc] init]; + zonekeys.viewName = zoneID.zoneName; zonekeys.tlk = [self fakeTLK:zoneID]; [zonekeys.tlk CKRecordWithZoneID: zoneID]; // no-op here, but memoize in the object @@ -291,26 +296,31 @@ } - (void)saveFakeKeyHierarchyToLocalDatabase: (CKRecordZoneID*)zoneID { - NSError* error = nil; ZoneKeys* zonekeys = [self createFakeKeyHierarchy: zoneID oldTLK:nil]; - [zonekeys.tlk saveToDatabase:&error]; - XCTAssertNil(error, "TLK saved to database successfully"); + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult { + NSError* error = nil; + + [zonekeys.tlk saveToDatabase:&error]; + XCTAssertNil(error, "TLK saved to database successfully"); + + [zonekeys.classA saveToDatabase:&error]; + XCTAssertNil(error, "Class A key saved to database successfully"); - [zonekeys.classA saveToDatabase:&error]; - XCTAssertNil(error, "Class A key saved to database successfully"); + [zonekeys.classC saveToDatabase:&error]; + XCTAssertNil(error, "Class C key saved to database successfully"); - [zonekeys.classC saveToDatabase:&error]; - XCTAssertNil(error, "Class C key saved to database successfully"); + [zonekeys.currentTLKPointer saveToDatabase:&error]; + XCTAssertNil(error, "Current TLK pointer saved to database successfully"); - [zonekeys.currentTLKPointer saveToDatabase:&error]; - XCTAssertNil(error, "Current TLK pointer saved to database successfully"); + [zonekeys.currentClassAPointer saveToDatabase:&error]; + XCTAssertNil(error, "Current Class A pointer saved to database successfully"); - [zonekeys.currentClassAPointer saveToDatabase:&error]; - XCTAssertNil(error, "Current Class A pointer saved to database successfully"); + [zonekeys.currentClassCPointer saveToDatabase:&error]; + XCTAssertNil(error, "Current Class C pointer saved to database successfully"); - [zonekeys.currentClassCPointer saveToDatabase:&error]; - XCTAssertNil(error, "Current Class C pointer saved to database successfully"); + return CKKSDatabaseTransactionCommit; + }]; } - (void)putFakeDeviceStatusInCloudKit:(CKRecordZoneID*)zoneID zonekeys:(ZoneKeys*)zonekeys { @@ -460,7 +470,7 @@ for(CKKSKeychainView* view in views) { XCTAssertEqual(0, [view.keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTLKCreation] wait:40*NSEC_PER_SEC], @"key state should enter 'waitfortlkcreation' (view %@)", view); - [keysetOps addObject: [view findKeySet]]; + [keysetOps addObject: [view findKeySet:NO]]; } // Now that we've kicked them all off, wait for them to resolve @@ -577,6 +587,7 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) CFReleaseNull(cferror); return piggybackdata; } + - (void)SOSPiggyBackAddToKeychain:(NSDictionary*)piggydata{ __block CFErrorRef cferror = NULL; kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) { @@ -676,11 +687,15 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) ZoneKeys* keys = self.keys[zoneID]; XCTAssertNotNil(keys, "Have a zonekeys object for this zone"); - for(CKKSTLKShareRecord* share in keys.tlkShares) { - NSError* error = nil; - [share saveToDatabase:&error]; - XCTAssertNil(error, "Shouldn't have been an error saving a TLKShare to the database"); - } + [CKKSSQLDatabaseObject performCKKSTransaction:^CKKSDatabaseTransactionResult{ + for(CKKSTLKShareRecord* share in keys.tlkShares) { + NSError* error = nil; + [share saveToDatabase:&error]; + XCTAssertNil(error, "Shouldn't have been an error saving a TLKShare to the database"); + } + + return CKKSDatabaseTransactionCommit; + }]; } - (void)createAndSaveFakeKeyHierarchy: (CKRecordZoneID*)zoneID { @@ -862,7 +877,7 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) - (void)checkNoCKKSData: (CKKSKeychainView*) view { // Test that there are no items in the database - [view dispatchSync:^bool{ + [view dispatchSyncWithReadOnlySQLTransaction:^{ NSError* error = nil; NSArray* ckmes = [CKKSMirrorEntry all: view.zoneID error:&error]; XCTAssertNil(error, "No error fetching CKMEs"); @@ -883,7 +898,6 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) NSArray* deviceStates = [CKKSDeviceStateEntry allInZone:view.zoneID error:&error]; XCTAssertNil(error, "should be no error fetching device states"); XCTAssertEqual(deviceStates.count, 0ul, "No Device State entries"); - return false; }]; } @@ -982,6 +996,15 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) return item; } + +- (CKRecord*)createFakeTombstoneRecord:(CKRecordZoneID*)zoneID recordName:(NSString*)recordName account:(NSString*)account { + NSMutableDictionary* item = [[self fakeRecordDictionary:account zoneID:zoneID] mutableCopy]; + item[@"tomb"] = @YES; + + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:recordName zoneID:zoneID]; + return [self newRecord:ckrid withNewItemData:item]; +} + - (CKRecord*)createFakeRecord: (CKRecordZoneID*)zoneID recordName:(NSString*)recordName { return [self createFakeRecord: zoneID recordName:recordName withAccount: nil key:nil]; } @@ -1037,6 +1060,17 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) return ckr; } +- (void)addItemToCloudKitZone:(NSDictionary*)itemDict recordName:(NSString*)recordName zoneID:(CKRecordZoneID*)zoneID +{ + FakeCKZone* zone = self.zones[zoneID]; + XCTAssertNotNil(zone, "Should have a zone for %@", zoneID); + + CKRecordID* ckrid = [[CKRecordID alloc] initWithRecordName:recordName zoneID:zoneID]; + CKRecord* record = [self newRecord:ckrid withNewItemData:itemDict]; + + [zone addToZone:record]; +} + - (NSDictionary*)decryptRecord: (CKRecord*) record { CKKSItem* item = [[CKKSItem alloc] initWithCKRecord: record]; @@ -1099,6 +1133,18 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) [self addGenericPassword:password account:account viewHint:viewHint access:(id)kSecAttrAccessibleAfterFirstUnlock expecting:errSecSuccess message:@"Add item to keychain with a viewhint"]; } + +- (void)addGenericPassword:(NSString*)password account:(NSString*)account accessGroup:(NSString*)accessGroup +{ + [self addGenericPassword:password + account:account + access:(id)kSecAttrAccessibleAfterFirstUnlock + viewHint:nil + accessGroup:accessGroup + expecting:errSecSuccess + message:@"Add item to keychain with an access group"]; +} + - (void)updateGenericPassword: (NSString*) newPassword account: (NSString*)account { NSDictionary* query = @{ (id)kSecClass : (id)kSecClassGenericPassword, @@ -1178,10 +1224,83 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) XCTAssertEqualObjects(storedPassword, password, "Stored password should match received password"); } +- (void)checkGenericPasswordStoredUUID:(NSString*)uuid account:(NSString*)account { + NSDictionary* queryAttributes = @{(id)kSecClass: (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : account, + (id)kSecAttrSynchronizable: @(YES), + (id)kSecReturnAttributes : @(YES), + (id)kSecReturnData : (id)kCFBooleanTrue, + }; + + __block CFErrorRef cferror = nil; + Query *q = query_create_with_limit( (__bridge CFDictionaryRef)queryAttributes, NULL, kSecMatchUnlimited, NULL, &cferror); + XCTAssertNil((__bridge id)cferror, "Should be no error creating query"); + CFReleaseNull(cferror); + + __block size_t count = 0; + + bool ok = kc_with_dbt(true, &cferror, ^(SecDbConnectionRef dbt) { + return SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef item, bool *stop) { + count += 1; + + NSString* itemUUID = (NSString*) CFBridgingRelease(CFRetain(SecDbItemGetValue(item, &v10itemuuid, &cferror))); + XCTAssertEqualObjects(uuid, itemUUID, "Item uuid should match expectation"); + }); + }); + + XCTAssertTrue(ok, "query should have been successful"); + XCTAssertNil((__bridge id)cferror, "Should be no error performing query"); + CFReleaseNull(cferror); + + XCTAssertEqual(count, 1, "Should have processed one item"); +} + +- (void)setGenericPasswordStoredUUID:(NSString*)uuid account:(NSString*)account { + NSDictionary* queryAttributes = @{(id)kSecClass: (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.security.ckks", + (id)kSecAttrAccount : account, + (id)kSecAttrSynchronizable: @(YES), + (id)kSecReturnAttributes : @(YES), + (id)kSecReturnData : (id)kCFBooleanTrue, + }; + + __block CFErrorRef cferror = nil; + Query *q = query_create_with_limit( (__bridge CFDictionaryRef)queryAttributes, NULL, kSecMatchUnlimited, NULL, &cferror); + XCTAssertNil((__bridge id)cferror, "Should be no error creating query"); + CFReleaseNull(cferror); + + __block size_t count = 0; + + bool ok = kc_with_dbt(true, &cferror, ^(SecDbConnectionRef dbt) { + return SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef item, bool *stop) { + count += 1; + + NSDictionary* updates = @{(id) kSecAttrUUID: uuid}; + + SecDbItemRef new_item = SecDbItemCopyWithUpdates(item, (__bridge CFDictionaryRef)updates, &cferror); + XCTAssertTrue(new_item != NULL, "Should be able to create a new item"); + + bool updateOk = kc_transaction_type(dbt, kSecDbExclusiveRemoteCKKSTransactionType, &cferror, ^{ + return SecDbItemUpdate(item, new_item, dbt, kCFBooleanFalse, q->q_uuid_from_primary_key, &cferror); + }); + XCTAssertTrue(updateOk, "Should be able to update item"); + + return; + }); + }); + + XCTAssertTrue(ok, "query should have been successful"); + XCTAssertNil((__bridge id)cferror, "Should be no error performing query"); + CFReleaseNull(cferror); + + XCTAssertEqual(count, 1, "Should have processed one item"); +} + -(XCTestExpectation*)expectChangeForView:(NSString*)view { NSString* notification = [NSString stringWithFormat: @"com.apple.security.view-change.%@", view]; return [self expectationForNotification:notification object:nil handler:^BOOL(NSNotification * _Nonnull nsnotification) { - secnotice("ckks", "Got a notification for %@: %@", notification, nsnotification); + ckksnotice_global("ckks", "Got a notification for %@: %@", notification, nsnotification); return YES; }]; } @@ -1210,14 +1329,6 @@ static CFDictionaryRef SOSCreatePeerGestaltFromName(CFStringRef name) } } -- (OTAccountMetadataClassC*)loadOrCreateAccountMetadata:(NSError**)error -{ - if(error) { - *error = [NSError errorWithDomain:@"securityd" code:errSecInteractionNotAllowed userInfo:nil]; - } - return nil; -} - @end #endif // OCTAGON diff --git a/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.h b/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.h index 0cb5406b..f8694906 100644 --- a/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.h +++ b/keychain/ckks/tests/CloudKitKeychainSyncingTestsBase.h @@ -25,7 +25,12 @@ #define CloudKitKeychainSyncingTestsBase_h #import + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" #import +#pragma clang diagnostic pop + #import #include diff --git a/keychain/ckks/tests/CloudKitMockXCTest.h b/keychain/ckks/tests/CloudKitMockXCTest.h index 4df9a3cb..40b9ea6f 100644 --- a/keychain/ckks/tests/CloudKitMockXCTest.h +++ b/keychain/ckks/tests/CloudKitMockXCTest.h @@ -36,6 +36,7 @@ #import "keychain/ckks/tests/MockCloudKit.h" #import "keychain/ot/OTManager.h" +#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h" NS_ASSUME_NONNULL_BEGIN @@ -48,6 +49,9 @@ NS_ASSUME_NONNULL_BEGIN @class CKKSReachabilityTracker; @class SOSCKKSPeerAdapter; +@interface CKKSTestFailureLogger : NSObject +@end + @interface CloudKitMockXCTest : XCTestCase @property CKRecordZoneID* testZoneID; @@ -106,7 +110,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable) CKKSMockOctagonAdapter *mockOctagonAdapter; - (NSSet*)managedViewList; -- (TPPolicy*)viewSortingPolicyForManagedViewList; +- (TPSyncingPolicy*)viewSortingPolicyForManagedViewList; +- (TPSyncingPolicy*)viewSortingPolicyForManagedViewListWithUserControllableViews:(NSSet*)ucv + syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews; @property (nullable) id mockCKKSViewManager; @property (nullable) CKKSViewManager* injectedManager; @@ -127,6 +133,9 @@ NS_ASSUME_NONNULL_BEGIN // Fill this in to fail the next modifyzones operation @property (nullable) NSError* nextModifyRecordZonesError; +// Used to track the test failure logger (for test teardown purposes) +@property (class) CKKSTestFailureLogger* testFailureLogger; + - (CKKSKey*)fakeTLK:(CKRecordZoneID*)zoneID; - (void)expectCKModifyItemRecords:(NSUInteger)expectedNumberOfRecords diff --git a/keychain/ckks/tests/CloudKitMockXCTest.m b/keychain/ckks/tests/CloudKitMockXCTest.m index f8e42b58..02e3b87e 100644 --- a/keychain/ckks/tests/CloudKitMockXCTest.m +++ b/keychain/ckks/tests/CloudKitMockXCTest.m @@ -30,7 +30,12 @@ #import #import #import + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" #import +#pragma clang diagnostic pop + #import #import #import @@ -78,15 +83,39 @@ - (void)_checkSelfCloudServicesEntitlement; @end +@implementation CKKSTestFailureLogger +- (instancetype)init { + if((self = [super init])) { + } + return self; +} + +- (void)testCase:(XCTestCase *)testCase didRecordIssue:(XCTIssue *)issue { + ckksnotice_global("ckkstests", "XCTest failure: (%@)%@:%lu error: %@ -- %@\n%@", + testCase.name, + issue.sourceCodeContext.location.fileURL, + (long)issue.sourceCodeContext.location.lineNumber, + issue.compactDescription, + issue.detailedDescription, + issue.sourceCodeContext.callStack); +} +@end @implementation CloudKitMockXCTest @synthesize aksLockState = _aksLockState; +static CKKSTestFailureLogger* _testFailureLoggerVariable; + + (void)setUp { // Turn on testing SecCKKSEnable(); SecCKKSTestsEnable(); SecCKKSSetReduceRateLimiting(true); + + self.testFailureLogger = [[CKKSTestFailureLogger alloc] init]; + + [[XCTestObservationCenter sharedTestObservationCenter] addTestObserver:self.testFailureLogger]; + [super setUp]; #if NO_SERVER @@ -94,6 +123,19 @@ #endif } ++ (void)tearDown { + [super tearDown]; + [[XCTestObservationCenter sharedTestObservationCenter] removeTestObserver:self.testFailureLogger]; +} + ++ (CKKSTestFailureLogger*)testFailureLogger { + return _testFailureLoggerVariable; +} + ++ (void)setTestFailureLogger:(CKKSTestFailureLogger*)logger { + _testFailureLoggerVariable = logger; +} + - (BOOL)isRateLimited:(SecTapToRadar *)ttrRequest { return self.isTTRRatelimited; @@ -132,7 +174,7 @@ self.apsEnvironment = @"fake APS push string"; // Static variables are a scourge. Let's reset this one... - [OctagonAPSReceiver resetGlobalEnviornmentMap]; + [OctagonAPSReceiver resetGlobalDelegatePortMap]; self.mockDatabaseExceptionCatcher = OCMStrictClassMock([CKDatabase class]); self.mockDatabase = OCMStrictClassMock([CKDatabase class]); @@ -162,7 +204,7 @@ // Inject a fake operation dependency so we won't respond with the CloudKit account status immediately // The CKKSAccountStateTracker won't send any login/logout calls without that information, so this blocks all CKKS setup self.ckaccountHoldOperation = [NSBlockOperation named:@"ckaccount-hold" withBlock:^{ - secnotice("ckks", "CKKS CK account status test hold released"); + ckksnotice_global("ckks", "CKKS CK account status test hold released"); }]; OCMStub([self.mockContainer accountStatusWithCompletionHandler: @@ -359,12 +401,6 @@ OCMStub([self.mockCKKSViewManager syncBackupAndNotifyAboutSync]); OCMStub([self.mockCKKSViewManager waitForTrustReady]).andReturn(YES); - if(!self.disableConfigureCKKSViewManagerWithViews) { - // Normally, the Octagon state machine calls this. But, since we won't be running that, help it out. - [self.injectedManager setSyncingViews:[self managedViewList] - sortingPolicy:[self viewSortingPolicyForManagedViewList]]; - } - // Lie and say network is available [self.reachabilityTracker setNetworkReachability:true]; @@ -377,6 +413,12 @@ // Actually load the database. kc_with_dbt(true, NULL, ^bool (SecDbConnectionRef dbt) { return false; }); + + if(!self.disableConfigureCKKSViewManagerWithViews) { + // Normally, the Octagon state machine calls this. But, since we won't be running that, help it out. + // CKKS might try to take a DB lock, so do this after the DB load above + [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList]; + } } - (OTManager*)setUpOTManager:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies @@ -400,11 +442,15 @@ - (void)setAksLockState:(bool)aksLockState { - + ckksnotice_global("ckkstests", "Setting mock AKS lock state to: %@", (aksLockState ? @"locked" : @"unlocked")); if(aksLockState) { [SecMockAKS lockClassA]; + + self.mockSOSAdapter.aksLocked = YES; } else { [SecMockAKS unlockAllClasses]; + + self.mockSOSAdapter.aksLocked = NO; } _aksLockState = aksLockState; } @@ -458,7 +504,14 @@ return (NSSet*) CFBridgingRelease(SOSViewCopyViewSet(kViewSetCKKS)); } -- (TPPolicy*)viewSortingPolicyForManagedViewList +- (TPSyncingPolicy*)viewSortingPolicyForManagedViewList +{ + return [self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet set] + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED]; +} + +- (TPSyncingPolicy*)viewSortingPolicyForManagedViewListWithUserControllableViews:(NSSet*)ucv + syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews { NSMutableArray* rules = [NSMutableArray array]; @@ -471,13 +524,13 @@ [rules addObject:mapping]; } - TPPolicy* policy = [TPPolicy policyWithModelToCategory:@[] - categoriesByView:@{} - introducersByCategory:@{} - keyViewMapping:rules - unknownRedactions:NO - version:[[TPPolicyVersion alloc] initWithVersion:1 hash:@"fake-policy-for-views"]]; - + TPSyncingPolicy* policy = [[TPSyncingPolicy alloc] initWithModel:@"test-policy" + version:[[TPPolicyVersion alloc] initWithVersion:1 hash:@"fake-policy-for-views"] + viewList:[self managedViewList] + userControllableViews:ucv + syncUserControllableViews:syncUserControllableViews + viewsToPiggybackTLKs:[NSSet set] + keyViewMapping:rules]; return policy; } @@ -589,7 +642,7 @@ -(void)holdCloudKitModifications { XCTAssertFalse([self.ckModifyHoldOperation isPending], "Shouldn't already be a pending cloudkit modify hold operation"); self.ckModifyHoldOperation = [NSBlockOperation blockOperationWithBlock:^{ - secnotice("ckks", "Released CloudKit modification hold."); + ckksnotice_global("ckks", "Released CloudKit modification hold."); }]; } -(void)releaseCloudKitModificationHold { @@ -601,7 +654,7 @@ -(void)holdCloudKitFetches { XCTAssertFalse([self.ckFetchHoldOperation isPending], "Shouldn't already be a pending cloudkit fetch hold operation"); self.ckFetchHoldOperation = [NSBlockOperation blockOperationWithBlock:^{ - secnotice("ckks", "Released CloudKit fetch hold."); + ckksnotice_global("ckks", "Released CloudKit fetch hold."); }]; } -(void)releaseCloudKitFetchHold { @@ -613,7 +666,7 @@ -(void)holdCloudKitModifyRecordZones { XCTAssertFalse([self.ckModifyRecordZonesHoldOperation isPending], "Shouldn't already be a pending cloudkit zone create hold operation"); self.ckModifyRecordZonesHoldOperation = [NSBlockOperation blockOperationWithBlock:^{ - secnotice("ckks", "Released CloudKit zone create hold."); + ckksnotice_global("ckks", "Released CloudKit zone create hold."); }]; } -(void)releaseCloudKitModifyRecordZonesHold { @@ -625,7 +678,7 @@ -(void)holdCloudKitModifySubscription { XCTAssertFalse([self.ckModifySubscriptionsHoldOperation isPending], "Shouldn't already be a pending cloudkit subscription hold operation"); self.ckModifySubscriptionsHoldOperation = [NSBlockOperation blockOperationWithBlock:^{ - secnotice("ckks", "Released CloudKit zone create hold."); + ckksnotice_global("ckks", "Released CloudKit zone create hold."); }]; } -(void)releaseCloudKitModifySubscriptionHold { @@ -812,14 +865,14 @@ if(expectedRecordTypeCounts) { matches &= !![modifiedRecordTypeCounts isEqual: filteredExpectedRecordTypeCounts]; if(!matches) { - secnotice("fakecloudkit", "Record number mismatch: %@ %@", modifiedRecordTypeCounts, filteredExpectedRecordTypeCounts); + secnotice("fakecloudkit", "Record number mismatch: attempted:%@ expected:%@", modifiedRecordTypeCounts, filteredExpectedRecordTypeCounts); result = NO; return; } } else { matches &= op.recordsToSave.count == 0u; if(!matches) { - secnotice("fakecloudkit", "Record number mismatch: %@ 0", modifiedRecordTypeCounts); + secnotice("fakecloudkit", "Record number mismatch: attempted:%@ expected:0", modifiedRecordTypeCounts); result = NO; return; } @@ -827,14 +880,14 @@ if(expectedDeletedRecordTypeCounts) { matches &= !![deletedRecordTypeCounts isEqual: expectedDeletedRecordTypeCounts]; if(!matches) { - secnotice("fakecloudkit", "Deleted record number mismatch: %@ %@", deletedRecordTypeCounts, expectedDeletedRecordTypeCounts); + secnotice("fakecloudkit", "Deleted record number mismatch: attempted:%@ expected:%@", deletedRecordTypeCounts, expectedDeletedRecordTypeCounts); result = NO; return; } } else { matches &= op.recordIDsToDelete.count == 0u; if(!matches) { - secnotice("fakecloudkit", "Deleted record number mismatch: %@ 0", deletedRecordTypeCounts); + secnotice("fakecloudkit", "Deleted record number mismatch: attempted:%@ expected:0", deletedRecordTypeCounts); result = NO; return; } @@ -858,6 +911,10 @@ // if you'd like to read the data from this write. NSBlockOperation* ckop = [NSBlockOperation named:@"cloudkit-write" withBlock: ^{ @synchronized(zone.currentDatabase) { + if(zone.blockBeforeWriteOperation) { + zone.blockBeforeWriteOperation(); + } + NSMutableArray* savedRecords = [[NSMutableArray alloc] init]; for(CKRecord* record in op.recordsToSave) { CKRecord* reflectedRecord = [record copy]; diff --git a/keychain/ckks/tests/MockCloudKit.h b/keychain/ckks/tests/MockCloudKit.h index 91226056..6267a478 100644 --- a/keychain/ckks/tests/MockCloudKit.h +++ b/keychain/ckks/tests/MockCloudKit.h @@ -120,6 +120,9 @@ typedef NSMutableDictionary FakeCKDatabase; // Serial queue. Use this for transactionality. @property dispatch_queue_t queue; +// Set this to run some code after a write operation has started, but before any results are delivered +@property (nullable) void (^blockBeforeWriteOperation)(void); + - (instancetype)initZone:(CKRecordZoneID*)zoneID; // Always Succeed diff --git a/keychain/ckks/tests/MockCloudKit.m b/keychain/ckks/tests/MockCloudKit.m index 1a15ff54..33775047 100644 --- a/keychain/ckks/tests/MockCloudKit.m +++ b/keychain/ckks/tests/MockCloudKit.m @@ -75,7 +75,7 @@ self.completionBlock = ^{ __strong __typeof(weakSelf) strongSelf = weakSelf; if(!strongSelf) { - secerror("ckks: received callback for released object"); + ckkserror_global("ckks", "received callback for released object"); return; } @@ -121,7 +121,7 @@ if(!skipCreation) { // Create the zone: - secnotice("ckks", "Creating zone %@", zone); + ckksnotice_global("ckks", "Creating zone %@", zone); ckdb[zone.zoneID] = [[FakeCKZone alloc] initZone: zone.zoneID]; } @@ -213,7 +213,7 @@ self.completionBlock = ^{ __strong __typeof(weakSelf) strongSelf = weakSelf; if(!strongSelf) { - secerror("ckks: received callback for released object"); + ckkserror_global("ckks", "received callback for released object"); return; } @@ -291,6 +291,8 @@ @synthesize recordZoneFetchCompletionBlock = _recordZoneFetchCompletionBlock; @synthesize fetchRecordZoneChangesCompletionBlock = _fetchRecordZoneChangesCompletionBlock; +@synthesize deviceIdentifier = _deviceIdentifier; + @synthesize operationID = _operationID; @synthesize resolvedConfiguration = _resolvedConfiguration; @synthesize group = _group; @@ -313,6 +315,7 @@ _configurationsByRecordZoneID = configurationsByRecordZoneID; _operationID = @"fake-operation-ID"; + _deviceIdentifier = @"ckkstests"; } return self; } @@ -422,11 +425,10 @@ self.recordZoneChangeTokensUpdatedBlock(zoneID, currentChangeToken, nil); self.recordZoneFetchCompletionBlock(zoneID, currentChangeToken, nil, moreComing, opError); + } - if(self.blockAfterFetch) { - self.blockAfterFetch(); - } - + if(self.blockAfterFetch) { + self.blockAfterFetch(); } self.fetchRecordZoneChangesCompletionBlock(nil); @@ -598,18 +600,15 @@ @implementation FakeAPSConnection @synthesize delegate; +@synthesize enabledTopics; +@synthesize opportunisticTopics; +@synthesize darkWakeTopics; + - (id)initWithEnvironmentName:(NSString *)environmentName namedDelegatePort:(NSString*)namedDelegatePort queue:(dispatch_queue_t)queue { if(self = [super init]) { } return self; } - -- (void)setEnabledTopics:(NSArray *)enabledTopics { -} - -- (void)setDarkWakeTopics:(NSArray *)darkWakeTopics { -} - @end // Do literally nothing @@ -767,10 +766,14 @@ - (NSError*)deleteCKRecordIDFromZone:(CKRecordID*) recordID { // todo: fail somehow dispatch_sync(self.queue, ^{ + ckksnotice("fakeck", self.zoneID, "Change token before server-deleted record is : %@", self.currentChangeToken); + self.pastDatabases[self.currentChangeToken] = [self.currentDatabase mutableCopy]; [self _onqueueRollChangeToken]; [self.currentDatabase removeObjectForKey: recordID]; + + ckksnotice("fakeck", self.zoneID, "Change token after server-deleted record is : %@", self.currentChangeToken); }); return nil; } @@ -824,7 +827,7 @@ if(notification) { // This isn't actually fake, but XCTest likes NSNotificationCenter a whole lot. // These notifications shouldn't escape this process, so it's perfect. - secnotice("ckks", "sending fake NSNotification %@", notification); + ckksnotice_global("ckks", "sending fake NSNotification %@", notification); [[NSNotificationCenter defaultCenter] postNotificationName:notification object:nil]; } } diff --git a/keychain/ckks/tests/OctagonAPSReceiverTests.m b/keychain/ckks/tests/OctagonAPSReceiverTests.m index 12ae14e6..18970fcb 100644 --- a/keychain/ckks/tests/OctagonAPSReceiverTests.m +++ b/keychain/ckks/tests/OctagonAPSReceiverTests.m @@ -33,7 +33,7 @@ #if OCTAGON -@interface CKKSAPSNotificationReceiver : NSObject +@interface CKKSAPSNotificationReceiver : NSObject @property XCTestExpectation* expectation; @property void (^block)(CKRecordZoneNotification* notification); @@ -107,9 +107,8 @@ - (void)testRegisterAndReceive { __weak __typeof(self)weakSelf = self; - OctagonAPSReceiver* apsr = [[OctagonAPSReceiver alloc] initWithEnvironmentName:@"testenvironment" - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; + OctagonAPSReceiver* apsr = [[OctagonAPSReceiver alloc] initWithNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:[FakeAPSConnection class]]; XCTAssertNotNil(apsr, "Should have received a OctagonAPSReceiver"); @@ -121,7 +120,7 @@ XCTAssertEqual(strongSelf.testZoneID, notification.recordZoneID, "Should have received a notification for the test zone"); }]; - CKKSCondition* registered = [apsr registerReceiver:anr forZoneID:self.testZoneID]; + CKKSCondition* registered = [apsr registerCKKSReceiver:anr]; XCTAssertEqual(0, [registered wait:1*NSEC_PER_SEC], "Registration should have completed within a second"); APSIncomingMessage* message = [OctagonAPSReceiverTests messageForZoneID:self.testZoneID]; XCTAssertNotNil(message, "Should have received a APSIncomingMessage"); @@ -131,46 +130,9 @@ [self waitForExpectationsWithTimeout:5.0 handler:nil]; } -- (void)testRegisterMultipleAndReceive { - __weak __typeof(self)weakSelf = self; - - OctagonAPSReceiver* apsr = [[OctagonAPSReceiver alloc] initWithEnvironmentName:@"testenvironment" - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; - - XCTAssertNotNil(apsr, "Should have received a OctagonAPSReceiver"); - - CKRecordZoneID* otherZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"otherzone" ownerName:CKCurrentUserDefaultName]; - - CKKSAPSNotificationReceiver* anr = [[CKKSAPSNotificationReceiver alloc] initWithExpectation:[self expectationWithDescription:@"receive testZoneID notification"] - block: - ^(CKRecordZoneNotification* notification) { - __strong __typeof(self) strongSelf = weakSelf; - XCTAssertNotNil(notification, "Should have received a notification"); - XCTAssertEqual(strongSelf.testZoneID, notification.recordZoneID, "Should have received a notification for the test zone"); - }]; - CKKSAPSNotificationReceiver* anr2 = [[CKKSAPSNotificationReceiver alloc] initWithExpectation:[self expectationWithDescription:@"receive otherzone notification"] - block: - ^(CKRecordZoneNotification* notification) { - XCTAssertNotNil(notification, "Should have received a notification"); - XCTAssertEqual(otherZoneID, notification.recordZoneID, "Should have received a notification for the test zone"); - }]; - - CKKSCondition* registered = [apsr registerReceiver:anr forZoneID:self.testZoneID]; - CKKSCondition* registered2 = [apsr registerReceiver:anr2 forZoneID:otherZoneID]; - XCTAssertEqual(0, [registered wait:1*NSEC_PER_SEC], "Registration should have completed within a second"); - XCTAssertEqual(0, [registered2 wait:1*NSEC_PER_SEC], "Registration should have completed within a second"); - - [apsr connection:apsr.apsConnection didReceiveIncomingMessage:[OctagonAPSReceiverTests messageForZoneID:self.testZoneID]]; - [apsr connection:apsr.apsConnection didReceiveIncomingMessage:[OctagonAPSReceiverTests messageForZoneID:otherZoneID]]; - - [self waitForExpectationsWithTimeout:5.0 handler:nil]; -} - - (void)testReceiveNotificationIfRegisteredAfterDelivery { - OctagonAPSReceiver* apsr = [[OctagonAPSReceiver alloc] initWithEnvironmentName:@"testenvironment" - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:[FakeAPSConnection class]]; + OctagonAPSReceiver* apsr = [[OctagonAPSReceiver alloc] initWithNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:[FakeAPSConnection class]]; XCTAssertNotNil(apsr, "Should have received a OctagonAPSReceiver"); // Receives a notification for the test zone @@ -184,7 +146,7 @@ XCTAssertNotNil(notification, "Should have received a (stored) notification"); }]; - CKKSCondition* registered = [apsr registerReceiver:anr forZoneID:self.testZoneID]; + CKKSCondition* registered = [apsr registerCKKSReceiver:anr]; XCTAssertEqual(0, [registered wait:1*NSEC_PER_SEC], "Registration should have completed within a second"); [self waitForExpectationsWithTimeout:5.0 handler:nil]; diff --git a/keychain/ckks/tests/RateLimiterTests.m b/keychain/ckks/tests/RateLimiterTests.m index 67f906bc..03c8056f 100644 --- a/keychain/ckks/tests/RateLimiterTests.m +++ b/keychain/ckks/tests/RateLimiterTests.m @@ -33,16 +33,14 @@ @implementation TestObject - (instancetype)init { - self = [super init]; - if (self) { + if ((self = [super init])) { _uuid = [[NSUUID UUID] UUIDString]; } return self; } - (instancetype)initWithNilUuid { - self = [super init]; - if (self) { + if ((self = [super init])) { _uuid = nil; } return self; diff --git a/keychain/ckks/tests/gen_test_plist.py b/keychain/ckks/tests/gen_test_plist.py index 52065f61..d3b6db8c 100644 --- a/keychain/ckks/tests/gen_test_plist.py +++ b/keychain/ckks/tests/gen_test_plist.py @@ -59,7 +59,10 @@ for x in get_class_names(): test_dictionary['WorkingDirectory'] = '/AppleInternal/XCTests/com.apple.security/' test_command = Foundation.NSMutableArray.array() - test_command.append('BATS_XCTEST_CMD -XCTest {} CKKSTests.xctest'.format(x)) + test_command.append('BATS_XCTEST_CMD') + test_command.append('-XCTest') + test_command.append('{}'.format(x)) + test_command.append('CKKSTests.xctest') test_dictionary['Command'] = test_command test_list.append(test_dictionary) diff --git a/keychain/ckksctl/ckksctl.m b/keychain/ckksctl/ckksctl.m index d27cf217..48d96d62 100644 --- a/keychain/ckksctl/ckksctl.m +++ b/keychain/ckksctl/ckksctl.m @@ -353,20 +353,17 @@ static void print_entry(id k, id v, int ind) NSString* accountTracker = pop(status,@"accounttracker", NSString); NSString* fetcher = pop(status,@"fetcher", NSString); NSString* zoneCreated = pop(status,@"zoneCreated", NSString); - NSString* zoneCreatedError = pop(status,@"zoneCreatedError", NSString); NSString* zoneSubscribed = pop(status,@"zoneSubscribed", NSString); - NSString* zoneSubscribedError = pop(status,@"zoneSubscribedError", NSString); NSString* zoneInitializeScheduler = pop(status,@"zoneInitializeScheduler", NSString); NSString* keystate = pop(status,@"keystate", NSString); - NSString* keyStateError = pop(status,@"keyStateError", NSString); NSString* statusError = pop(status,@"statusError", NSString); + NSString* itemSyncEnabled = pop(status,@"itemsyncing", NSString); NSString* currentTLK = pop(status,@"currentTLK", NSString); NSString* currentClassA = pop(status,@"currentClassA", NSString); NSString* currentClassC = pop(status,@"currentClassC", NSString); NSString* currentTLKPtr = pop(status,@"currentTLKPtr", NSString); NSString* currentClassAPtr = pop(status,@"currentClassAPtr", NSString); NSString* currentClassCPtr = pop(status,@"currentClassCPtr", NSString); - NSString* currentManifestGeneration = pop(status,@"currentManifestGen", NSString); NSArray* launchSequence = pop(status, @"launchSequence", NSArray); NSDictionary* oqe = pop(status,@"oqe", NSDictionary); @@ -376,14 +373,11 @@ static void print_entry(id k, id v, int ind) NSArray* devicestates = pop(status, @"devicestates", NSArray); NSArray* tlkshares = pop(status, @"tlkshares", NSArray); - NSString* zoneSetupOperation = pop(status,@"zoneSetupOperation", NSString); - NSString* keyStateOperation = pop(status,@"keyStateOperation", NSString); NSString* lastIncomingQueueOperation = pop(status,@"lastIncomingQueueOperation", NSString); NSString* lastNewTLKOperation = pop(status,@"lastNewTLKOperation", NSString); NSString* lastOutgoingQueueOperation = pop(status,@"lastOutgoingQueueOperation", NSString); NSString* lastProcessReceivedKeysOperation = pop(status,@"lastProcessReceivedKeysOperation", NSString); NSString* lastReencryptOutgoingItemsOperation = pop(status,@"lastReencryptOutgoingItemsOperation", NSString); - NSString* lastScanLocalItemsOperation = pop(status,@"lastScanLocalItemsOperation", NSString); printf("================================================================================\n\n"); @@ -398,18 +392,12 @@ static void print_entry(id k, id v, int ind) if(!([zoneCreated isEqualToString:@"yes"] && [zoneSubscribed isEqualToString:@"yes"])) { printf("CK Zone Created: %s\n", [[zoneCreated description] UTF8String]); - printf("CK Zone Created error: %s\n", [[zoneCreatedError description] UTF8String]); - printf("CK Zone Subscribed: %s\n", [[zoneSubscribed description] UTF8String]); - printf("CK Zone Subscription error: %s\n", [[zoneSubscribedError description] UTF8String]); printf("CK Zone initialize retry: %s\n", [[zoneInitializeScheduler description] UTF8String]); printf("\n"); } printf("Key state: %s\n", [keystate UTF8String]); - if(keyStateError != nil) { - printf("Key State Error: %s\n", [keyStateError UTF8String]); - } printf("Current TLK: %s\n", currentTLK != nil ? [currentTLK UTF8String] : [[NSString stringWithFormat:@"missing; pointer is %@", currentTLKPtr] UTF8String]); @@ -422,23 +410,20 @@ static void print_entry(id k, id v, int ind) printf("TLK shares: %s\n", [[tlkshares description] UTF8String]); + printf("Item syncing: %s\n", [[itemSyncEnabled description] UTF8String]); printf("Outgoing Queue counts: %s\n", [[oqe description] UTF8String]); printf("Incoming Queue counts: %s\n", [[iqe description] UTF8String]); printf("Key counts: %s\n", [[keys description] UTF8String]); - printf("latest manifest generation: %s\n", currentManifestGeneration == nil ? "null" : currentManifestGeneration.UTF8String); printf("Item counts (by key): %s\n", [[ckmirror description] UTF8String]); printf("Peer states: %s\n", [[devicestates description] UTF8String]); printf("zone change fetcher: %s\n", [[fetcher description] UTF8String]); - printf("zoneSetupOperation: %s\n", zoneSetupOperation == nil ? "never" : [zoneSetupOperation UTF8String]); - printf("keyStateOperation: %s\n", keyStateOperation == nil ? "never" : [keyStateOperation UTF8String]); printf("lastIncomingQueueOperation: %s\n", lastIncomingQueueOperation == nil ? "never" : [lastIncomingQueueOperation UTF8String]); printf("lastNewTLKOperation: %s\n", lastNewTLKOperation == nil ? "never" : [lastNewTLKOperation UTF8String]); printf("lastOutgoingQueueOperation: %s\n", lastOutgoingQueueOperation == nil ? "never" : [lastOutgoingQueueOperation UTF8String]); printf("lastProcessReceivedKeysOperation: %s\n", lastProcessReceivedKeysOperation == nil ? "never" : [lastProcessReceivedKeysOperation UTF8String]); printf("lastReencryptOutgoingItemsOperation: %s\n", lastReencryptOutgoingItemsOperation == nil ? "never" : [lastReencryptOutgoingItemsOperation UTF8String]); - printf("lastScanLocalItemsOperation: %s\n", lastScanLocalItemsOperation == nil ? "never" : [lastScanLocalItemsOperation UTF8String]); printf("Launch sequence:\n"); for (NSString *event in launchSequence) { @@ -476,7 +461,8 @@ static void print_entry(id k, id v, int ind) dispatch_semaphore_signal(sema); }]; - if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 65)) != 0) { + // The maximum device-side delay to start a fetch is 120s, so we must wait longer than that for a response. + if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 135)) != 0) { printf("\n\nError: timed out waiting for response\n"); return -1; } diff --git a/keychain/escrowrequest/EscrowRequestController.m b/keychain/escrowrequest/EscrowRequestController.m index 517279ee..57d6edac 100644 --- a/keychain/escrowrequest/EscrowRequestController.m +++ b/keychain/escrowrequest/EscrowRequestController.m @@ -57,6 +57,7 @@ OctagonState* const EscrowRequestStateWaitForUnlock = (OctagonState*)@"wait_for_ flags:(nonnull OctagonFlags *)flags pendingFlags:(nonnull id)pendingFlagHandler { + dispatch_assert_queue(self.queue); if([flags _onqueueContains:OctagonFlagEscrowRequestInformCloudServicesOperation]) { [flags _onqueueRemoveFlag:OctagonFlagEscrowRequestInformCloudServicesOperation]; return [[EscrowRequestInformCloudServicesOperation alloc] initWithIntendedState:EscrowRequestStateNothingToDo diff --git a/keychain/escrowrequest/EscrowRequestXPCProtocol.m b/keychain/escrowrequest/EscrowRequestXPCProtocol.m index 2bdaa7ae..a35ad32f 100644 --- a/keychain/escrowrequest/EscrowRequestXPCProtocol.m +++ b/keychain/escrowrequest/EscrowRequestXPCProtocol.m @@ -1,51 +1,27 @@ #import #import +#import #import "keychain/escrowrequest/EscrowRequestXPCProtocol.h" #import "utilities/debugging.h" NSXPCInterface* SecEscrowRequestSetupControlProtocol(NSXPCInterface* interface) { - static NSMutableSet *errClasses; - - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - errClasses = [NSMutableSet set]; - char *classes[] = { - "NSArray", - "NSData", - "NSDate", - "NSDictionary", - "NSError", - "NSNull", - "NSNumber", - "NSOrderedSet", - "NSSet", - "NSString", - "NSURL", - }; - - for (unsigned n = 0; n < sizeof(classes)/sizeof(classes[0]); n++) { - Class cls = objc_getClass(classes[n]); - if (cls) { - [errClasses addObject:cls]; - } - } - }); + NSSet* errClasses = [SecXPCHelper safeErrorClasses]; @try { [interface setClasses:errClasses forSelector:@selector(triggerEscrowUpdate:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(cachePrerecord:serializedPrerecord:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(fetchPrerecord:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errClasses forSelector:@selector(fetchRequestWaitingOnPasscode:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(fetchRequestStatuses:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(resetAllRequests:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errClasses forSelector:@selector(storePrerecordsInEscrow:) argumentIndex:1 ofReply:YES]; } @catch(NSException* e) { secerror("SecEscrowRequestSetupControlProtocol failed, continuing, but you might crash later: %@", e); -#if DEBUG @throw e; -#endif } return interface; diff --git a/keychain/headers/SecAccessControl.h b/keychain/headers/SecAccessControl.h index 5b66b242..5d54f581 100644 --- a/keychain/headers/SecAccessControl.h +++ b/keychain/headers/SecAccessControl.h @@ -94,7 +94,7 @@ typedef CF_OPTIONS(CFOptionFlags, SecAccessControlCreateFlags) { kSecAccessControlBiometryCurrentSet API_AVAILABLE(macos(10.13.4), ios(11.3)) = 1u << 3, kSecAccessControlTouchIDCurrentSet API_DEPRECATED_WITH_REPLACEMENT("kSecAccessControlBiometryCurrentSet", macos(10.12.1, 10.13.4), ios(9.0, 11.3)) = 1u << 3, kSecAccessControlDevicePasscode API_AVAILABLE(macos(10.11), ios(9.0)) = 1u << 4, - kSecAccessControlWatch API_AVAILABLE(macos(10.15), ios(NA), iosmac(13.0)) = 1u << 5, + kSecAccessControlWatch API_AVAILABLE(macos(10.15), ios(NA), macCatalyst(13.0)) = 1u << 5, kSecAccessControlOr API_AVAILABLE(macos(10.12.1), ios(9.0)) = 1u << 14, kSecAccessControlAnd API_AVAILABLE(macos(10.12.1), ios(9.0)) = 1u << 15, kSecAccessControlPrivateKeyUsage API_AVAILABLE(macos(10.12.1), ios(9.0)) = 1u << 30, diff --git a/keychain/headers/SecIdentityPriv.h b/keychain/headers/SecIdentityPriv.h index 99a62abb..2a54502e 100644 --- a/keychain/headers/SecIdentityPriv.h +++ b/keychain/headers/SecIdentityPriv.h @@ -51,91 +51,6 @@ SecIdentityRef SecIdentityCreate( //__OSX_AVAILABLE_STARTING(__MAC_10_3, __SEC_IPHONE_UNKNOWN); #if SEC_OS_OSX -/*! - @function SecIdentityCompare - @abstract Compares two SecIdentityRef instances for equality. - @param identity1 An identity reference. - @param identity2 An identity reference. - @param compareOptions A value containing option flags. Currently there are no compare options, so 0 should be passed for this parameter. - @result An enumerated value of type CFComparisonResult. See CFBase.h. - @discussion Two identities are considered equal if they contain identical certificate and private key components. - @deprecated in Mac OS X 10.5 and later; the CFEqual function should be used instead (CFBase.h). - */ -CFComparisonResult SecIdentityCompare( - SecIdentityRef identity1, - SecIdentityRef identity2, - CFOptionFlags compareOptions) - DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; - -/*! - @function SecIdentityFindPreferenceItem - @abstract Returns an identity preference item, given an identity string. - @param keychainOrArray A reference to an array of keychains to search, a single keychain, or NULL to search the user's default keychain search list. - @param idString A string containing a URI, hostname, or email (RFC822) address. - @param itemRef On return, a reference to the keychain item which was found. The caller is responsible for releasing this reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion An identity preference item maps a particular identity to a string, such as a URI or email address. It specifies that this identity should be preferred in transactions which match the provided string. - @deprecated in Mac OS X 10.7 and later; use SecIdentityCopyPreferred() instead (SecIdentity.h) - - WARNING: This function is based on an implementation detail and will go away - in a future release; its use should be avoided at all costs. It does not - provide a way to find a preference item based on key usage, and it can only - find preferences which are stored as keychain items, so it may fail to find - the item you expect. Please use the public API functions to manipulate - identity preferences. -*/ -OSStatus SecIdentityFindPreferenceItem( - CFTypeRef keychainOrArray, - CFStringRef idString, - SecKeychainItemRef *itemRef) - API_DEPRECATED_WITH_REPLACEMENT("SecIdentityCopyPreferred", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); - -/*! - @function SecIdentityAddPreferenceItem - @abstract Adds a new identity preference item to the specified keychain. - @param keychainRef A reference to the keychain in which to store the preference item. Pass NULL to specify the user's default keychain. - @param identityRef An identity reference. - @param idString A string containing a URI, hostname, or email (RFC822) address. - @param itemRef On return, a reference to the new keychain item. The caller is responsible for releasing this reference. Pass NULL if the reference is not needed. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion An identity preference item maps a particular identity to a string, such as a URI or email address. It specifies that this identity should be preferred in transactions which match the provided string. - @deprecated in Mac OS X 10.5; use SecIdentitySetPreference() instead (SecIdentity.h). -*/ -OSStatus SecIdentityAddPreferenceItem( - SecKeychainRef keychainRef, - SecIdentityRef identityRef, - CFStringRef idString, - SecKeychainItemRef *itemRef) - API_DEPRECATED_WITH_REPLACEMENT("SecIdentitySetPreference", macos(10.0, 10.5)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); - -/*! - @function SecIdentityUpdatePreferenceItem - @abstract Given an existing identity preference keychain item, update it with the provided identity. - @param itemRef An identity preference keychain item, as returned by SecIdentityFindPreferenceItem or SecIdentityAddPreferenceItem. - @param identityRef An identity reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is used to update an existing preference item when a different identity is preferred. - @deprecated in Mac OS X 10.5; use SecIdentitySetPreference() instead (SecIdentity.h). -*/ -OSStatus SecIdentityUpdatePreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef identityRef) - API_DEPRECATED_WITH_REPLACEMENT("SecIdentitySetPreference", macos(10.0, 10.5)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); - -/*! - @function SecIdentityCopyFromPreferenceItem - @abstract Given an existing identity preference keychain item, obtain a SecIdentityRef for the identity it specifies. - @param itemRef An identity preference keychain item, as returned by SecIdentityFindPreferenceItem or SecIdentityAddPreferenceItem. - @param identityRef On return, an identity reference. The caller is responsible for releasing this reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is used to obtain a SecIdentityRef from an existing preference item. - @deprecated in Mac OS X 10.5; use SecIdentityCopyPreference() instead (SecIdentity.h). -*/ -OSStatus SecIdentityCopyFromPreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef *identityRef) - API_DEPRECATED_WITH_REPLACEMENT("SecIdentityCopyPreference", macos(10.0, 10.5)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); - /*! @function ConvertArrayToKeyUsage @abstract Given an array of key usages defined in SecItem.h return the equivalent CSSM_KEYUSE diff --git a/keychain/headers/SecImportExport.h b/keychain/headers/SecImportExport.h index c6c91c6a..ba56a792 100644 --- a/keychain/headers/SecImportExport.h +++ b/keychain/headers/SecImportExport.h @@ -149,7 +149,7 @@ typedef CF_OPTIONS(uint32_t, SecKeyImportExportFlags) /* * Parameters specific to SecKeyRefs. */ -typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) +typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) { /* for import and export */ uint32_t version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */ @@ -166,10 +166,10 @@ typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) CSSM_KEYUSE keyUsage; /* CSSM_KEYUSE_DECRYPT, CSSM_KEYUSE_SIGN, * etc. */ CSSM_KEYATTR_FLAGS keyAttributes; /* CSSM_KEYATTR_PERMANENT, etc. */ -} SecKeyImportExportParameters API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +} SecKeyImportExportParameters API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); -typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) +typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst) { /* for import and export */ uint32_t version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */ @@ -194,7 +194,7 @@ typedef struct API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac) * - kSecAttrIsSensitive for private keys * - kSecAttrIsExtractable by default */ -} SecItemImportExportKeyParameters API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +} SecItemImportExportKeyParameters API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * SecKeychainItemExport() @@ -254,7 +254,7 @@ OSStatus SecKeychainItemExport( SecItemImportExportFlags flags, /* kSecItemPemArmour, etc. */ const SecKeyImportExportParameters * __nullable keyParams, /* optional */ CFDataRef * __nonnull CF_RETURNS_RETAINED exportedData) /* external representation returned here */ - API_DEPRECATED_WITH_REPLACEMENT("SecItemExport", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecItemExport", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * SecItemExport() @@ -472,7 +472,7 @@ OSStatus SecKeychainItemImport( const SecKeyImportExportParameters * __nullable keyParams, /* optional */ SecKeychainRef __nullable importKeychain, /* optional */ CFArrayRef * __nullable CF_RETURNS_RETAINED outItems) /* optional */ - API_DEPRECATED_WITH_REPLACEMENT("SecItemImport", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecItemImport", macos(10.0, 10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /* * SecItemImport() diff --git a/keychain/headers/SecImportExportPriv.h b/keychain/headers/SecImportExportPriv.h index 6d43101f..c70c3958 100644 --- a/keychain/headers/SecImportExportPriv.h +++ b/keychain/headers/SecImportExportPriv.h @@ -10,7 +10,7 @@ CF_IMPLICIT_BRIDGING_ENABLED #if TARGET_OS_OSX OSStatus SecPKCS12Import_ios(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef * __nonnull CF_RETURNS_RETAINED items) - SPI_AVAILABLE(macos(10.15), iosmac(13.0)) API_UNAVAILABLE(ios, watchos, tvos); + SPI_AVAILABLE(macos(10.15), macCatalyst(13.0)) API_UNAVAILABLE(ios, watchos, tvos); #endif CF_IMPLICIT_BRIDGING_DISABLED diff --git a/keychain/headers/SecItem.h b/keychain/headers/SecItem.h index baef2e98..03a0d784 100644 --- a/keychain/headers/SecItem.h +++ b/keychain/headers/SecItem.h @@ -1026,12 +1026,12 @@ extern const CFStringRef kSecValuePersistentRef */ extern const CFStringRef kSecUseItemList API_AVAILABLE(macos(10.6)) - API_DEPRECATED("Not implemented on this platform", ios(2.0, 12.0), tvos(9.0, 12.0), watchos(1.0, 5.0)) - API_UNAVAILABLE(bridgeos, iosmac); + API_DEPRECATED("Not implemented on this platform", ios(2.0, 12.0), tvos(9.0, 12.0), watchos(1.0, 5.0), macCatalyst(13.0, 13.0)) + API_UNAVAILABLE(bridgeos); extern const CFStringRef kSecUseKeychain API_AVAILABLE(macos(10.7), ios(NA), bridgeos(NA)); extern const CFStringRef kSecUseOperationPrompt - API_AVAILABLE(macos(10.10), ios(8.0)); + API_DEPRECATED("Use kSecUseAuthenticationContext and set LAContext.localizedReason property", macos(10.10, 10.16), ios(8.0, 14.0)); extern const CFStringRef kSecUseNoAuthenticationUI API_DEPRECATED("Use kSecUseAuthenticationUI instead.", macos(10.10, 10.11), ios(8.0, 9.0)); extern const CFStringRef kSecUseAuthenticationUI @@ -1057,9 +1057,9 @@ extern const CFStringRef kSecUseDataProtectionKeychain only with SecItemCopyMatching. */ extern const CFStringRef kSecUseAuthenticationUIAllow - API_AVAILABLE(macos(10.11), ios(9.0)); + API_DEPRECATED("Instead of kSecUseAuthenticationUI, use kSecUseAuthenticationContext and set LAContext.interactionNotAllowed property", macos(10.11, 10.16), ios(9.0, 14.0)); extern const CFStringRef kSecUseAuthenticationUIFail - API_AVAILABLE(macos(10.11), ios(9.0)); + API_DEPRECATED("Instead of kSecUseAuthenticationUI, use kSecUseAuthenticationContext and set LAContext.interactionNotAllowed property", macos(10.11, 10.16), ios(9.0, 14.0)); extern const CFStringRef kSecUseAuthenticationUISkip API_AVAILABLE(macos(10.11), ios(9.0)); diff --git a/keychain/headers/SecItemPriv.h b/keychain/headers/SecItemPriv.h index c458816d..9720d12e 100644 --- a/keychain/headers/SecItemPriv.h +++ b/keychain/headers/SecItemPriv.h @@ -305,6 +305,19 @@ extern const CFStringRef kSecAttrPCSPlaintextPublicKey extern const CFStringRef kSecAttrPCSPlaintextPublicIdentity __OSX_AVAILABLE(10.13) __IOS_AVAILABLE(11.0) __TVOS_AVAILABLE(11.0) __WATCHOS_AVAILABLE(4.0); +extern const CFStringRef kSecDataInetExtraNotes +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); +extern const CFStringRef kSecDataInetExtraHistory +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); +extern const CFStringRef kSecDataInetExtraClientDefined0 +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); +extern const CFStringRef kSecDataInetExtraClientDefined1 +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); +extern const CFStringRef kSecDataInetExtraClientDefined2 +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); +extern const CFStringRef kSecDataInetExtraClientDefined3 +__OSX_AVAILABLE(10.16) __IOS_AVAILABLE(14.0) __TVOS_AVAILABLE(14.0) __WATCHOS_AVAILABLE(7.0); + // ObjectID of item stored on the token. Token-type specific BLOB. // For kSecAttrTokenIDSecureEnclave and kSecAttrTokenIDAppleKeyStore, ObjectID is libaks's blob representation of encoded key. extern const CFStringRef kSecAttrTokenOID @@ -433,7 +446,7 @@ extern const CFStringRef kSecUseCallerName extern const CFStringRef kSecUseTokenRawItems __OSX_AVAILABLE(10.13) __IOS_AVAILABLE(11.0) __TVOS_AVAILABLE(11.0) __WATCHOS_AVAILABLE(4.0); extern const CFStringRef kSecUseCertificatesWithMatchIssuers - __OSX_AVAILABLE(10.14) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); + __OSX_AVAILABLE(10.14) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, macCatalyst); extern const CFStringRef kSOSInternalAccessGroup __OSX_AVAILABLE(10.9) __IOS_AVAILABLE(7.0) __TVOS_AVAILABLE(9.3) __WATCHOS_AVAILABLE(2.3); @@ -455,24 +468,6 @@ extern const CFStringRef kSecAttrTokenIDAppleKeyStore extern const CFStringRef kSecNetworkExtensionAccessGroupSuffix; -/*! - @function SecItemCopyDisplayNames - @abstract Returns an array containing unique display names for each of the - certificates, keys, identities, or passwords in the provided items - array. - @param items An array containing items of type SecKeychainItemRef, - SecKeyRef, SecCertificateRef, or SecIdentityRef. All items in the - array should be of the same type. - @param displayNames On return, an array of CFString references containing - unique names for the supplied items. You are responsible for releasing - this array reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Use this function to obtain item names which are suitable for - display in a menu or list view. The returned names are guaranteed to - be unique across the set of provided items. -*/ -OSStatus SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames); - /*! @function SecItemDeleteAll @abstract Removes all items from the keychain. @@ -526,6 +521,7 @@ void SecItemFetchCurrentItemAcrossAllDevices(CFStringRef accessGroup, @function SecItemVerifyBackupIntegrity @abstract Verifies the presence and integrity of all key material required to restore a backup of the keychain. + @discussion This function performs a synchronous call to securityd, be prepared to wait for it to scan the keychain. @param lightweight Only verify the item keys wrapped by backup keys instead of the default rigorous pass. This mode can be run in any security class. @@ -601,8 +597,7 @@ bool _SecSystemKeychainTransfer(CFErrorRef *error); bool _SecSyncDeleteUserViews(uid_t uid, CFErrorRef *error); - -OSStatus SecItemUpdateTokenItems(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes); +OSStatus SecItemUpdateTokenItemsForAccessGroups(CFTypeRef tokenID, CFArrayRef accessGroups, CFArrayRef tokenItemsAttributes); #if SEC_OS_OSX CFTypeRef SecItemCreateFromAttributeDictionary_osx(CFDictionaryRef refAttributes); @@ -695,6 +690,17 @@ __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_NA); extern const CFStringRef kSecAttrTokenIDSecureElement SPI_AVAILABLE(ios(10.13)); +/*! + @function SecItemDeleteKeychainItemsForAppClip + @abstract Remove all keychain items of specified App Clip's application identifier + @discussion At uninstallation time an App Clip should not leave behind any data. This function deletes any keychain items it might have had. + @param applicationIdentifier Name of the App Clip application identifier which is getting uninstalled. + @result Returns errSecSuccess if zero or more items were successfully deleted, otherwise errSecInternal + */ +OSStatus +SecItemDeleteKeychainItemsForAppClip(CFStringRef applicationIdentifier) +SPI_AVAILABLE(ios(10.14)); + __END_DECLS #endif /* !_SECURITY_SECITEMPRIV_H_ */ diff --git a/keychain/headers/SecKey.h b/keychain/headers/SecKey.h index 9b0a67b0..a905732c 100644 --- a/keychain/headers/SecKey.h +++ b/keychain/headers/SecKey.h @@ -915,19 +915,19 @@ __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AV RSA signature with PKCS#1 padding, input data must be SHA-512 generated digest. @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1 - RSA signature with PKCS#1 padding, SHA-1 digest is generated from input data of any size. + RSA signature with PKCS#1 padding, SHA-1 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224 - RSA signature with PKCS#1 padding, SHA-224 digest is generated from input data of any size. + RSA signature with PKCS#1 padding, SHA-224 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256 - RSA signature with PKCS#1 padding, SHA-256 digest is generated from input data of any size. + RSA signature with PKCS#1 padding, SHA-256 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384 - RSA signature with PKCS#1 padding, SHA-384 digest is generated from input data of any size. + RSA signature with PKCS#1 padding, SHA-384 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512 - RSA signature with PKCS#1 padding, SHA-512 digest is generated from input data of any size. + RSA signature with PKCS#1 padding, SHA-512 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSASignatureDigestPSSSHA1 RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, input data must be SHA-1 generated digest. @@ -950,60 +950,60 @@ __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AV PSS padding is calculated using MGF1 with SHA512 and saltLength parameter is set to 64 (SHA-512 output size). @constant kSecKeyAlgorithmRSASignatureMessagePSSSHA1 - RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-1 digest is generated from input data of any size. + RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-1 digest is generated by called function automatically from input data of any size. PSS padding is calculated using MGF1 with SHA1 and saltLength parameter is set to 20 (SHA-1 output size). @constant kSecKeyAlgorithmRSASignatureMessagePSSSHA224 - RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-224 digest is generated from input data of any size. + RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-224 digest is generated by called function automatically from input data of any size. PSS padding is calculated using MGF1 with SHA224 and saltLength parameter is set to 28 (SHA-224 output size). @constant kSecKeyAlgorithmRSASignatureMessagePSSSHA256 - RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-256 digest is generated from input data of any size. + RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-256 digest is generated by called function automatically from input data of any size. PSS padding is calculated using MGF1 with SHA256 and saltLength parameter is set to 32 (SHA-256 output size). @constant kSecKeyAlgorithmRSASignatureMessagePSSSHA384 - RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-384 digest is generated from input data of any size. + RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-384 digest is generated by called function automatically from input data of any size. PSS padding is calculated using MGF1 with SHA384 and saltLength parameter is set to 48 (SHA-384 output size). @constant kSecKeyAlgorithmRSASignatureMessagePSSSHA512 - RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-512 digest is generated from input data of any size. + RSA signature with RSASSA-PSS padding according to PKCS#1 v2.1, SHA-512 digest is generated by called function automatically from input data of any size. PSS padding is calculated using MGF1 with SHA512 and saltLength parameter is set to 64 (SHA-512 output size). @constant kSecKeyAlgorithmECDSASignatureRFC4754 - ECDSA algorithm, signature is concatenated r and s, big endian, data is message digest. + ECDSA algorithm, signature is concatenated r and s, big endian, input data must be message digest generated by some hash function. @constant kSecKeyAlgorithmECDSASignatureDigestX962 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest. + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest generated by some hash functions. @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest created by SHA1 algorithm. + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest created by SHA1 algorithm. - @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest created by SHA224 algorithm. + @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA224 + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest created by SHA224 algorithm. - @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest created by SHA256 algorithm. + @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA256 + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest created by SHA256 algorithm. - @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest created by SHA384 algorithm. + @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA384 + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest created by SHA384 algorithm. - @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest created by SHA512 algorithm. + @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA512 + ECDSA algorithm, signature is in DER x9.62 encoding, input data must be message digest created by SHA512 algorithm. @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA1 - ECDSA algorithm, signature is in DER x9.62 encoding, SHA-1 digest is generated from input data of any size. + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-1 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA224 - ECDSA algorithm, signature is in DER x9.62 encoding, SHA-224 digest is generated from input data of any size. + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-224 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA256 - ECDSA algorithm, signature is in DER x9.62 encoding, SHA-256 digest is generated from input data of any size. + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-256 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA384 - ECDSA algorithm, signature is in DER x9.62 encoding, SHA-384 digest is generated from input data of any size. + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-384 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA512 - ECDSA algorithm, signature is in DER x9.62 encoding, SHA-512 digest is generated from input data of any size. + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-512 digest is generated by called function automatically from input data of any size. @constant kSecKeyAlgorithmRSAEncryptionRaw Raw RSA encryption or decryption, size of data must match RSA key modulus size. Note that direct diff --git a/keychain/headers/SecKeyPriv.h b/keychain/headers/SecKeyPriv.h index 1f22315a..06eaa37c 100644 --- a/keychain/headers/SecKeyPriv.h +++ b/keychain/headers/SecKeyPriv.h @@ -357,7 +357,7 @@ SPI_AVAILABLE(macos(10.8), ios(9.0)); For compatibility, your code should migrate to use SecKeyGetAlgorithmId instead. */ CFIndex SecKeyGetAlgorithmID(SecKeyRef key) -API_DEPRECATED_WITH_REPLACEMENT("SecKeyGetAlgorithmId", ios(5.0, 9.0)) API_UNAVAILABLE(iosmac); +API_DEPRECATED_WITH_REPLACEMENT("SecKeyGetAlgorithmId", ios(5.0, 9.0)) API_UNAVAILABLE(macCatalyst); #endif // TARGET_OS_IPHONE #if TARGET_OS_OSX @@ -372,7 +372,7 @@ API_DEPRECATED_WITH_REPLACEMENT("SecKeyGetAlgorithmId", ios(5.0, 9.0)) API_UNAVA had different arguments and a different return value. Use SecKeyGetAlgorithmId instead. */ OSStatus SecKeyGetAlgorithmID(SecKeyRef key, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) -API_DEPRECATED_WITH_REPLACEMENT("SecKeyGetAlgorithmId", macos(10.2, 10.8)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); +API_DEPRECATED_WITH_REPLACEMENT("SecKeyGetAlgorithmId", macos(10.2, 10.8)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, macCatalyst); #endif #if !SEC_OS_OSX @@ -473,7 +473,7 @@ OSStatus SecKeyImportPair( SecAccessRef initialAccess, SecKeyRef* publicKey, SecKeyRef* privateKey) - API_DEPRECATED_WITH_REPLACEMENT("SecItemImport", macos(10.0, 10.5)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecItemImport", macos(10.0, 10.5)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); /*! @function SecKeyCreate @@ -504,7 +504,7 @@ SecKeyRef SecKeyCreate(CFAllocatorRef allocator, */ OSStatus SecKeyCreateWithCSSMKey(const CSSM_KEY *key, SecKeyRef* keyRef) API_DEPRECATED("CSSM_KEY is deprecated", macos(10.11, 10.14)); -// Alias macOS versions of this deprecated SPI to unique macOS names. Undecorated names are used for iosmac. +// Alias macOS versions of this deprecated SPI to unique macOS names. Undecorated names are used for macCatalyst. #define SecKeyRawSign SecKeyRawSign_macOS #define SecKeyRawVerify SecKeyRawVerify_macOS @@ -809,6 +809,10 @@ typedef CF_ENUM(uint32_t, SecKeyAttestationKeyType) 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, kSecKeyAttestationKeyTypeSecureElement SPI_AVAILABLE(ios(13.0)) = 4, + kSecKeyAttestationKeyTypeOIKCommitted SPI_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0)) = 5, + kSecKeyAttestationKeyTypeOIKProposed SPI_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0)) = 6, + kSecKeyAttestationKeyTypeDAKCommitted SPI_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0)) = 7, + kSecKeyAttestationKeyTypeDAKProposed SPI_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0)) = 8, } SPI_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)); /*! diff --git a/keychain/headers/SecSharedCredential.h b/keychain/headers/SecSharedCredential.h index 21a89444..0d047b70 100644 --- a/keychain/headers/SecSharedCredential.h +++ b/keychain/headers/SecSharedCredential.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2014-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -52,7 +52,9 @@ CF_IMPLICIT_BRIDGING_ENABLED shared password. You use this key to get a value of type CFStringRef that contains a password. */ -extern const CFStringRef kSecSharedPassword API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(macos, iosmac, tvos, watchos); +extern const CFStringRef kSecSharedPassword + API_AVAILABLE(ios(8.0), macCatalyst(14.0), macos(10.16)) + API_UNAVAILABLE(tvos, watchos); /*! @function SecAddSharedWebCredential @@ -66,7 +68,9 @@ extern const CFStringRef kSecSharedPassword API_AVAILABLE(ios(8.0)) API_UNAVAILA Note: since a request involving shared web credentials may potentially require user interaction or other verification to be approved, this function is dispatched asynchronously; your code provides a completion handler that will be called once the results (if any) are available. */ void SecAddSharedWebCredential(CFStringRef fqdn, CFStringRef account, CFStringRef __nullable password, - void (^completionHandler)(CFErrorRef __nullable error)) API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(macos, iosmac, tvos, watchos); + void (^completionHandler)(CFErrorRef __nullable error)) + API_AVAILABLE(ios(8.0), macCatalyst(14.0), macos(10.16)) + API_UNAVAILABLE(tvos, watchos); /*! @function SecRequestSharedWebCredential @@ -87,7 +91,10 @@ void SecAddSharedWebCredential(CFStringRef fqdn, CFStringRef account, CFStringRe Note: since a request involving shared web credentials may potentially require user interaction or other verification to be approved, this function is dispatched asynchronously; your code provides a completion handler that will be called once the results (if any) are available. */ void SecRequestSharedWebCredential(CFStringRef __nullable fqdn, CFStringRef __nullable account, - void (^completionHandler)(CFArrayRef __nullable credentials, CFErrorRef __nullable error)) API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(macos, iosmac, tvos, watchos); + void (^completionHandler)(CFArrayRef __nullable credentials, CFErrorRef __nullable error)) + API_DEPRECATED("Use ASAuthorizationController to make an ASAuthorizationPasswordRequest (AuthenticationServices framework)", + ios(8.0,14.0), macCatalyst(14.0,14.0), macos(10.16,10.16)) + API_UNAVAILABLE(tvos, watchos); /*! @function SecCreateSharedWebCredentialPassword @@ -95,7 +102,9 @@ void SecRequestSharedWebCredential(CFStringRef __nullable fqdn, CFStringRef __nu @return CFStringRef password in the form xxx-xxx-xxx-xxx where x is taken from the sets "abcdefghkmnopqrstuvwxy", "ABCDEFGHJKLMNPQRSTUVWXYZ", "3456789" with at least one character from each set being present. */ __nullable -CFStringRef SecCreateSharedWebCredentialPassword(void) API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(macos, iosmac, tvos, watchos); +CFStringRef SecCreateSharedWebCredentialPassword(void) + API_AVAILABLE(ios(8.0), macCatalyst(14.0), macos(10.16)) + API_UNAVAILABLE(tvos, watchos); #endif /* __BLOCKS__ */ diff --git a/keychain/ot/CuttlefishXPCWrapper.m b/keychain/ot/CuttlefishXPCWrapper.m index 868f2bd8..731be0ed 100644 --- a/keychain/ot/CuttlefishXPCWrapper.m +++ b/keychain/ot/CuttlefishXPCWrapper.m @@ -310,8 +310,9 @@ enum {NUM_RETRIES = 5}; deviceName:(nullable NSString*)deviceName serialNumber:(NSString *)serialNumber osVersion:(NSString *)osVersion - policyVersion:(nullable TPPolicy *)policyVersion + policyVersion:(nullable TPPolicyVersion *)policyVersion policySecrets:(nullable NSDictionary *)policySecrets + syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews signingPrivKeyPersistentRef:(nullable NSData *)spkPr encPrivKeyPersistentRef:(nullable NSData*)epkPr reply:(void (^)(NSString * _Nullable peerID, @@ -319,8 +320,7 @@ enum {NUM_RETRIES = 5}; NSData * _Nullable permanentInfoSig, NSData * _Nullable stableInfo, NSData * _Nullable stableInfoSig, - NSSet* syncingViews, - TPPolicy* _Nullable syncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply { __block int i = 0; @@ -333,7 +333,7 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, nil, nil, nil, nil, nil, nil, error); + reply(nil, nil, nil, nil, nil, nil, error); } ++i; }] prepareWithContainer:container @@ -348,6 +348,7 @@ enum {NUM_RETRIES = 5}; osVersion:osVersion policyVersion:policyVersion policySecrets:policySecrets + syncUserControllableViews:syncUserControllableViews signingPrivKeyPersistentRef:spkPr encPrivKeyPersistentRef:epkPr reply:reply]; @@ -361,6 +362,7 @@ enum {NUM_RETRIES = 5}; preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply { __block int i = 0; @@ -373,7 +375,7 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, nil, error); + reply(nil, nil, nil, error); } ++i; }] establishWithContainer:container context:context ckksKeys:viewKeySets tlkShares:tlkShares preapprovedKeys:preapprovedKeys reply:reply]; @@ -414,8 +416,8 @@ enum {NUM_RETRIES = 5}; context:(nonnull NSString *)context bottleID:(nonnull NSString *)bottleID reply:(nonnull void (^)(NSString * _Nullable, - NSSet* _Nullable peerSyncingViewList, - TPPolicy * _Nullable peerSyncingPolicy, + TPSyncingPolicy* _Nullable peerSyncingPolicy, + BOOL refetchWasNeeded, NSError * _Nullable))reply { __block int i = 0; __block bool retry; @@ -427,7 +429,7 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, nil, nil, error); + reply(nil, nil, false, error); } ++i; }] preflightVouchWithBottleWithContainer:container @@ -471,8 +473,7 @@ enum {NUM_RETRIES = 5}; recoveryKey:(NSString*)recoveryKey salt:(NSString*)salt reply:(nonnull void (^)(NSString * _Nullable, - NSSet* _Nullable peerSyncingViewList, - TPPolicy * _Nullable peerSyncingPolicy, + TPSyncingPolicy* _Nullable peerSyncingPolicy, NSError * _Nullable))reply { __block int i = 0; __block bool retry; @@ -484,7 +485,7 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, nil, nil, error); + reply(nil, nil, error); } ++i; }] preflightVouchWithRecoveryKeyWithContainer:container @@ -527,11 +528,10 @@ enum {NUM_RETRIES = 5}; voucherSig:(NSData *)voucherSig ckksKeys:(NSArray *)viewKeySets tlkShares:(NSArray *)tlkShares - preapprovedKeys:(NSArray *)preapprovedKeys + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, - NSSet* _Nullable viewSet, - TPPolicy* _Nullable syncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply { __block int i = 0; @@ -544,7 +544,7 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, nil, nil, nil, error); + reply(nil, nil, nil, error); } ++i; }] joinWithContainer:container context:context voucherData:voucherData voucherSig:voucherSig ckksKeys:viewKeySets tlkShares:tlkShares preapprovedKeys:preapprovedKeys reply:reply]; @@ -553,6 +553,7 @@ enum {NUM_RETRIES = 5}; - (void)preflightPreapprovedJoinWithContainer:(NSString *)container context:(NSString *)context + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(BOOL launchOkay, NSError * _Nullable error))reply { @@ -569,7 +570,7 @@ enum {NUM_RETRIES = 5}; reply(NO, error); } ++i; - }] preflightPreapprovedJoinWithContainer:container context:context reply:reply]; + }] preflightPreapprovedJoinWithContainer:container context:context preapprovedKeys:preapprovedKeys reply:reply]; } while (retry); } @@ -577,11 +578,10 @@ enum {NUM_RETRIES = 5}; context:(NSString *)context ckksKeys:(NSArray *)ckksKeys tlkShares:(NSArray *)tlkShares - preapprovedKeys:(NSArray *)preapprovedKeys + preapprovedKeys:(nullable NSArray *)preapprovedKeys reply:(void (^)(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, - NSSet* _Nullable syncingViewList, - TPPolicy* _Nullable syncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error))reply { __block int i = 0; @@ -594,10 +594,15 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, nil, nil, nil, error); + reply(nil, nil, nil, error); } ++i; - }] attemptPreapprovedJoinWithContainer:container context:context ckksKeys:ckksKeys tlkShares:tlkShares preapprovedKeys:preapprovedKeys reply:reply]; + }] attemptPreapprovedJoinWithContainer:container + context:context + ckksKeys:ckksKeys + tlkShares:tlkShares + preapprovedKeys:preapprovedKeys + reply:reply]; } while (retry); } @@ -608,7 +613,8 @@ enum {NUM_RETRIES = 5}; osVersion:(nullable NSString *)osVersion policyVersion:(nullable NSNumber *)policyVersion policySecrets:(nullable NSDictionary *)policySecrets - reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, NSError * _Nullable error))reply + syncUserControllableViews:(nullable NSNumber *)syncUserControllableViews + reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, TPSyncingPolicy* _Nullable policy, NSError * _Nullable error))reply { __block int i = 0; __block bool retry; @@ -620,10 +626,18 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, error); + reply(nil, nil, error); } ++i; - }] updateWithContainer:container context:context deviceName:deviceName serialNumber:serialNumber osVersion:osVersion policyVersion:policyVersion policySecrets:policySecrets reply:reply]; + }] updateWithContainer:container + context:context + deviceName:deviceName + serialNumber:serialNumber + osVersion:osVersion + policyVersion:policyVersion + policySecrets:policySecrets + syncUserControllableViews:syncUserControllableViews + reply:reply]; } while (retry); } @@ -742,8 +756,9 @@ enum {NUM_RETRIES = 5}; - (void)fetchCurrentPolicyWithContainer:(NSString*)container context:(NSString*)context - reply:(void (^)(NSSet* _Nullable viewList, - TPPolicy * _Nullable policy, + modelIDOverride:(NSString* _Nullable)modelIDOverride + reply:(void (^)(TPSyncingPolicy* _Nullable syncingPolicy, + TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers, NSError * _Nullable error))reply { __block int i = 0; @@ -756,10 +771,12 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(nil, nil, error); + reply(nil, + TPPBPeerStableInfo_UserControllableViewStatus_UNKNOWN, + error); } ++i; - }] fetchCurrentPolicyWithContainer:container context:context reply:reply]; + }] fetchCurrentPolicyWithContainer:container context:context modelIDOverride:modelIDOverride reply:reply]; } while (retry); } @@ -813,7 +830,8 @@ enum {NUM_RETRIES = 5}; recoveryKey:(NSString *)recoveryKey salt:(NSString *)salt ckksKeys:(NSArray *)ckksKeys - reply:(void (^)(NSError* _Nullable error))reply + reply:(void (^)(NSArray* _Nullable keyHierarchyRecords, + NSError* _Nullable error))reply { __block int i = 0; __block bool retry; @@ -825,7 +843,7 @@ enum {NUM_RETRIES = 5}; retry = true; } else { secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); - reply(error); + reply(nil, error); } ++i; }] setRecoveryKeyWithContainer:container context:context recoveryKey:recoveryKey salt:salt ckksKeys:ckksKeys reply:reply]; @@ -920,4 +938,43 @@ enum {NUM_RETRIES = 5}; } +- (void)fetchViableEscrowRecordsWithContainer:(nonnull NSString *)container context:(nonnull NSString *)context forceFetch:(BOOL)forceFetch reply:(nonnull void (^)(NSArray * _Nullable, NSError * _Nullable))reply +{ + __block int i = 0; + __block bool retry; + do { + retry = false; + [[self.cuttlefishXPCConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *_Nonnull error) { + if (i < NUM_RETRIES && [self.class retryable:error]) { + secnotice("octagon", "retrying cuttlefish XPC, (%d, %@)", i, error); + retry = true; + } else { + secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); + reply(nil, error); + } + ++i; + }] fetchViableEscrowRecordsWithContainer:container context:context forceFetch:forceFetch reply:reply]; + } while (retry); +} + +- (void)removeEscrowCacheWithContainer:(nonnull NSString *)container context:(nonnull NSString *)context reply:(nonnull void (^)(NSError * _Nullable))reply { + __block int i = 0; + __block bool retry; + do { + retry = false; + [[self.cuttlefishXPCConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *_Nonnull error) { + if (i < NUM_RETRIES && [self.class retryable:error]) { + secnotice("octagon", "retrying cuttlefish XPC, (%d, %@)", i, error); + retry = true; + } else { + secerror("octagon: Can't talk with TrustedPeersHelper: %@", error); + reply(error); + } + ++i; + }] removeEscrowCacheWithContainer:container context:context reply:reply]; + } while (retry); +} + + + @end diff --git a/keychain/ot/OTClientStateMachine.m b/keychain/ot/OTClientStateMachine.m index 88f684f1..cbb6e8ad 100644 --- a/keychain/ot/OTClientStateMachine.m +++ b/keychain/ot/OTClientStateMachine.m @@ -286,7 +286,8 @@ NSDictionary* OctagonClientStateMap(void) { osVersion:nil policyVersion:nil policySecrets:nil - reply:^(TrustedPeersHelperPeerState* peerState, NSError* error) { + syncUserControllableViews:nil + reply:^(TrustedPeersHelperPeerState* peerState, TPSyncingPolicy* policy, NSError* error) { if(error) { secerror("OTCuttlefishContext: updating errored: %@", error); } else { diff --git a/keychain/ot/OTClientVoucherOperation.m b/keychain/ot/OTClientVoucherOperation.m index 6257c0d2..f7951b8d 100644 --- a/keychain/ot/OTClientVoucherOperation.m +++ b/keychain/ot/OTClientVoucherOperation.m @@ -77,7 +77,8 @@ WEAKIFY(self); // Acquire the CKKS TLKs to pass in - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.operationDependencies]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.operationDependencies + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"vouch-with-keys" diff --git a/keychain/ot/OTClique+Private.h b/keychain/ot/OTClique+Private.h new file mode 100644 index 00000000..298321dd --- /dev/null +++ b/keychain/ot/OTClique+Private.h @@ -0,0 +1,24 @@ + +#ifndef OTClique_Private_h +#define OTClique_Private_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OTClique(Private) + ++ (NSArray* _Nullable)fetchEscrowRecordsInternal:(OTConfigurationContext*)configurationContext + error:(NSError* __autoreleasing *)error; + ++ (BOOL)isCloudServicesAvailable; + +- (BOOL)resetAndEstablish:(CuttlefishResetReason)resetReason error:(NSError**)error; + +- (BOOL)establish:(NSError**)error; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* OTClique_Private_h */ diff --git a/keychain/ot/OTClique.h b/keychain/ot/OTClique.h index cfe080f1..eccb408a 100644 --- a/keychain/ot/OTClique.h +++ b/keychain/ot/OTClique.h @@ -25,6 +25,15 @@ #ifndef OTClique_h #define OTClique_h +#if __OBJC2__ + +#import +#import +#import +#import +#import +#import + typedef NS_ENUM(NSInteger, CliqueStatus) { CliqueStatusIn = 0, /*There is a clique and I am in it*/ CliqueStatusNotIn = 1, /*There is a clique and I am not in it - you should get a voucher to join or tell another peer to trust us*/ @@ -34,16 +43,6 @@ typedef NS_ENUM(NSInteger, CliqueStatus) { CliqueStatusError = -1 /*unable to determine circle status, inspect CFError to find out why */ }; -#import - -#if __OBJC2__ - -#import -#import -#import -#import -#import - typedef NS_ENUM(NSInteger, OTCDPStatus) { OTCDPStatusUnknown = 0, OTCDPStatusDisabled = 1, @@ -67,11 +66,12 @@ extern NSString* kSecEntitlementPrivateOctagonEscrow; @interface OTConfigurationContext : NSObject @property (nonatomic, copy) NSString* context; +@property (nonatomic, copy) NSString* containerName; @property (nonatomic, copy, nullable) NSString* dsid; @property (nonatomic, copy, nullable) NSString* altDSID; -@property (nonatomic, strong, nullable) SFSignInAnalytics* analytics; @property (nonatomic, copy, nullable) NSString* authenticationAppleID; @property (nonatomic, copy, nullable) NSString* passwordEquivalentToken; +@property (nonatomic) BOOL overrideEscrowCache; // Use this to inject your own OTControl object. It must be configured as synchronous. @property (nullable, strong) OTControl* otControl; @@ -129,11 +129,6 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; */ - (instancetype)initWithContextData:(OTConfigurationContext *)ctx; -/* - * Much like initWithContextData, but might fail. There are currently no failures possible. - */ -- (instancetype _Nullable)initWithContextData:(OTConfigurationContext *)ctx error:(NSError**)error __deprecated_msg("Use initWithContextData instead"); - /* * * @abstract Establish a new clique, reset protected data * Reset the clique @@ -247,7 +242,6 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; */ - (NSDictionary* _Nullable)peerDeviceNamesByPeerID:(NSError * __autoreleasing *)error; - /* * CDP bit handling */ @@ -258,11 +252,31 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; + (OTCDPStatus)getCDPStatus:(OTConfigurationContext*)arguments error:(NSError* __autoreleasing *)error; +/* + * User view handling + */ + +/* * + * @abstract Set the current status of user-controllable views. This is unavailable on TV and Watch, and will error. + * @param error, This will return an error if anything goes wrong + * @return success + */ +- (BOOL)setUserControllableViewsSyncStatus:(BOOL)enabled + error:(NSError* __autoreleasing *)error; + +/* * + * @abstract Fetch the current status of user-controllable views + * @param error, This will return an error if anything goes wrong + * @return status, The status of syncing. Note that in the success case, this can be NO while error remains empty. + */ +- (BOOL)fetchUserControllableViewsSyncingEnabled:(NSError* __autoreleasing *)error __attribute__((swift_error(nonnull_error))); + /* SOS glue */ - (BOOL)joinAfterRestore:(NSError * __autoreleasing *)error; -- (BOOL)safariPasswordSyncingEnabled:(NSError *__autoreleasing*)error; +- (BOOL)safariPasswordSyncingEnabled:(NSError *__autoreleasing*)error +API_DEPRECATED_WITH_REPLACEMENT("fetchUserControllableViewsSyncingEnabled",macos(10.15, 10.16), ios(13.0, 14.0), watchos(6.0, 7.0), tvos(13.0,14.0)); - (BOOL)isLastFriend:(NSError *__autoreleasing*)error; @@ -270,7 +284,9 @@ extern OTCliqueCDPContextType OTCliqueCDPContextTypeUpdatePasscode; - (NSArray* _Nullable)copyViewUnawarePeerInfo:(NSError *__autoreleasing*)error; -- (BOOL)viewSet:(NSSet*)enabledViews disabledViews:(NSSet*)disabledViews; +- (BOOL)viewSet:(NSSet*)enabledViews disabledViews:(NSSet*)disabledViews +API_DEPRECATED_WITH_REPLACEMENT("setUserControllableViewsSyncStatus",macos(10.15, 10.16), ios(13.0, 14.0), watchos(6.0, 7.0), tvos(13.0,14.0)); + - (BOOL)setUserCredentialsAndDSID:(NSString*)userLabel password:(NSData*)userPassword diff --git a/keychain/ot/OTClique.m b/keychain/ot/OTClique.m index fbf8e5da..41d426a6 100644 --- a/keychain/ot/OTClique.m +++ b/keychain/ot/OTClique.m @@ -27,6 +27,7 @@ #import #import "keychain/ot/OTClique.h" +#import "keychain/ot/OTClique+Private.h" #import "keychain/ot/OTConstants.h" #import "keychain/ot/OTDefines.h" #import "keychain/SigninMetrics/OctagonSignPosts.h" @@ -51,7 +52,7 @@ const NSString* kSecEntitlementPrivateOctagonEscrow = @"com.apple.private.octago #import "keychain/ot/categories/OctagonEscrowRecoverer.h" SOFT_LINK_FRAMEWORK(PrivateFrameworks, KeychainCircle); -SOFT_LINK_FRAMEWORK(PrivateFrameworks, CloudServices); +SOFT_LINK_OPTIONAL_FRAMEWORK(PrivateFrameworks, CloudServices); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wstrict-prototypes" @@ -124,6 +125,7 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { @implementation OTConfigurationContext + - (OTControl* _Nullable)makeOTControl:(NSError**)error { #if OCTAGON @@ -225,23 +227,17 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { [self.defaults removeObjectForKey:OTDefaultsOctagonEnable]; } -- (instancetype)initWithContextData:(OTConfigurationContext *)ctx error:(NSError * __autoreleasing *)error -{ - return [self initWithContextData:ctx]; -} - - (instancetype)initWithContextData:(OTConfigurationContext *)ctx { #if OCTAGON - self = [super init]; - if(self){ + if ((self = [super init])) { _ctx = [[OTConfigurationContext alloc]init]; _ctx.context = ctx.context ?: OTDefaultContext; _ctx.dsid = [ctx.dsid copy]; _ctx.altDSID = [ctx.altDSID copy]; - _ctx.analytics = ctx.analytics; _ctx.otControl = ctx.otControl; _ctx.ckksControl = ctx.ckksControl; + _ctx.overrideEscrowCache = ctx.overrideEscrowCache; self.defaults = [NSMutableDictionary dictionary]; } @@ -250,7 +246,8 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { NSAssert(false, @"OTClique is not implemented on this platform"); // make the build analyzer happy - self = [super init]; + if ((self = [super init])) { + } return self; #endif // OCTAGON } @@ -385,7 +382,7 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { secnotice("clique-newfriends", "makeNewFriends invoked using context: %@, dsid: %@", data.context, data.dsid); bool result = false; bool subTaskSuccess = false; - OctagonSignpost performEscrowRecoverySignpost = OctagonSignpostBegin(OctagonSignpostNameMakeNewFriends); + OctagonSignpost newFriendsSignpost = OctagonSignpostBegin(OctagonSignpostNameMakeNewFriends); OTClique* clique = [[OTClique alloc] initWithContextData:data]; @@ -398,7 +395,7 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { if(error) { *error = localError; } - OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); + OctagonSignpostEnd(newFriendsSignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); return nil; } else { secnotice("clique-newfriends", "Octagon account reset succeeded"); @@ -416,7 +413,7 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { } else { CFBridgingRelease(resetError); } - OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); + OctagonSignpostEnd(newFriendsSignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); return nil; } secnotice("clique-newfriends", "newFriendsWithContextData: reset the SOS circle"); @@ -426,7 +423,7 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { secnotice("clique-newfriends", "makeNewFriends complete"); subTaskSuccess = true; - OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); + OctagonSignpostEnd(newFriendsSignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess); return clique; @@ -437,11 +434,35 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { #endif } ++ (BOOL)isCloudServicesAvailable +{ +#if OCTAGON + if (isCloudServicesAvailable()) { + return YES; + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + secnotice("octagon", "CloudServices is unavailable on this platform"); + }); + return NO; +#else + return NO; +#endif +} + + (OTClique* _Nullable)performEscrowRecoveryWithContextData:(OTConfigurationContext*)data escrowArguments:(NSDictionary*)sbdRecoveryArguments error:(NSError**)error { #if OCTAGON + if ([OTClique isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; + } + OctagonSignpost performEscrowRecoverySignpost = OctagonSignpostBegin(OctagonSignpostNamePerformEscrowRecovery); bool subTaskSuccess = false; NSError* localError = nil; @@ -511,7 +532,7 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { secnotice("clique-recovery", "recovering from bottle: %@", bottleID); __block NSError* restoreBottleError = nil; - OctagonSignpost bottleRecoverySignPost = OctagonSignpostBegin(OctagonSignpostNamePerformBottleRecovery); + OctagonSignpost bottleRecoverySignPost = OctagonSignpostBegin(OctagonSignpostNamePerformOctagonJoin); //restore bottle! [control restore:OTCKContainerName contextID:data.context @@ -528,7 +549,7 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { }]; subTaskSuccess = (restoreBottleError == nil) ? true : false; - OctagonSignpostEnd(bottleRecoverySignPost, OctagonSignpostNamePerformBottleRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformBottleRecovery), (int)subTaskSuccess); + OctagonSignpostEnd(bottleRecoverySignPost, OctagonSignpostNamePerformOctagonJoin, OctagonSignpostNumber1(OctagonSignpostNamePerformOctagonJoin), (int)subTaskSuccess); if(restoreBottleError) { if(error){ @@ -553,6 +574,11 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { if(resetError) { secnotice("clique-recovery", "failed to reset octagon: %@", resetError); + if(error){ + *error = resetError; + } + OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNamePerformEscrowRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformEscrowRecovery), (int)subTaskSuccess); + return nil; } else{ secnotice("clique-recovery", "reset octagon succeeded"); } @@ -791,20 +817,9 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { if([OTClique platformSupportsSOS] && sosIdentifiers.count >0) { CFErrorRef removeFriendError = NULL; - NSData* analyticsData = nil; secnotice("clique-removefriends", "removing sos friends: %@", sosIdentifiers); - - if(self.ctx.analytics){ - NSError* encodingError = nil; - analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - } - - if(analyticsData) { - result = SOSCCRemovePeersFromCircleWithAnalytics((__bridge CFArrayRef)friendIdentifiers, (__bridge CFDataRef)analyticsData, &removeFriendError); - } else { - result = SOSCCRemovePeersFromCircle((__bridge CFArrayRef)friendIdentifiers, &removeFriendError); - } + result = SOSCCRemovePeersFromCircle((__bridge CFArrayRef)friendIdentifiers, &removeFriendError); if(removeFriendError) { secnotice("clique-removefriends", "removeFriendsInClique failed: unable to remove friends: %@", removeFriendError); @@ -879,21 +894,7 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { } if([OTClique platformSupportsSOS]) { - NSData* analyticsData = nil; - - if(self.ctx.analytics) { - NSError* encodingError = nil; - analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - if(!analyticsData){ - secnotice("clique-leaveClique", "leaveClique unable to archive analytics object: %@", encodingError); - } - } - - if(analyticsData) { - result &= SOSCCRemoveThisDeviceFromCircleWithAnalytics((__bridge CFDataRef)analyticsData, &removeThisDeviceError); - } else { - result &= SOSCCRemoveThisDeviceFromCircle(&removeThisDeviceError); - } + result &= SOSCCRemoveThisDeviceFromCircle(&removeThisDeviceError); if (error) { *error = (NSError*)CFBridgingRelease(removeThisDeviceError); } else { @@ -1013,6 +1014,11 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { } - (BOOL)safariPasswordSyncingEnabled:(NSError **)error +{ + return [self fetchUserControllableViewsSyncingEnabled:error]; +} + +- (BOOL)sosSafariPasswordSyncingEnabled:(NSError **)error { secnotice("clique-safari", "safariPasswordSyncingEnabled for context:%@, altdsid:%@", self.ctx.context, self.ctx.altDSID); OctagonSignpost safariSyncingEnabledSignPost = OctagonSignpostBegin(OctagonSignpostNameSafariPasswordSyncingEnabled); @@ -1046,6 +1052,158 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { } } +- (BOOL)setUserControllableViewsSyncStatus:(BOOL)enabled + error:(NSError* __autoreleasing *)error +{ + if([OTClique platformSupportsSOS]) { + // We either enable or disable this list of SOS views, taken from CDP. + NSSet* sosViews = [NSSet setWithObjects:(__bridge id)kSOSViewWiFi, + (__bridge id)kSOSViewAutofillPasswords, + (__bridge id)kSOSViewSafariCreditCards, + (__bridge id)kSOSViewOtherSyncable, + nil]; + + BOOL sosResult = NO; + if(enabled) { + sosResult = [self sosViewSet:sosViews disabledViews:[NSSet set]]; + } else { + sosResult = [self sosViewSet:[NSSet set] disabledViews:sosViews]; + } + + if(sosResult == NO) { + secnotice("clique-user-sync", "SOS view setting failed, but no error returned"); + if(error) { + *error = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain + code:kSOSErrorNotReady + userInfo:@{ + NSLocalizedDescriptionKey: @"SOS reported failure, but no error given" + }]; + } + + return NO; + } + } + + if(OctagonIsEnabled()) { + return [self setOctagonUserControllableViewsSyncEnabled:enabled + error:error]; + } + + return YES; +} + +- (BOOL)setOctagonUserControllableViewsSyncEnabled:(BOOL)enabled + error:(NSError* __autoreleasing *)error +{ +#if OCTAGON + OTControl* control = [self makeOTControl:error]; + if(!control) { + return NO; + } + + __block NSError* localError = nil; + + secnotice("clique-user-sync", "setting user-controllable-sync status to %@", enabled ? @"enabled" : @"paused"); + + [control setUserControllableViewsSyncStatus:self.ctx.containerName + contextID:self.ctx.context + enabled:enabled + reply:^(BOOL nowSyncing, NSError* _Nullable fetchError) { + if(fetchError) { + secnotice("clique-user-sync", "setting user-controllable-sync status errored: %@", fetchError); + localError = fetchError; + } else { + secnotice("clique-user-sync", "setting user-controllable-sync status succeeded, now : %@", nowSyncing ? @"enabled" : @"paused"); + } + }]; + + if(error && localError) { + *error = localError; + } + + return localError == nil; +#else + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:errSecUnimplemented + userInfo:@{NSLocalizedDescriptionKey: @"setOctagonUserControllableViewSync unimplemented on this platform"}]; + } + return NO; +#endif +} + +- (BOOL)fetchUserControllableViewsSyncingEnabled:(NSError* __autoreleasing *)error +{ + if(!OctagonIsEnabled() && ![OTClique platformSupportsSOS]) { + secnotice("clique-user-sync", "No syncing platforms enabled; views are not syncing"); + return NO; + } + + __block BOOL octagonSyncing = NO; +#if OCTAGON + if(OctagonIsEnabled()) { + OTControl* control = [self makeOTControl:error]; + if(!control) { + return NO; + } + + __block NSError* localError = nil; + [control fetchUserControllableViewsSyncStatus:self.ctx.containerName + contextID:self.ctx.context + reply:^(BOOL nowSyncing, NSError* _Nullable fetchError) { + if(fetchError) { + secnotice("clique-user-sync", "fetching user-controllable-sync status errored: %@", fetchError); + } else { + secnotice("clique-user-sync", "fetched user-controllable-sync status as : %@", nowSyncing ? @"enabled" : @"paused"); + } + octagonSyncing = nowSyncing; + localError = fetchError; + }]; + + if(localError) { + if(error) { + *error = localError; + } + return octagonSyncing; + } + } +#endif + + BOOL sosSafariEnabled = NO; + if([OTClique platformSupportsSOS]) { + NSError* localError = nil; + sosSafariEnabled = [self sosSafariPasswordSyncingEnabled:&localError]; + + if(localError) { + if(error) { + *error = localError; + } + return sosSafariEnabled; + } + } + + if(OctagonIsEnabled() && [OTClique platformSupportsSOS]) { + // Return the OR of this value, so that the UI checkbox will be on if any syncing is occurring + return octagonSyncing || sosSafariEnabled; + + } else if(OctagonIsEnabled() && ![OTClique platformSupportsSOS]) { + return octagonSyncing; + + } else if(!OctagonIsEnabled()&& [OTClique platformSupportsSOS]) { + return sosSafariEnabled; + + } else { + // Should be impossible, due to the check above. So: + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:errSecUnimplemented + userInfo:@{NSLocalizedDescriptionKey: @"fetchUserControllableViewsSyncingEnabled has no meaning if all sync systems are not on this platform"}]; + } + return NO; + } +} + + - (BOOL)isLastFriend:(NSError **)error { secnotice("clique-isLastFriend", "is last friend"); @@ -1061,20 +1219,8 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { if([OTClique platformSupportsSOS]) { CFErrorRef initialSyncErrorRef = NULL; - bool result = false; - if(self.ctx.analytics){ - NSError* encodingError = nil; - NSData* analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - if(!encodingError && analyticsData){ - result = SOSCCWaitForInitialSyncWithAnalytics((__bridge CFDataRef)analyticsData, &initialSyncErrorRef); - }else{ - result = SOSCCWaitForInitialSync(&initialSyncErrorRef); - } - }else{ - result = SOSCCWaitForInitialSync(&initialSyncErrorRef); - } + BOOL initialSyncResult = SOSCCWaitForInitialSync(&initialSyncErrorRef) ? YES : NO; - BOOL initialSyncResult = result ? YES : NO; if (error) { *error = (NSError*)CFBridgingRelease(initialSyncErrorRef); } else { @@ -1133,23 +1279,28 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { - (BOOL)viewSet:(NSSet*)enabledViews disabledViews:(NSSet*)disabledViews { - secnotice("clique-legacy", "viewSet for context:%@, altdsid:%@", self.ctx.context, self.ctx.altDSID); + if(OctagonIsEnabled()) { + bool enableUserViews = [enabledViews containsObject:(__bridge NSString*)kSOSViewAutofillPasswords]; + NSError* octagonError = nil; + // This function should log its success or failure + BOOL result = [self setOctagonUserControllableViewsSyncEnabled:enableUserViews error:&octagonError]; + if(!result) { + return NO; + } + } + + return [self sosViewSet:enabledViews disabledViews:disabledViews]; +} + +- (BOOL)sosViewSet:(NSSet*)enabledViews disabledViews:(NSSet*)disabledViews +{ + secnotice("clique-legacy", "viewSet for context:%@, altdsid:%@ enable:%@, disable:%@", + self.ctx.context, self.ctx.altDSID, enabledViews, disabledViews); OctagonSignpost signPost = OctagonSignpostBegin(OctagonSignpostNameViewSet); bool subTaskSuccess = false; if([OTClique platformSupportsSOS]) { - bool result = false; - if(self.ctx.analytics){ - NSError* encodingError = nil; - NSData* analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - if(!encodingError && analyticsData){ - result = SOSCCViewSetWithAnalytics((__bridge CFSetRef)enabledViews, (__bridge CFSetRef)disabledViews, (__bridge CFDataRef)analyticsData); - }else{ - result = SOSCCViewSet((__bridge CFSetRef)enabledViews, (__bridge CFSetRef)disabledViews); - } - }else{ - result = SOSCCViewSet((__bridge CFSetRef)enabledViews, (__bridge CFSetRef)disabledViews); - } + bool result = SOSCCViewSet((__bridge CFSetRef)enabledViews, (__bridge CFSetRef)disabledViews); BOOL viewSetResult = result ? YES : NO; subTaskSuccess = result; @@ -1172,28 +1323,10 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { if([OTClique platformSupportsSOS]) { CFErrorRef setCredentialsErrorRef = NULL; - bool result = false; - if(self.ctx.analytics){ - NSError* encodingError = nil; - NSData* analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - if(!encodingError && analyticsData){ - result = SOSCCSetUserCredentialsAndDSIDWithAnalytics((__bridge CFStringRef)userLabel, - (__bridge CFDataRef)userPassword, - (__bridge CFStringRef)self.ctx.dsid, - (__bridge CFDataRef)analyticsData, - &setCredentialsErrorRef); - }else{ - result = SOSCCSetUserCredentialsAndDSID((__bridge CFStringRef)userLabel, - (__bridge CFDataRef)userPassword, - (__bridge CFStringRef)self.ctx.dsid, - &setCredentialsErrorRef); - } - }else{ - result = SOSCCSetUserCredentialsAndDSID((__bridge CFStringRef)userLabel, - (__bridge CFDataRef)userPassword, - (__bridge CFStringRef)self.ctx.dsid, - &setCredentialsErrorRef); - } + bool result = SOSCCSetUserCredentialsAndDSID((__bridge CFStringRef)userLabel, + (__bridge CFDataRef)userPassword, + (__bridge CFStringRef)self.ctx.dsid, + &setCredentialsErrorRef); BOOL setCredentialsResult = result ? YES : NO; secnotice("clique-legacy", "setUserCredentialsAndDSID results: %d %@", setCredentialsResult, setCredentialsErrorRef); @@ -1379,19 +1512,8 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { #endif // OCTAGON if([OTClique platformSupportsSOS]) { - NSData* analyticsData = nil; CFErrorRef joinErrorRef = NULL; - if(self.ctx.analytics){ - NSError* encodingError = nil; - analyticsData = [NSKeyedArchiver archivedDataWithRootObject:self.ctx.analytics requiringSecureCoding:YES error:&encodingError]; - } - - if(analyticsData){ - result = SOSCCRequestToJoinCircleWithAnalytics((__bridge CFDataRef)analyticsData, &joinErrorRef); - } else { - result = SOSCCRequestToJoinCircle(&joinErrorRef); - } - + result = SOSCCRequestToJoinCircle(&joinErrorRef); secnotice("clique-legacy", "sos requestToJoinCircle complete: %d %@", result, joinErrorRef); if (error) { *error = (NSError*)CFBridgingRelease(joinErrorRef); @@ -1427,6 +1549,62 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { } } ++ (NSArray* _Nullable)fetchEscrowRecordsInternal:(OTConfigurationContext*)configurationContext + error:(NSError**)error +{ +#if OCTAGON + secnotice("clique-fetchrecords", "fetching escrow records for context:%@, altdsid:%@", configurationContext.context, configurationContext.altDSID); + + if(OctagonIsEnabled()) { + __block NSError* localError = nil; + __block NSArray* localRecords = nil; + + OTControl *control = [configurationContext makeOTControl:&localError]; + if (!control) { + secnotice("clique-fetchrecords", "unable to create otcontrol: %@", localError); + if (error) { + *error = localError; + } + return nil; + } + [control fetchEscrowRecords:OTCKContainerName + contextID:configurationContext.context + forceFetch:configurationContext.overrideEscrowCache + reply:^(NSArray * _Nullable records, + NSError * _Nullable fetchError) { + if(fetchError) { + secnotice("clique-fetchrecords", "fetchEscrowRecords errored: %@", fetchError); + } else { + secnotice("clique-fetchrecords", "fetchEscrowRecords succeeded: %@", records); + } + localError = fetchError; + localRecords = records; + }]; + + if(error && localError) { + *error = localError; + } + + secnotice("clique-fetchrecords", "fetchEscrowRecords complete"); + + return localRecords; + } else { + // With octagon off, fail with 'unimplemented' + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:errSecUnimplemented + userInfo:@{NSLocalizedDescriptionKey: @"fetching escrow records unimplemented"}]; + } + return nil; + } +#else // !OCTAGON + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return NULL; +#endif +} + // MARK: SBD interfaces + (OTBottleIDs* _Nullable)findOptimalBottleIDsWithContextData:(OTConfigurationContext*)data error:(NSError**)error @@ -1574,7 +1752,11 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { secerror("octagon-setrecoverykey, SecRKCreateRecoveryKeyWithError() failed: %@", createRecoveryKeyError); userInfo[NSLocalizedDescriptionKey] = @"SecRKCreateRecoveryKeyWithError() failed"; userInfo[NSUnderlyingErrorKey] = createRecoveryKeyError; - retError = [NSError errorWithDomain:getkSecureBackupErrorDomain() code:kSecureBackupInternalError userInfo:userInfo]; + if ([OTClique isCloudServicesAvailable] == NO) { + retError = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:userInfo]; + } else { + retError = [NSError errorWithDomain:getkSecureBackupErrorDomain() code:kSecureBackupInternalError userInfo:userInfo]; + } OctagonSignpostEnd(signPost, OctagonSignpostNameSetNewRecoveryKeyWithData, OctagonSignpostNumber1(OctagonSignpostNameSetNewRecoveryKeyWithData), (int)subTaskSuccess); reply(nil, retError); return; @@ -1586,7 +1768,11 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { NSError *underlyingError = CFBridgingRelease(registerError); userInfo[NSLocalizedDescriptionKey] = @"SecRKRegisterBackupPublicKey() failed"; userInfo[NSUnderlyingErrorKey] = underlyingError; - retError = [NSError errorWithDomain:getkSecureBackupErrorDomain() code:kSecureBackupInternalError userInfo:userInfo]; + if ([OTClique isCloudServicesAvailable] == NO) { + retError = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:userInfo]; + } else { + retError = [NSError errorWithDomain:getkSecureBackupErrorDomain() code:kSecureBackupInternalError userInfo:userInfo]; + } OctagonSignpostEnd(signPost, OctagonSignpostNameSetNewRecoveryKeyWithData, OctagonSignpostNumber1(OctagonSignpostNameSetNewRecoveryKeyWithData), (int)subTaskSuccess); reply(nil,retError); return; @@ -1858,6 +2044,12 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { + (OTClique* _Nullable)resetProtectedData:(OTConfigurationContext*)data error:(NSError**)error { #if OCTAGON + if ([OTClique isCloudServicesAvailable] == NO) { + if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented userInfo:nil]; + } + return nil; + } NSError *controlError = nil; OTControl *control = [data makeOTControl:&controlError]; if (!control) { @@ -1924,22 +2116,6 @@ NSString* OTCDPStatusToString(OTCDPStatus status) { } } - //reset ckks - CKKSControl* ckksControl = [data makeCKKSControl:&localError]; - [ckksControl rpcResetCloudKit:nil reason:@"clique-reset-protected-data" reply:^(NSError* resetError){ - localError = resetError; - }]; - - if(localError) { - secerror("clique-reset-protected-data: ckks cloudkit reset failed: %@", localError); - if(error) { - *error = localError; - } - return nil; - } else { - secnotice("clique-reset-protected-data", "ckks cloudkit reset succeeded"); - } - return clique; #else // !OCTAGON if(error) { diff --git a/keychain/ot/OTConstants.h b/keychain/ot/OTConstants.h index 736ab162..6898c1b7 100644 --- a/keychain/ot/OTConstants.h +++ b/keychain/ot/OTConstants.h @@ -27,6 +27,7 @@ #include bool OctagonIsEnabled(void); +bool SecErrorIsNestedErrorCappingEnabled(void); #if __OBJC__ @@ -44,6 +45,7 @@ extern NSString* OTProtocolPairing; extern NSString* OTProtocolPiggybacking; extern const char * OTTrustStatusChangeNotification; +extern NSString* OTEscrowRecordPrefix; BOOL OctagonPlatformSupportsSOS(void); @@ -64,6 +66,17 @@ void OctagonAuthoritativeTrustSetIsEnabled(BOOL value); BOOL OctagonIsSOSFeatureEnabled(void); void OctagonSetSOSFeatureEnabled(BOOL value); +BOOL OctagonIsOptimizationEnabled(void); +void OctagonSetOptimizationEnabled(BOOL value); + +BOOL OctagonIsEscrowRecordFetchEnabled(void); +void OctagonSetEscrowRecordFetchEnabled(BOOL value); + +BOOL SecKVSOnCloudKitIsEnabled(void); +void SecKVSOnCloudKitSetOverrideIsEnabled(BOOL value); + +void SecErrorSetOverrideNestedErrorCappingIsEnabled(BOOL value); + typedef NS_ENUM(NSInteger, CuttlefishResetReason) { CuttlefishResetReasonUnknown = 0, CuttlefishResetReasonUserInitiatedReset = 1, @@ -74,6 +87,9 @@ typedef NS_ENUM(NSInteger, CuttlefishResetReason) { CuttlefishResetReasonTestGenerated = 6, }; +extern NSString* const CuttlefishErrorDomain; +extern NSString* const CuttlefishErrorRetryAfterKey; + #endif // __OBJC__ #endif /* OTConstants_h */ diff --git a/keychain/ot/OTConstants.m b/keychain/ot/OTConstants.m index e839d139..9d133e61 100644 --- a/keychain/ot/OTConstants.m +++ b/keychain/ot/OTConstants.m @@ -42,6 +42,11 @@ NSString* OTProtocolPiggybacking = @"OctagonPiggybacking"; const char * OTTrustStatusChangeNotification = "com.apple.security.octagon.trust-status-change"; +NSString* const CuttlefishErrorDomain = @"CuttlefishError"; +NSString* const CuttlefishErrorRetryAfterKey = @"retryafter"; + +NSString* OTEscrowRecordPrefix = @"com.apple.icdp.record."; + // I don't recommend using this command, but it does describe the plist that will enable this feature: // // defaults write /System/Library/FeatureFlags/Domain/Security octagon -dict Enabled -bool YES @@ -58,6 +63,18 @@ static bool OctagonAuthoritativeTrustEnabledOverride = false; static bool OctagonSOSFeatureIsEnabledOverrideSet = false; static bool OctagonSOSFeatureIsEnabledOverride = false; +static bool OctagonOptimizationIsEnabledOverrideSet = false; +static bool OctagonOptimizationIsEnabledOverride = false; + +static bool OctagonEscrowRecordFetchIsEnabledOverrideSet = false; +static bool OctagonEscrowRecordFetchIsEnabledOverride = false; + +static bool SecKVSOnCloudKitIsEnabledOverrideSet = false; +static bool SecKVSOnCloudKitIsEnabledOverride = false; + +static bool SecErrorNestedErrorCappingIsEnabledOverrideSet = false; +static bool SecErrorNestedErrorCappingIsEnabledOverride = false; + bool OctagonIsEnabled(void) { if(OctagonEnabledOverrideSet) { @@ -191,7 +208,7 @@ BOOL OctagonIsSOSFeatureEnabled(void) { if(OctagonSOSFeatureIsEnabledOverrideSet) { secnotice("octagon", "SOS Feature is %@ (overridden)", OctagonSOSFeatureIsEnabledOverride ? @"enabled" : @"disabled"); - return OctagonSOSFeatureIsEnabledOverrideSet; + return OctagonSOSFeatureIsEnabledOverride; } static bool sosEnabled = true; @@ -209,3 +226,100 @@ void OctagonSetSOSFeatureEnabled(BOOL value) OctagonSOSFeatureIsEnabledOverrideSet = true; OctagonSOSFeatureIsEnabledOverride = value; } + +//feature flag for enabling/disabling performance enhancements +BOOL OctagonIsOptimizationEnabled(void) +{ + if(OctagonOptimizationIsEnabledOverrideSet) { + secnotice("octagon", "Octagon Optimization is %@ (overridden)", OctagonOptimizationIsEnabledOverride ? @"enabled" : @"disabled"); + return OctagonOptimizationIsEnabledOverride; + } + + static bool optimizationEnabled = true; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + optimizationEnabled = os_feature_enabled(Security, OctagonOptimization); + secnotice("octagon", "Octagon Optimization is %@ (via feature flags)", optimizationEnabled ? @"enabled" : @"disabled"); + }); + + return optimizationEnabled; +} + +void OctagonSetOptimizationEnabled(BOOL value) +{ + OctagonOptimizationIsEnabledOverrideSet = true; + OctagonOptimizationIsEnabledOverride = value; +} + + +//feature flag for checking if escrow record fetching is enabled +BOOL OctagonIsEscrowRecordFetchEnabled(void) +{ + if(OctagonEscrowRecordFetchIsEnabledOverrideSet) { + secnotice("octagon", "Octagon Escrow Record Fetching is %@ (overridden)", OctagonEscrowRecordFetchIsEnabledOverride ? @"enabled" : @"disabled"); + return OctagonEscrowRecordFetchIsEnabledOverride; + } + + static bool escrowRecordFetchingEnabled = true; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + escrowRecordFetchingEnabled = os_feature_enabled(Security, OctagonEscrowRecordFetch); + secnotice("octagon", "Octagon Escrow Record Fetching is %@ (via feature flags)", escrowRecordFetchingEnabled ? @"enabled" : @"disabled"); + }); + + return escrowRecordFetchingEnabled; +} + +void OctagonSetEscrowRecordFetchEnabled(BOOL value) +{ + OctagonEscrowRecordFetchIsEnabledOverrideSet = true; + OctagonEscrowRecordFetchIsEnabledOverride = value; +} + +//feature flag for checking kvs on cloudkit enablement +BOOL SecKVSOnCloudKitIsEnabled(void) +{ + if(SecKVSOnCloudKitIsEnabledOverrideSet) { + secnotice("octagon", "KVS on CloudKit is %@ (overridden)", SecKVSOnCloudKitIsEnabledOverride ? @"enabled" : @"disabled"); + return SecKVSOnCloudKitIsEnabledOverride; + } + + static bool kvsOnCloudKitEnabled = true; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + kvsOnCloudKitEnabled = os_feature_enabled(KVS, KVSOnCloudKitForAll); + secnotice("octagon", "KVS on CloudKit is %@ (via feature flags)", kvsOnCloudKitEnabled ? @"enabled" : @"disabled"); + }); + + return kvsOnCloudKitEnabled; +} + +void SecKVSOnCloudKitSetOverrideIsEnabled(BOOL value) +{ + SecKVSOnCloudKitIsEnabledOverrideSet = true; + SecKVSOnCloudKitIsEnabledOverride = value; +} + +//feature flag for checking whether or not we should cap the number of nested errors +bool SecErrorIsNestedErrorCappingEnabled(void) +{ + if(SecErrorNestedErrorCappingIsEnabledOverrideSet) { + secnotice("octagon", "SecError Nested Error Capping is %@ (overridden)", SecErrorNestedErrorCappingIsEnabledOverride ? @"enabled" : @"disabled"); + return SecErrorNestedErrorCappingIsEnabledOverride; + } + + static bool errorCappingEnabled = true; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + errorCappingEnabled = os_feature_enabled(Security, SecErrorNestedErrorCapping); + secnotice("octagon", "SecError Nested Error Capping is %@ (via feature flags)", errorCappingEnabled ? @"enabled" : @"disabled"); + }); + + return errorCappingEnabled; +} + +void SecErrorSetOverrideNestedErrorCappingIsEnabled(BOOL value) +{ + SecErrorNestedErrorCappingIsEnabledOverrideSet = true; + SecErrorNestedErrorCappingIsEnabledOverride = value; +} diff --git a/keychain/ot/OTControl.h b/keychain/ot/OTControl.h index c279f62c..9b903dc8 100644 --- a/keychain/ot/OTControl.h +++ b/keychain/ot/OTControl.h @@ -214,10 +214,6 @@ NS_ASSUME_NONNULL_BEGIN skipRateLimitingCheck:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError *_Nullable error))reply; -- (void)attemptSosUpgrade:(NSString* _Nullable)container - context:(NSString*)context - reply:(void (^)(NSError* _Nullable error))reply; - - (void)waitForOctagonUpgrade:(NSString* _Nullable)container context:(NSString*)context reply:(void (^)(NSError* _Nullable error))reply; @@ -246,6 +242,26 @@ skipRateLimitingCheck:(BOOL)skipRateLimitingCheck contextID:(NSString*)contextID reply:(void (^)(NSError* _Nullable error))reply; + +- (void)fetchEscrowRecords:(NSString * _Nullable)container + contextID:(NSString*)contextID + forceFetch:(BOOL)forceFetch + reply:(void (^)(NSArray* _Nullable records, + NSError* _Nullable error))reply; + +- (void)setUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + enabled:(BOOL)enabled + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply; + +- (void)fetchUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply; + +- (void)invalidateEscrowCache:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + reply:(nonnull void (^)(NSError * _Nullable error))reply; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTControl.m b/keychain/ot/OTControl.m index e5669901..67cd5ea5 100644 --- a/keychain/ot/OTControl.m +++ b/keychain/ot/OTControl.m @@ -441,15 +441,6 @@ skipRateLimitingCheck:(BOOL)skipRateLimitingCheck }] healthCheck:container context:context skipRateLimitingCheck:skipRateLimitingCheck reply:reply]; } -- (void)attemptSosUpgrade:(NSString* _Nullable)container - context:(NSString*)context - reply:(void (^)(NSError* _Nullable error))reply -{ - [[self getConnection: ^(NSError* error) { - reply(error); - }] attemptSosUpgrade:container context:context reply:reply]; -} - - (void)waitForOctagonUpgrade:(NSString* _Nullable)container context:(NSString*)context reply:(void (^)(NSError* _Nullable error))reply @@ -508,6 +499,46 @@ skipRateLimitingCheck:(BOOL)skipRateLimitingCheck }] getCDPStatus:containerName contextID:contextID reply:reply]; } +- (void)fetchEscrowRecords:(NSString * _Nullable)container + contextID:(NSString*)contextID + forceFetch:(BOOL)forceFetch + reply:(void (^)(NSArray* _Nullable records, + NSError* _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(nil, connectionError); + }] fetchEscrowRecords:container contextID:contextID forceFetch:forceFetch reply:reply]; +} + +- (void)setUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + enabled:(BOOL)enabled + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(NO, connectionError); + }] setUserControllableViewsSyncStatus:containerName contextID:contextID enabled:enabled reply:reply]; + +} + +- (void)fetchUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(NO, connectionError); + }] fetchUserControllableViewsSyncStatus:containerName contextID:contextID reply:reply]; +} + +- (void)invalidateEscrowCache:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + reply:(nonnull void (^)(NSError * _Nullable error))reply +{ + [[self getConnection: ^(NSError* connectionError) { + reply(connectionError); + }] invalidateEscrowCache:containerName contextID:contextID reply:reply]; +} + + (OTControl*)controlObject:(NSError* __autoreleasing *)error { return [OTControl controlObject:false error:error]; } diff --git a/keychain/ot/OTControlProtocol.h b/keychain/ot/OTControlProtocol.h index 48f99a77..736875b4 100644 --- a/keychain/ot/OTControlProtocol.h +++ b/keychain/ot/OTControlProtocol.h @@ -34,8 +34,6 @@ NS_ASSUME_NONNULL_BEGIN @class OTJoiningConfiguration; -typedef void (^OTNextJoinCompleteBlock)(BOOL finished, NSData* _Nullable message, NSError* _Nullable error); - @protocol OTControlProtocol - (void)restore:(NSString *)contextID dsid:(NSString *)dsid secret:(NSData*)secret escrowRecordID:(NSString*)escrowRecordID reply:(void (^)(NSData* _Nullable signingKeyData, NSData* _Nullable encryptionKeyData, NSError * _Nullable error))reply; - (void)octagonEncryptionPublicKey:(void (^)(NSData* _Nullable encryptionKey, NSError * _Nullable))reply; @@ -185,10 +183,6 @@ typedef void (^OTNextJoinCompleteBlock)(BOOL finished, NSData* _Nullable message skipRateLimitingCheck:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError *_Nullable error))reply; -- (void)attemptSosUpgrade:(NSString* _Nullable)container - context:(NSString*)context - reply:(void (^)(NSError* _Nullable error))reply; - - (void)waitForOctagonUpgrade:(NSString* _Nullable)container context:(NSString*)context reply:(void (^)(NSError* _Nullable error))reply; @@ -217,6 +211,25 @@ skipRateLimitingCheck:(BOOL)skipRateLimitingCheck contextID:(NSString*)contextID reply:(void (^)(OTCDPStatus status, NSError* _Nullable error))reply; +- (void)fetchEscrowRecords:(NSString * _Nullable)container + contextID:(NSString*)contextID + forceFetch:(BOOL)forceFetch + reply:(void (^)(NSArray* _Nullable records, + NSError* _Nullable error))reply; + +- (void)invalidateEscrowCache:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + reply:(nonnull void (^)(NSError * _Nullable error))reply; + +/* View Handling */ +- (void)setUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + enabled:(BOOL)enabled + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply; + +- (void)fetchUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply; @end NSXPCInterface* OTSetupControlProtocol(NSXPCInterface* interface); diff --git a/keychain/ot/OTControlProtocol.m b/keychain/ot/OTControlProtocol.m index 9c0df198..d0ab951a 100644 --- a/keychain/ot/OTControlProtocol.m +++ b/keychain/ot/OTControlProtocol.m @@ -26,73 +26,59 @@ #import "keychain/ot/OTControlProtocol.h" #import "keychain/ot/OTJoiningConfiguration.h" #import - -#if OCTAGON -#import -#import -#import -#include -#import -#import -#endif // OCTAGON - +#include NSXPCInterface* OTSetupControlProtocol(NSXPCInterface* interface) { #if OCTAGON NSSet *errorClasses = [SecXPCHelper safeErrorClasses]; @try { - [interface setClasses:errorClasses forSelector:@selector(restore:dsid:secret:escrowRecordID:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(octagonEncryptionPublicKey:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(octagonSigningPublicKey:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(listOfEligibleBottledPeerRecords:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(signOut:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(restore:dsid:secret:escrowRecordID:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(octagonEncryptionPublicKey:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(octagonSigningPublicKey:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(listOfEligibleBottledPeerRecords:) argumentIndex:1 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(signIn:container:context:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(reset:) argumentIndex:0 ofReply:YES]; - + [interface setClasses:errorClasses forSelector:@selector(signOut:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(notifyIDMSTrustLevelChangeForContainer:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(reset:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(handleIdentityChangeForSigningKey:ForEncryptionKey:ForPeerID:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcEpochWithConfiguration:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcPrepareIdentityAsApplicantWithConfiguration:reply:) argumentIndex:5 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcVoucherWithConfiguration:peerID:permanentInfo:permanentInfoSig:stableInfo:stableInfoSig:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcJoinWithConfiguration:vouchData:vouchSig:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(preflightBottledPeer:dsid:reply:) argumentIndex:3 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(launchBottledPeer:bottleID:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(scrubBottledPeer:bottleID:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(handleIdentityChangeForSigningKey:ForEncryptionKey:ForPeerID:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(status:context:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(fetchEgoPeerID:context:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(fetchCliqueStatus:context:configuration:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(fetchTrustStatus:context:configuration:reply:) argumentIndex:4 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(fetchEscrowContents:contextID:reply:) argumentIndex:3 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(startOctagonStateMachine:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(resetAndEstablish:context:altDSID:resetReason:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(establish:context:altDSID:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(leaveClique:context:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(removeFriendsInClique:context:peerIDs:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(peerDeviceNamesByPeerID:context:reply:) argumentIndex:1 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(fetchAllViableBottles:context:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(restore:contextID:bottleSalt:entropy:bottleID:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(fetchEscrowContents:contextID:reply:) argumentIndex:3 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(createRecoveryKey:contextID:recoveryKey:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(joinWithRecoveryKey:contextID:recoveryKey:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(healthCheck:context:skipRateLimitingCheck:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(attemptSosUpgrade:context:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(waitForOctagonUpgrade:context:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(postCDPFollowupResult:type:error:containerName:contextName:reply:) argumentIndex:2 ofReply:NO]; [interface setClasses:errorClasses forSelector:@selector(postCDPFollowupResult:type:error:containerName:contextName:reply:) argumentIndex:0 ofReply:YES]; [interface setClasses:errorClasses forSelector:@selector(tapToRadar:description:radar:reply:) argumentIndex:0 ofReply:YES]; - [interface setClasses:errorClasses forSelector:@selector(resetAndEstablish:context:altDSID:resetReason:reply:) argumentIndex:0 ofReply:YES]; - -#if __OBJC2__ - - [interface setClasses:errorClasses - forSelector:@selector(rpcEpochWithConfiguration:reply:) - argumentIndex:1 - ofReply:YES]; - [interface setClasses:errorClasses - forSelector:@selector(rpcPrepareIdentityAsApplicantWithConfiguration:reply:) - argumentIndex:5 - ofReply:YES]; - [interface setClasses:errorClasses - forSelector:@selector(rpcVoucherWithConfiguration:peerID:permanentInfo:permanentInfoSig:stableInfo:stableInfoSig:reply:) - argumentIndex:2 - ofReply:YES]; - [interface setClasses:errorClasses - forSelector:@selector(rpcJoinWithConfiguration:vouchData:vouchSig:reply:) - argumentIndex:0 - ofReply:YES]; -#endif /* __OBJC2__ */ + [interface setClasses:errorClasses forSelector:@selector(refetchCKKSPolicy:contextID:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(setCDPEnabled:contextID:reply:) argumentIndex:0 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(getCDPStatus:contextID:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(fetchEscrowRecords:contextID:forceFetch:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(setUserControllableViewsSyncStatus:contextID:enabled:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(fetchUserControllableViewsSyncStatus:contextID:reply:) argumentIndex:1 ofReply:YES]; } @catch(NSException* e) { secerror("OTSetupControlProtocol failed, continuing, but you might crash later: %@", e); -#if DEBUG @throw e; -#endif } #endif diff --git a/keychain/ot/OTCuttlefishAccountStateHolder.h b/keychain/ot/OTCuttlefishAccountStateHolder.h index abdb5e32..6267d27f 100644 --- a/keychain/ot/OTCuttlefishAccountStateHolder.h +++ b/keychain/ot/OTCuttlefishAccountStateHolder.h @@ -34,8 +34,6 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)persistNewTrustState:(OTAccountMetadataClassC_TrustState)newState error:(NSError**)error; -- (BOOL)persistNewEpoch:(uint64_t)epoch error:(NSError**)error; - - (BOOL)persistAccountChanges:(OTAccountMetadataClassC* _Nullable (^)(OTAccountMetadataClassC* metadata))makeChanges error:(NSError**)error; @@ -45,7 +43,6 @@ NS_ASSUME_NONNULL_BEGIN - (NSDate *)lastHealthCheckupDate:(NSError * _Nullable *)error; - (BOOL)persistLastHealthCheck:(NSDate*)lastCheck error:(NSError**)error; -- (OTAccountMetadataClassC_AttemptedAJoinState)fetchPersistedJoinAttempt:(NSError * _Nullable *)error; - (BOOL)persistOctagonJoinAttempt:(OTAccountMetadataClassC_AttemptedAJoinState)attempt error:(NSError**)error; @end diff --git a/keychain/ot/OTCuttlefishAccountStateHolder.m b/keychain/ot/OTCuttlefishAccountStateHolder.m index b6d596d1..5b9ea18a 100644 --- a/keychain/ot/OTCuttlefishAccountStateHolder.m +++ b/keychain/ot/OTCuttlefishAccountStateHolder.m @@ -99,19 +99,6 @@ return current.peerID; } -- (OTAccountMetadataClassC_AttemptedAJoinState)fetchPersistedJoinAttempt:(NSError * _Nullable *)error { - NSError* localError = nil; - OTAccountMetadataClassC* current = [self loadOrCreateAccountMetadata:&localError]; - - if(localError || !current) { - if(error) { - *error = localError; - } - return OTAccountMetadataClassC_AttemptedAJoinState_UNKNOWN; - } - return current.attemptedJoin; -} - - (NSDate *)lastHealthCheckupDate:(NSError * _Nullable *)error { NSError* localError = nil; @@ -144,26 +131,6 @@ } error:error]; } -- (BOOL)persistNewAccountState:(OTAccountMetadataClassC_AccountState)newState - optionalAltDSID:(NSString* _Nullable)altDSID - error:(NSError**)error -{ - return [self persistAccountChanges:^(OTAccountMetadataClassC *metadata) { - metadata.icloudAccountState = newState; - metadata.altDSID = altDSID; - return metadata; - } error:error]; -} - -- (BOOL)persistNewEpoch:(uint64_t)epoch - error:(NSError**)error -{ - return [self persistAccountChanges:^(OTAccountMetadataClassC *metadata) { - metadata.epoch = epoch; - return metadata; - } error:error]; -} - - (BOOL)persistAccountChanges:(OTAccountMetadataClassC* _Nullable (^)(OTAccountMetadataClassC*))makeChanges error:(NSError**)error { @@ -256,5 +223,4 @@ }); } - @end diff --git a/keychain/ot/OTCuttlefishContext.h b/keychain/ot/OTCuttlefishContext.h index 714b7013..828662e4 100644 --- a/keychain/ot/OTCuttlefishContext.h +++ b/keychain/ot/OTCuttlefishContext.h @@ -159,9 +159,17 @@ NS_ASSUME_NONNULL_BEGIN NSString* _Nullable peerID, NSDictionary* _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError * _Nullable))reply; - (void)rpcFetchDeviceNamesByPeerID:(void (^)(NSDictionary* _Nullable peers, NSError* _Nullable error))reply; -- (void)rpcFetchAllViableBottles:(void (^)(NSArray* _Nullable sortedBottleIDs, NSArray* _Nullable sortedPartialEscrowRecordIDs, NSError* _Nullable error))reply; +- (void)rpcFetchAllViableBottles:(void (^)(NSArray* _Nullable sortedBottleIDs, + NSArray* _Nullable sortedPartialEscrowRecordIDs, + NSError* _Nullable error))reply; + +- (void)rpcFetchAllViableEscrowRecords:(BOOL)forceFetch reply:(void (^)(NSArray* _Nullable records, + NSError* _Nullable error))reply; +- (void)rpcInvalidateEscrowCache:(void (^)(NSError* _Nullable error))reply; + - (void)fetchEscrowContents:(void (^)(NSData* _Nullable entropy, NSString* _Nullable bottleID, NSData* _Nullable signingPublicKey, @@ -170,6 +178,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)rpcRefetchCKKSPolicy:(void (^)(NSError * _Nullable error))reply; +- (void)rpcFetchUserControllableViewsSyncingStatus:(void (^)(BOOL areSyncing, NSError* _Nullable error))reply; +- (void)rpcSetUserControllableViewsSyncingStatus:(BOOL)status reply:(void (^)(BOOL areSyncing, NSError* _Nullable error))reply; + - (void)requestTrustedDeviceListRefresh; - (OTDeviceInformation*)prepareInformation; @@ -179,19 +190,15 @@ NS_ASSUME_NONNULL_BEGIN - (OTOperationDependencies*)operationDependencies; -- (void)attemptSOSUpgrade:(void (^)(NSError* _Nullable error))reply; - - (void)waitForOctagonUpgrade:(void (^)(NSError* error))reply NS_SWIFT_NAME(waitForOctagonUpgrade(reply:)); - (BOOL)waitForReady:(int64_t)timeOffset; - // For testing. - (OTAccountMetadataClassC_AccountState)currentMemoizedAccountState; - (OTAccountMetadataClassC_TrustState)currentMemoizedTrustState; - (NSDate* _Nullable) currentMemoizedLastHealthCheck; -- (void) checkTrustStatusAndPostRepairCFUIfNecessary:(void (^ _Nullable)(CliqueStatus status, BOOL posted, BOOL hasIdentity, NSError * _Nullable error))reply; -- (void) setAccountStateHolder:(OTCuttlefishAccountStateHolder*)accountMetadataStore; +- (void)checkTrustStatusAndPostRepairCFUIfNecessary:(void (^ _Nullable)(CliqueStatus status, BOOL posted, BOOL hasIdentity, BOOL isLocked, NSError * _Nullable error))reply; - (void)clearCKKSViewManager; @@ -199,8 +206,6 @@ NS_ASSUME_NONNULL_BEGIN // Octagon Health Check Helpers - (void)checkOctagonHealth:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError * _Nullable error))reply; -- (BOOL)postRepairCFU:(NSError**)error; -- (void)postConfirmPasscodeCFU:(NSError**)error; // For reporting - (BOOL)machineIDOnMemoizedList:(NSString*)machineID error:(NSError**)error NS_SWIFT_NOTHROW; diff --git a/keychain/ot/OTCuttlefishContext.m b/keychain/ot/OTCuttlefishContext.m index a4e5c8fc..a5e52ed4 100644 --- a/keychain/ot/OTCuttlefishContext.m +++ b/keychain/ot/OTCuttlefishContext.m @@ -33,6 +33,7 @@ #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" +#include "keychain/SecureObjectSync/SOSInternal.h" #import "keychain/analytics/CKKSLaunchSequence.h" #import "keychain/categories/NSError+UsefulConstructors.h" @@ -56,6 +57,7 @@ #import "keychain/ot/OTDetermineHSA2AccountStatusOperation.h" #import "keychain/ot/OTDeviceInformationAdapter.h" #import "keychain/ot/OTEnsureOctagonKeyConsistency.h" +#import "keychain/ot/OTPreloadOctagonKeysOperation.h" #import "keychain/ot/OTEpochOperation.h" #import "keychain/ot/OTEstablishOperation.h" #import "keychain/ot/OTFetchViewsOperation.h" @@ -64,6 +66,7 @@ #import "keychain/ot/OTLeaveCliqueOperation.h" #import "keychain/ot/OTLocalCKKSResetOperation.h" #import "keychain/ot/OTLocalCuttlefishReset.h" +#import "keychain/ot/OTModifyUserControllableViewStatusOperation.h" #import "keychain/ot/OTOperationDependencies.h" #import "keychain/ot/OTPrepareOperation.h" #import "keychain/ot/OTRemovePeersOperation.h" @@ -107,8 +110,6 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; @interface OTCuttlefishContext () { - NSData* _vouchData; - NSData* _vouchSig; NSString* _bottleID; NSString* _bottleSalt; NSData* _entropy; @@ -127,6 +128,9 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; @property CKKSCondition *cloudKitAccountStateKnown; @property CKKSNearFutureScheduler* suggestTLKUploadNotifier; +@property CKKSNearFutureScheduler* requestPolicyCheckNotifier; + +@property OctagonAPSReceiver* apsReceiver; // Make writable @property (nullable) CKKSViewManager* viewManager; @@ -134,7 +138,6 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; // Dependencies (for injection) @property id sosAdapter; @property id octagonAdapter; -@property (readonly) Class apsConnectionClass; @property (readonly) Class escrowRequestClass; @property (nonatomic) BOOL initialBecomeUntrustedPosted; @@ -162,11 +165,14 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; _containerName = containerName; _contextID = contextID; + _apsReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort + apsConnectionClass:apsConnectionClass]; + [_apsReceiver registerCuttlefishReceiver:self forContainerName:self.containerName]; + _viewManager = viewManager; _initialBecomeUntrustedPosted = NO; - _apsConnectionClass = apsConnectionClass; _launchSequence = [[CKKSLaunchSequence alloc] initWithRocketName:@"com.apple.octagon.launch"]; _queue = dispatch_queue_create("com.apple.security.otcuttlefishcontext", DISPATCH_QUEUE_SERIAL); @@ -212,6 +218,15 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; secnotice("octagon-ckks", "Adding flag for CKKS TLK upload"); [self.stateMachine handleFlag:OctagonFlagCKKSRequestsTLKUpload]; }]; + + _requestPolicyCheckNotifier = [[CKKSNearFutureScheduler alloc] initWithName:@"octagon-policy-check" + delay:500*NSEC_PER_MSEC + keepProcessAlive:false + dependencyDescriptionCode:0 block:^{ + STRONGIFY(self); + secnotice("octagon-ckks", "Adding flag for CKKS policy check"); + [self.stateMachine handleFlag:OctagonFlagCKKSRequestsPolicyCheck]; + }]; } return self; } @@ -398,7 +413,11 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } [self.stateMachine handleFlag:OctagonFlagAccountIsAvailable]; - + + if(OctagonIsOptimizationEnabled()){ + [self.stateMachine handleFlag:OctagonFlagWarmEscrowRecordCache]; + } + if(localError) { if(error) { *error = localError; @@ -547,11 +566,9 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; - (void)localReset:(nonnull void (^)(NSError * _Nullable))reply { - OTLocalResetOperation* pendingOp = [[OTLocalResetOperation alloc] init:self.containerName - contextID:self.contextID - intendedState:OctagonStateBecomeUntrusted - errorState:OctagonStateError - cuttlefishXPCWrapper:self.cuttlefishXPCWrapper]; + OTLocalResetOperation* pendingOp = [[OTLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateInitializing + errorState:OctagonStateError]; NSMutableSet* sourceStates = [NSMutableSet setWithArray: OctagonStateMap().allKeys]; [self.stateMachine doSimpleStateMachineRPC:@"local-reset" op:pendingOp sourceStates:sourceStates reply:reply]; @@ -715,8 +732,6 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; { dispatch_assert_queue(self.queue); - WEAKIFY(self); - [self.launchSequence addEvent:currentState]; // If We're initializing, or there was some recent update to the account state, @@ -749,7 +764,12 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } if([currentState isEqualToString:OctagonStateCloudKitNewlyAvailable]) { - return [self cloudKitAccountNewlyAvailableOperation]; + OctagonFlag* warmEscrowCache = nil; + if([flags _onqueueContains:OctagonFlagWarmEscrowRecordCache] && OctagonIsOptimizationEnabled()) { + [flags _onqueueRemoveFlag:OctagonFlagWarmEscrowRecordCache]; + warmEscrowCache = OctagonFlagWarmEscrowRecordCache; + } + return [self cloudKitAccountNewlyAvailableOperation:warmEscrowCache]; } if([currentState isEqualToString:OctagonStateDetermineCDPState]) { @@ -848,6 +868,31 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; intendedState:OctagonStateBecomeReady errorState:OctagonStateError]; } + + if([currentState isEqualToString:OctagonStateEnableUserControllableViews]) { + return [[OTModifyUserControllableViewStatusOperation alloc] initWithDependencies:self.operationDependencies + intendedViewStatus:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED + intendedState:OctagonStateBecomeReady + peerMissingState:OctagonStateReadyUpdated + errorState:OctagonStateBecomeReady]; + } + + if([currentState isEqualToString:OctagonStateDisableUserControllableViews]) { + return [[OTModifyUserControllableViewStatusOperation alloc] initWithDependencies:self.operationDependencies + intendedViewStatus:TPPBPeerStableInfo_UserControllableViewStatus_DISABLED + intendedState:OctagonStateBecomeReady + peerMissingState:OctagonStateReadyUpdated + errorState:OctagonStateBecomeReady]; + } + + if([currentState isEqualToString:OctagonStateSetUserControllableViewsToPeerConsensus]) { + // Setting the status to FOLLOWING will either enable or disable the value, depending on our peers. + return [[OTModifyUserControllableViewStatusOperation alloc] initWithDependencies:self.operationDependencies + intendedViewStatus:TPPBPeerStableInfo_UserControllableViewStatus_FOLLOWING + intendedState:OctagonStateBecomeReady + peerMissingState:OctagonStateReadyUpdated + errorState:OctagonStateBecomeReady]; + } if([currentState isEqualToString:OctagonStateNoAccount]) { // We only want to move out of untrusted if something useful has happened! @@ -885,6 +930,17 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } } + if([flags _onqueueContains:OctagonFlagAttemptSOSConsistency]) { + [flags _onqueueRemoveFlag:OctagonFlagAttemptSOSConsistency]; + if(self.sosAdapter.sosEnabled) { + secnotice("octagon", "Attempting SOS upgrade again (due to a consistency notification)"); + return [OctagonStateTransitionOperation named:@"attempt-sos-upgrade" + entering:OctagonStateAttemptSOSUpgrade]; + } else { + secnotice("octagon", "Someone would like us to check SOS consistency, but this platform doesn't support SOS."); + } + } + if([flags _onqueueContains:OctagonFlagCuttlefishNotification]) { [flags _onqueueRemoveFlag:OctagonFlagCuttlefishNotification]; secnotice("octagon", "Updating TPH (while untrusted) due to push"); @@ -915,69 +971,19 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if([currentState isEqualToString:OctagonStateDetermineiCloudAccountState]) { secnotice("octagon", "Determine iCloud account status"); - // TODO replace with OTDetermineHSA2AccountStatusOperation in Octagon: ensure Octagon operations can't occur on SA accounts - return [OctagonStateTransitionOperation named:@"octagon-determine-icloud-state" - intending:OctagonStateNoAccount - errorState:OctagonStateError - withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { - STRONGIFY(self); - - NSError *authKitError = nil; - NSString* primaryAccountAltDSID = [self.authKitAdapter primaryiCloudAccountAltDSID:&authKitError]; - - dispatch_sync(self.queue, ^{ - NSError* error = nil; - - if(primaryAccountAltDSID != nil) { - secnotice("octagon", "iCloud account is present; checking HSA2 status"); - - bool hsa2 = [self.authKitAdapter accountIsHSA2ByAltDSID:primaryAccountAltDSID]; - secnotice("octagon", "HSA2 is %@", hsa2 ? @"enabled" : @"disabled"); - - [self.accountMetadataStore _onqueuePersistAccountChanges:^OTAccountMetadataClassC *(OTAccountMetadataClassC * metadata) { - if(hsa2) { - metadata.icloudAccountState = OTAccountMetadataClassC_AccountState_ACCOUNT_AVAILABLE; - } else { - metadata.icloudAccountState = OTAccountMetadataClassC_AccountState_NO_ACCOUNT; - } - metadata.altDSID = primaryAccountAltDSID; - return metadata; - } error:&error]; - - // If there's an HSA2 account, return to 'initializing' here, as we want to centralize decisions on what to do next - if(hsa2) { - op.nextState = OctagonStateInitializing; - } else { - [self.accountStateTracker setHSA2iCloudAccountStatus:CKKSAccountStatusNoAccount]; - op.nextState = OctagonStateWaitForHSA2; - } - - } else { - secnotice("octagon", "iCloud account is not present: %@", authKitError); - - [self.accountMetadataStore _onqueuePersistAccountChanges:^OTAccountMetadataClassC *(OTAccountMetadataClassC * metadata) { - metadata.icloudAccountState = OTAccountMetadataClassC_AccountState_NO_ACCOUNT; - metadata.altDSID = nil; - return metadata; - } error:&error]; - - op.nextState = OctagonStateNoAccount; - } - - if(error) { - secerror("octagon: unable to save new account state: %@", error); - } - }); - }]; + // If there's an HSA2 account, return to 'initializing' here, as we want to centralize decisions on what to do next + return [[OTDetermineHSA2AccountStatusOperation alloc] initWithDependencies:self.operationDependencies + stateIfHSA2:OctagonStateInitializing + stateIfNotHSA2:OctagonStateWaitForHSA2 + stateIfNoAccount:OctagonStateNoAccount + errorState:OctagonStateError]; } if([currentState isEqualToString:OctagonStateNoAccountDoReset]) { secnotice("octagon", "Attempting local-reset as part of signout"); - return [[OTLocalResetOperation alloc] init:self.containerName - contextID:self.contextID - intendedState:OctagonStateNoAccount - errorState:OctagonStateNoAccount - cuttlefishXPCWrapper:self.cuttlefishXPCWrapper]; + return [[OTLocalResetOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateNoAccount + errorState:OctagonStateNoAccount]; } if([currentState isEqualToString:OctagonStateEnsureConsistency]) { @@ -993,6 +999,18 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; entering:OctagonStateBecomeReady]; } + if([currentState isEqualToString:OctagonStateBottlePreloadOctagonKeysInSOS]) { + secnotice("octagon", "Preloading Octagon Keys on the SOS Account"); + if(self.sosAdapter.sosEnabled) { + return [[OTPreloadOctagonKeysOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBecomeReady + errorState:OctagonStateBecomeReady]; + } + // Add further consistency checks here. + return [OctagonStateTransitionOperation named:@"no-preload-octagon-key" + entering:OctagonStateBecomeReady]; + } + if([currentState isEqualToString:OctagonStateEnsureUpdatePreapprovals]) { secnotice("octagon", "SOS is enabled; ensuring preapprovals are correct"); return [[OTSOSUpdatePreapprovalsOperation alloc] initWithDependencies:self.operationDependencies @@ -1001,6 +1019,12 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; errorState:OctagonStateBecomeReady]; } + if([currentState isEqualToString:OctagonStateAttemptSOSUpgradeDetermineCDPState]) { + return [[OTDetermineCDPBitStatusOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateAttemptSOSUpgrade + errorState:OctagonStateWaitForCDP]; + } + if([currentState isEqualToString:OctagonStateAttemptSOSUpgrade] && OctagonPerformSOSUpgrade()) { secnotice("octagon", "Investigating SOS status"); return [[OTSOSUpgradeOperation alloc] initWithDependencies:self.operationDependencies @@ -1041,43 +1065,20 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; epoch:1]; } else if([currentState isEqualToString:OctagonStateBottleJoinVouchWithBottle]) { - // Octagon: ensure we use appropriate CKKS policy when joining octagon with future policy - // When we join with a bottle, we need to be sure that we've found all the TLKShares that we can reasonably unpack via the bottle - - OTVouchWithBottleOperation* pendingOp = [[OTVouchWithBottleOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateInitiatorSetCDPBit - errorState:OctagonStateBecomeUntrusted - bottleID:_bottleID - entropy:_entropy - bottleSalt:_bottleSalt]; - - CKKSResultOperation* callback = [CKKSResultOperation named:@"vouchWithBottle-callback" - withBlock:^{ - secnotice("otrpc", "Returning a vouch with bottle call: %@, %@ %@", pendingOp.voucher, pendingOp.voucherSig, pendingOp.error); - self->_vouchSig = pendingOp.voucherSig; - self->_vouchData = pendingOp.voucher; - }]; - [callback addDependency:pendingOp]; - [self.operationQueue addOperation: callback]; - - return pendingOp; + return [[OTVouchWithBottleOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateInitiatorSetCDPBit + errorState:OctagonStateBecomeUntrusted + bottleID:_bottleID + entropy:_entropy + bottleSalt:_bottleSalt + saveVoucher:YES]; } else if([currentState isEqualToString:OctagonStateVouchWithRecoveryKey]) { - OTVouchWithRecoveryKeyOperation* pendingOp = [[OTVouchWithRecoveryKeyOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateInitiatorSetCDPBit - errorState:OctagonStateBecomeUntrusted - recoveryKey:_recoveryKey]; - - CKKSResultOperation* callback = [CKKSResultOperation named:@"vouchWithRecoveryKey-callback" - withBlock:^{ - secnotice("otrpc", "Returning a vouch with recovery key call: %@, %@ %@", pendingOp.voucher, pendingOp.voucherSig, pendingOp.error); - self->_vouchSig = pendingOp.voucherSig; - self->_vouchData = pendingOp.voucher; - }]; - [callback addDependency:pendingOp]; - [self.operationQueue addOperation: callback]; - - return pendingOp; + return [[OTVouchWithRecoveryKeyOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateInitiatorSetCDPBit + errorState:OctagonStateBecomeUntrusted + recoveryKey:_recoveryKey + saveVoucher:YES]; } else if([currentState isEqualToString:OctagonStateInitiatorSetCDPBit]) { return [[OTSetCDPBitOperation alloc] initWithDependencies:self.operationDependencies @@ -1094,13 +1095,10 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return op; } else if ([currentState isEqualToString:OctagonStateInitiatorJoin]){ - OTJoinWithVoucherOperation* op = [[OTJoinWithVoucherOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateBecomeReady - ckksConflictState:OctagonStateInitiatorJoinCKKSReset - errorState:OctagonStateBecomeUntrusted - voucherData:_vouchData - voucherSig:_vouchSig]; - return op; + return [[OTJoinWithVoucherOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBottlePreloadOctagonKeysInSOS + ckksConflictState:OctagonStateInitiatorJoinCKKSReset + errorState:OctagonStateBecomeUntrusted]; } else if([currentState isEqualToString:OctagonStateInitiatorJoinCKKSReset]) { return [[OTLocalCKKSResetOperation alloc] initWithDependencies:self.operationDependencies @@ -1109,11 +1107,9 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } else if ([currentState isEqualToString:OctagonStateInitiatorJoinAfterCKKSReset]){ return [[OTJoinWithVoucherOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateBecomeReady + intendedState:OctagonStateBottlePreloadOctagonKeysInSOS ckksConflictState:OctagonStateBecomeUntrusted - errorState:OctagonStateBecomeUntrusted - voucherData:_vouchData - voucherSig:_vouchSig]; + errorState:OctagonStateBecomeUntrusted]; } else if([currentState isEqualToString:OctagonStateResetBecomeUntrusted]) { return [self becomeUntrustedOperation:OctagonStateResetAndEstablish]; @@ -1128,8 +1124,8 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } else if([currentState isEqualToString:OctagonStateResetAnyMissingTLKCKKSViews]) { return [[OTResetCKKSZonesLackingTLKsOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateEstablishEnableCDPBit - errorState:OctagonStateError]; + intendedState:OctagonStateEstablishEnableCDPBit + errorState:OctagonStateError]; } else if([currentState isEqualToString:OctagonStateEstablishEnableCDPBit]) { return [[OTSetCDPBitOperation alloc] initWithDependencies:self.operationDependencies @@ -1181,6 +1177,17 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; intendedState: OctagonStateBecomeUntrusted errorState: OctagonStateBecomeUntrusted]; + } else if([currentState isEqualToString:OctagonStateWaitForClassCUnlock]) { + if([flags _onqueueContains:OctagonFlagUnlocked]) { + [flags _onqueueRemoveFlag:OctagonFlagUnlocked]; + return [OctagonStateTransitionOperation named:[NSString stringWithFormat:@"%@", @"initializing-after-initial-unlock"] + entering:OctagonStateInitializing]; + } + + [pendingFlagHandler _onqueueHandlePendingFlag:[[OctagonPendingFlag alloc] initWithFlag:OctagonFlagUnlocked + conditions:OctagonPendingConditionsDeviceUnlocked]]; + return nil; + } else if([currentState isEqualToString: OctagonStateWaitForUnlock]) { if([flags _onqueueContains:OctagonFlagUnlocked]) { [flags _onqueueRemoveFlag:OctagonFlagUnlocked]; @@ -1206,6 +1213,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return [[OTUploadNewCKKSTLKsOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateReady ckksConflictState:OctagonStateAssistCKKSTLKUploadCKKSReset + peerMissingState:OctagonStateReadyUpdated errorState:OctagonStateReady]; } else if([currentState isEqualToString:OctagonStateAssistCKKSTLKUploadCKKSReset]) { @@ -1218,20 +1226,51 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return [[OTUploadNewCKKSTLKsOperation alloc] initWithDependencies:self.operationDependencies intendedState:OctagonStateReady ckksConflictState:OctagonStateReady + peerMissingState:OctagonStateReadyUpdated errorState:OctagonStateReady]; } else if([currentState isEqualToString:OctagonStateReady]) { + if([flags _onqueueContains:OctagonFlagCuttlefishNotification]) { + [flags _onqueueRemoveFlag:OctagonFlagCuttlefishNotification]; + secnotice("octagon", "Updating TPH (while ready) due to push"); + return [OctagonStateTransitionOperation named:@"octagon-update" + entering:OctagonStateReadyUpdated]; + } + if([flags _onqueueContains:OctagonFlagCKKSRequestsTLKUpload]) { [flags _onqueueRemoveFlag:OctagonFlagCKKSRequestsTLKUpload]; return [OctagonStateTransitionOperation named:@"ckks-assist" entering:OctagonStateAssistCKKSTLKUpload]; } - if([flags _onqueueContains:OctagonFlagCuttlefishNotification]) { - [flags _onqueueRemoveFlag:OctagonFlagCuttlefishNotification]; - secnotice("octagon", "Updating TPH (while ready) due to push"); - return [OctagonStateTransitionOperation named:@"octagon-update" - entering:OctagonStateReadyUpdated]; + if([flags _onqueueContains:OctagonFlagAttemptBottleTLKExtraction]) { + [flags _onqueueRemoveFlag:OctagonFlagAttemptBottleTLKExtraction]; + if(_bottleID && _entropy && _bottleSalt) { + // Reuse the vouch-with-bottle operation. That'll make us a new voucher, but as a side effect, it will extract TLKs. + return [[OTVouchWithBottleOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBecomeReady + errorState:OctagonStateBecomeReady + bottleID:_bottleID + entropy:_entropy + bottleSalt:_bottleSalt + saveVoucher:NO]; + } else { + secnotice("octagon", "Received an suggestion to retry TLK extraction via bottle, but have no entropy stashed"); + } + } + + if([flags _onqueueContains:OctagonFlagAttemptRecoveryKeyTLKExtraction]) { + [flags _onqueueRemoveFlag:OctagonFlagAttemptRecoveryKeyTLKExtraction]; + if(_recoveryKey) { + // Reuse the vouch-with-rk operation. That'll make us a new voucher, but as a side effect, it will extract TLKs. + return [[OTVouchWithRecoveryKeyOperation alloc] initWithDependencies:self.operationDependencies + intendedState:OctagonStateBecomeReady + errorState:OctagonStateBecomeReady + recoveryKey:_recoveryKey + saveVoucher:NO]; + } else { + secnotice("octagon", "Received an suggestion to retry TLK extraction via RK, but have no recovery key stashed"); + } } if([flags _onqueueContains:OctagonFlagFetchAuthKitMachineIDList]) { @@ -1269,6 +1308,27 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } } + if([flags _onqueueContains:OctagonFlagAttemptUserControllableViewStatusUpgrade]) { + [flags _onqueueRemoveFlag:OctagonFlagAttemptUserControllableViewStatusUpgrade]; + secnotice("octagon", "Attempting user-view control upgrade"); + return [OctagonStateTransitionOperation named:@"attempt-user-view-upgrade" + entering:OctagonStateSetUserControllableViewsToPeerConsensus]; + } + + if([flags _onqueueContains:OctagonFlagCKKSRequestsPolicyCheck]) { + [flags _onqueueRemoveFlag:OctagonFlagCKKSRequestsPolicyCheck]; + secnotice("octagon", "Updating CKKS policy"); + return [OctagonStateTransitionOperation named:@"ckks-policy-update" + entering:OctagonStateReadyUpdated]; + } + + if([flags _onqueueContains:OctagonFlagCKKSViewSetChanged]) { + // We want to tell CKKS that we're trusted again. + [flags _onqueueRemoveFlag:OctagonFlagCKKSViewSetChanged]; + return [OctagonStateTransitionOperation named:@"ckks-update-trust" + entering:OctagonStateBecomeReady]; + } + if([flags _onqueueContains:OctagonFlagAccountIsAvailable]) { // We're in ready--we already know the account is available secnotice("octagon", "Removing 'account is available' flag"); @@ -1287,7 +1347,6 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; [flags _onqueueRemoveFlag:OctagonFlagCDPEnabled]; } - secnotice("octagon", "Entering state ready"); [[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:OctagonAnalyticsLastKeystateReady]; [self.launchSequence launch]; return nil; @@ -1319,7 +1378,9 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; OTAccountMetadataClassC* account = [self.accountMetadataStore loadOrCreateAccountMetadata:&localError]; if(localError && [self.lockStateTracker isLockedError:localError]){ secnotice("octagon", "Device is locked! pending initialization on unlock"); - op.nextState = OctagonStateWaitForUnlock; + // Since we can't load a class C item, we go to a different waitforunlock state. + // That way, we'll be less likely for an RPC to break us. + op.nextState = OctagonStateWaitForClassCUnlock; return; } @@ -1336,6 +1397,20 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; // This seems an odd place to do this, but CKKS currently also tracks the CloudKit account state. // Since we think we have an HSA2 account, let CKKS figure out its own CloudKit state secnotice("octagon-ckks", "Initializing CKKS views"); + [self.cuttlefishXPCWrapper fetchCurrentPolicyWithContainer:self.containerName + context:self.contextID + modelIDOverride:self.deviceAdapter.modelID + reply:^(TPSyncingPolicy * _Nullable syncingPolicy, + TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers, + NSError * _Nullable policyError) { + if(!syncingPolicy || policyError) { + secnotice("octagon-ckks", "Unable to fetch initial syncing policy: %@", policyError); + } else { + secnotice("octagon-ckks", "Fetched initial syncing policy: %@", syncingPolicy); + [self.viewManager setCurrentSyncingPolicy:syncingPolicy]; + } + }]; + [self.viewManager createViews]; [self.viewManager beginCloudKitOperationOfAllViews]; @@ -1383,7 +1458,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; intending:OctagonStateCuttlefishTrustCheck errorState:OctagonStatePostRepairCFU withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { - [self checkTrustStatusAndPostRepairCFUIfNecessary:^(CliqueStatus status, BOOL posted, BOOL hasIdentity, NSError *trustFromTPHError) { + [self checkTrustStatusAndPostRepairCFUIfNecessary:^(CliqueStatus status, BOOL posted, BOOL hasIdentity, BOOL isLocked, NSError *trustFromTPHError) { [[CKKSAnalytics logger] logResultForEvent:OctagonEventTPHHealthCheckStatus hardFailure:false result:trustFromTPHError]; if(trustFromTPHError) { @@ -1391,7 +1466,10 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; op.error = trustFromTPHError; op.nextState = OctagonStateError; } else { - if(hasIdentity == NO) { + if (isLocked == YES) { + op.nextState = OctagonStateWaitForUnlock; + secnotice("octagon-health", "TPH says device is locked!"); + } else if (hasIdentity == NO) { op.nextState = OctagonStateUntrusted; } else if(hasIdentity == YES && status == CliqueStatusIn){ secnotice("octagon-health", "TPH says we're trusted and in"); @@ -1440,8 +1518,8 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if(shouldPost) { secnotice("octagon-health", "Posting Escrow CFU"); NSError* postEscrowCFUError = nil; - [self postConfirmPasscodeCFU:&postEscrowCFUError]; - if(postEscrowCFUError) { + BOOL ret = [self postConfirmPasscodeCFU:&postEscrowCFUError]; + if(!ret) { op.error = postEscrowCFUError; } } else { @@ -1468,31 +1546,54 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; intending:OctagonStateUntrusted errorState:OctagonStateError withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { + __block BOOL deviceIsLocked = NO; [self checkTrustStatusAndPostRepairCFUIfNecessary:^(CliqueStatus status, BOOL posted, BOOL hasIdentity, + BOOL isLocked, NSError * _Nullable postError) { if(postError) { secerror("ocagon-health: failed to post repair cfu via state machine: %@", postError); + } else if (isLocked) { + deviceIsLocked = isLocked; + secnotice("octagon-health", "device is locked, not posting cfu"); } else { secnotice("octagon-health", "posted repair cfu via state machine"); } }]; - op.nextState = OctagonStateUntrusted; + if (deviceIsLocked == YES) { + op.nextState = OctagonStateWaitForUnlock; + } else { + op.nextState = OctagonStateUntrusted; + } }]; } -- (CKKSResultOperation* _Nullable)cloudKitAccountNewlyAvailableOperation +- (CKKSResultOperation* _Nullable)cloudKitAccountNewlyAvailableOperation:(OctagonFlag*)warmEscrowCache { WEAKIFY(self); + return [OctagonStateTransitionOperation named:@"octagon-icloud-account-available" intending:OctagonStateDetermineCDPState errorState:OctagonStateError withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) { STRONGIFY(self); - // Register with APS, but don't bother to wait until it's complete. secnotice("octagon", "iCloud sign in occurred. Attemping to register with APS..."); - + // Check if escrow fetch flag is set to warm up the escrow cache + if(warmEscrowCache != nil && OctagonIsOptimizationEnabled()) { + secnotice("octagon-warm-escrowcache", "Beginning fetching escrow records to warm up the escrow cache in TPH"); + dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{ + STRONGIFY(self); + [self rpcFetchAllViableEscrowRecords:NO reply:^(NSArray *records, NSError *error) { + if(error){ + secerror("octagon-warm-escrowcache: failed to fetch escrow records, %@", error); + } else { + secnotice("octagon-warm-escrowcache", "Successfully fetched escrow records"); + } + }]; + }); + } + // Register with APS, but don't bother to wait until it's complete. CKContainer* ckContainer = [CKContainer containerWithIdentifier:self.containerName]; [ckContainer serverPreferredPushEnvironmentWithCompletionHandler: ^(NSString *apsPushEnvString, NSError *error) { STRONGIFY(self); @@ -1507,10 +1608,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } else { secnotice("octagonpush", "Registering for environment '%@'", apsPushEnvString); - OctagonAPSReceiver* aps = [OctagonAPSReceiver receiverForEnvironment:apsPushEnvString - namedDelegatePort:SecCKKSAPSNamedPort - apsConnectionClass:self.apsConnectionClass]; - [aps registerCuttlefishReceiver:self forContainerName:self.containerName]; + [self.apsReceiver registerForEnvironment:apsPushEnvString]; } }]; @@ -1531,6 +1629,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; NSString* egoPeerID, NSDictionary* _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError * _Nullable error) { BOOL hasIdentity = egoPeerID != nil; secnotice("octagon-health", "repairAccountIfTrustedByTPHWithIntendedState status: %ld, peerID: %@, isExcluded: %d error: %@", (long)status, egoPeerID, isExcluded, error); @@ -1541,6 +1640,12 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return; } + if (isLocked) { + secnotice("octagon-health", "device is locked"); + nextState = OctagonStateWaitForUnlock; + return; + } + if(OctagonAuthoritativeTrustIsEnabled() && hasIdentity && status == CliqueStatusIn) { secnotice("octagon-health", "TPH believes we're trusted, accepting ego peerID as %@", egoPeerID); @@ -1567,7 +1672,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return nextState; } -- (void)checkTrustStatusAndPostRepairCFUIfNecessary:(void (^ _Nullable)(CliqueStatus status, BOOL posted, BOOL hasIdentity, NSError * _Nullable error))reply +- (void)checkTrustStatusAndPostRepairCFUIfNecessary:(void (^ _Nullable)(CliqueStatus status, BOOL posted, BOOL hasIdentity, BOOL isLocked, NSError * _Nullable error))reply { WEAKIFY(self); OTOperationConfiguration *configuration = [[OTOperationConfiguration alloc] init]; @@ -1575,6 +1680,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; NSString* _Nullable egoPeerID, NSDictionary* _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError * _Nullable error) { STRONGIFY(self); @@ -1582,7 +1688,13 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; BOOL hasIdentity = egoPeerID != nil; if (error && error.code != errSecInteractionNotAllowed) { - reply(status, NO, hasIdentity, error); + reply(status, NO, hasIdentity, isLocked, error); + return; + } + + if (isLocked) { + secnotice("octagon", "device is locked; not posting CFU"); + reply(status, NO, hasIdentity, isLocked, error); return; } @@ -1605,7 +1717,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } if(!phonePeerPresent) { secnotice("octagon", "No iOS peers in account; not posting CFU"); - reply(status, NO, hasIdentity, nil); + reply(status, NO, hasIdentity, isLocked, nil); return; } #endif @@ -1631,7 +1743,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if(circleError && [circleError.domain isEqualToString:(__bridge NSString*)kSOSErrorDomain] && circleError.code == kSOSErrorNotReady) { secnotice("octagon", "SOS is not ready, not posting CFU until it becomes so"); - reply(status, NO, hasIdentity, nil); + reply(status, NO, hasIdentity, isLocked, nil); return; } else if(circleError) { @@ -1640,7 +1752,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } else if(sosStatus == kSOSCCInCircle) { secnotice("octagon", "SOS is InCircle, not posting CFU"); - reply(status, NO, hasIdentity, nil); + reply(status, NO, hasIdentity, isLocked, nil); return; } else { secnotice("octagon", "SOS is %@, posting CFU", (__bridge NSString*)SOSCCGetStatusDescription(sosStatus)); @@ -1651,10 +1763,10 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if(OctagonAuthoritativeTrustIsEnabled() && (status == CliqueStatusNotIn || status == CliqueStatusAbsent || isExcluded)) { NSError* localError = nil; BOOL posted = [self postRepairCFU:&localError]; - reply(status, posted, hasIdentity, localError); + reply(status, posted, hasIdentity, isLocked, localError); return; } - reply(status, NO, hasIdentity, nil); + reply(status, NO, hasIdentity, isLocked, nil); return; }]; } @@ -1699,16 +1811,26 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; [self.accountStateTracker triggerOctagonStatusFetch]; } - [self checkTrustStatusAndPostRepairCFUIfNecessary:^(CliqueStatus status, BOOL posted, BOOL hasIdentity, NSError * _Nullable postError) { + __block BOOL deviceIsLocked = NO; + [self checkTrustStatusAndPostRepairCFUIfNecessary:^(CliqueStatus status, BOOL posted, BOOL hasIdentity, BOOL isLocked, NSError * _Nullable postError) { [[CKKSAnalytics logger] logResultForEvent:OctagonEventCheckTrustForCFU hardFailure:false result:postError]; if(postError){ secerror("octagon: cfu failed to post"); + } else if (isLocked == YES) { + deviceIsLocked = isLocked; + secerror("octagon: device is locked, not posting cfu"); } else { secnotice("octagon", "clique status: %@, posted cfu: %d", OTCliqueStatusToString(status), !!posted); } }]; + if (deviceIsLocked == YES) { + secnotice("octagon", "device is locked, state moving to wait for unlock"); + op.nextState = OctagonStateWaitForUnlock; + return; + } + [self.accountMetadataStore persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { metadata.trustState = OTAccountMetadataClassC_TrustState_UNTRUSTED; return metadata; @@ -1727,6 +1849,15 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; [view endTrustedOperation]; } + // We are no longer in a CKKS4All world. Tell SOS! + if(self.sosAdapter.sosEnabled) { + NSError* soserror = nil; + [self.sosAdapter updateCKKS4AllStatus:NO error:&soserror]; + if(soserror) { + secnotice("octagon-ckks", "Unable to disable the CKKS4All status in SOS: %@", soserror); + } + } + /* * Initial notification that we let the world know that trust is up and doing something */ @@ -1761,13 +1892,12 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; __block NSString* peerID = nil; NSError* localError = nil; - __block NSSet* viewList = nil; - __block TPPolicy* policy = nil; + __block TPSyncingPolicy* policy = nil; [self.accountMetadataStore persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { peerID = metadata.peerID; - viewList = metadata.syncingViews.count > 0 ? [NSSet setWithArray:metadata.syncingViews] : nil; - policy = metadata.hasSyncingPolicy ? [metadata getTPPolicy] : nil; + + policy = metadata.hasSyncingPolicy ? [metadata getTPSyncingPolicy] : nil; if(metadata.attemptedJoin == OTAccountMetadataClassC_AttemptedAJoinState_ATTEMPTED) { return nil; @@ -1778,17 +1908,37 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if(!peerID || localError) { secerror("octagon-ckks: No peer ID to pass to CKKS. Syncing will be disabled."); - } else if(!viewList || !policy) { + } else if(!policy) { secerror("octagon-ckks: No memoized CKKS policy, re-fetching"); op.nextState = OctagonStateRefetchCKKSPolicy; return; } else { - secnotice("octagon-ckks", "Initializing CKKS views with view list %@ and policy %@", viewList, policy); - [self.viewManager setSyncingViews:viewList - sortingPolicy:policy]; + if(policy.syncUserControllableViews == TPPBPeerStableInfo_UserControllableViewStatus_UNKNOWN) { + secnotice("octagon-ckks", "Memoized CKKS policy has no opinion of user-controllable view status"); + // Suggest the update, whenever possible + OctagonPendingFlag* pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptUserControllableViewStatusUpgrade + conditions:OctagonPendingConditionsDeviceUnlocked]; + [self.stateMachine handlePendingFlag:pendingFlag]; + } else { + // We are now in a CKKS4All world. Tell SOS! + if(self.sosAdapter.sosEnabled) { + NSError* soserror = nil; + [self.sosAdapter updateCKKS4AllStatus:YES error:&soserror]; + if(soserror) { + secnotice("octagon-ckks", "Unable to enable the CKKS4All status in SOS: %@", soserror); + } + } + } + + secnotice("octagon-ckks", "Initializing CKKS views with policy %@: %@", policy, policy.viewList); - OctagonCKKSPeerAdapter* octagonAdapter = [[OctagonCKKSPeerAdapter alloc] initWithPeerID:peerID operationDependencies:[self operationDependencies]]; + [self.viewManager setCurrentSyncingPolicy:policy]; + + OctagonCKKSPeerAdapter* octagonAdapter = [[OctagonCKKSPeerAdapter alloc] initWithPeerID:peerID + containerName:self.containerName + contextID:self.contextID + cuttlefishXPC:self.cuttlefishXPCWrapper]; // This octagon adapter must be able to load the self peer keys, or we're in trouble. NSError* egoPeerKeysError = nil; @@ -1824,7 +1974,8 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } [view beginTrustedOperation:peerProviders - suggestTLKUpload:self.suggestTLKUploadNotifier]; + suggestTLKUpload:self.suggestTLKUploadNotifier + requestPolicyCheck:self.requestPolicyCheckNotifier]; } } [self notifyTrustChanged:OTAccountMetadataClassC_TrustState_TRUSTED]; @@ -1875,7 +2026,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } if (ckDeviceId) { NSString *selfDeviceID = self.viewManager.accountTracker.ckdeviceID; - if (![selfDeviceID isEqualToString:serialNumber]) { + if (serialNumber == nil || ![selfDeviceID isEqualToString:serialNumber]) { secnotice("octagon", "TTR request not for me (deviceId)"); return; } @@ -1999,7 +2150,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; if(accountMetadata.lastHealthCheckup == 0) { return nil; } - return [[NSDate alloc] initWithTimeIntervalSince1970: accountMetadata.lastHealthCheckup]; + return [[NSDate alloc] initWithTimeIntervalSince1970: ((NSTimeInterval)accountMetadata.lastHealthCheckup) / 1000.0]; } - (void)requestTrustedDeviceListRefresh @@ -2086,6 +2237,21 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; haveAccount = false; } }); + + if(!haveAccount) { + // Right after account sign-in, it's possible that the CK account exists, but that we just haven't learned about + // it yet, and still have the 'no account' state cached. So, let's check in... + secnotice("octagon-ck", "No CK account present. Attempting to refetch CK account status..."); + if(![self.accountStateTracker notifyCKAccountStatusChangeAndWait:timeout]) { + secnotice("octagon-ck", "Fetching new CK account status did not complete in time"); + } + + // After the above call finishes, we should have a fresh value in self.cloudKitAccountInfo + dispatch_sync(self.queue, ^{ + haveAccount = self.cloudKitAccountInfo.accountStatus == CKKSAccountStatusAvailable; + }); + secnotice("octagon-ck", "After refetch, CK account status is %@", haveAccount ? @"present" : @"missing"); + } return haveAccount ? CKKSAccountStatusAvailable : CKKSAccountStatusNoAccount; } @@ -2156,10 +2322,10 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return; } --(void)joinWithBottle:(NSString*)bottleID - entropy:(NSData *)entropy - bottleSalt:(NSString *)bottleSalt - reply:(void (^)(NSError * _Nullable error))reply +- (void)joinWithBottle:(NSString*)bottleID + entropy:(NSData *)entropy + bottleSalt:(NSString *)bottleSalt + reply:(void (^)(NSError * _Nullable error))reply { _bottleID = bottleID; _entropy = entropy; @@ -2213,19 +2379,22 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return @{ OctagonStateInitiatorSetCDPBit: @{ OctagonStateInitiatorUpdateDeviceList: @{ - OctagonStateInitiatorJoin: @{ - OctagonStateBecomeReady: @{ - OctagonStateReady: [OctagonStateTransitionPathStep success], - }, - - OctagonStateInitiatorJoinCKKSReset: @{ - OctagonStateInitiatorJoinAfterCKKSReset: @{ - OctagonStateBecomeReady: @{ - OctagonStateReady: [OctagonStateTransitionPathStep success] + OctagonStateInitiatorJoin: @{ + OctagonStateBottlePreloadOctagonKeysInSOS: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success], + }, + }, + OctagonStateInitiatorJoinCKKSReset: @{ + OctagonStateInitiatorJoinAfterCKKSReset: @{ + OctagonStateBottlePreloadOctagonKeysInSOS: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success] + }, + }, + }, }, - }, }, - }, }, }, }; @@ -2236,15 +2405,24 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; reply:(void (^)(NSError * _Nullable error))reply { - _vouchData = vouchData; - _vouchSig = vouchSig; - if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { secnotice("octagon", "No cloudkit account present"); reply([self errorNoiCloudAccount]); return; } + NSError* metadataError = nil; + [self.accountMetadataStore persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.voucher = vouchData; + metadata.voucherSignature = vouchSig; + return metadata; + } error:&metadataError]; + if(metadataError) { + secnotice("octagon", "Unable to save voucher for joining: %@", metadataError); + reply(metadataError); + return; + } + NSMutableSet* sourceStates = [NSMutableSet setWithObject:OctagonStateInitiatorAwaitingVoucher]; OctagonStateTransitionPath* path = [OctagonStateTransitionPath pathFromDictionary:[self joinStatePathDictionary]]; @@ -2369,8 +2547,9 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } result[@"CoreFollowUp"] = [self.followupHandler sysdiagnoseStatus]; - result[@"lastOctagonPush"] = [[CKKSAnalytics logger] datePropertyForKey:CKKSAnalyticsLastOctagonPush]; + result[@"lastOctagonPush"] = [[CKKSAnalytics logger] datePropertyForKey:CKKSAnalyticsLastOctagonPush]; + result[@"pushEnvironments"] = [self.apsReceiver registeredPushEnvironments]; [self.cuttlefishXPCWrapper dumpWithContainer:self.containerName context:self.contextID @@ -2467,6 +2646,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; NSString* egoPeerID, NSDictionary* _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError *error))reply { CliqueStatus status = CliqueStatusAbsent; @@ -2477,8 +2657,8 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; status = CliqueStatusNotIn; } - secnotice("octagon", "returning cached clique status: %@", OTCliqueStatusToString(status)); - reply(status, account.peerID, nil, NO, NULL); + secinfo("octagon", "returning cached clique status: %@", OTCliqueStatusToString(status)); + reply(status, account.peerID, nil, NO, NO, NULL); } @@ -2487,6 +2667,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; NSString* _Nullable peerID, NSDictionary* _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError *error))reply { __block NSError* localError = nil; @@ -2494,13 +2675,13 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; OTAccountMetadataClassC* account = [self.accountMetadataStore loadOrCreateAccountMetadata:&localError]; if(localError && [self.lockStateTracker isLockedError:localError]){ secnotice("octagon", "Device is locked! pending initialization on unlock"); - reply(CliqueStatusError, nil, nil, NO, localError); + reply(CliqueStatusError, nil, nil, NO, NO, localError); return; } if(account.icloudAccountState == OTAccountMetadataClassC_AccountState_NO_ACCOUNT) { secnotice("octagon", "no account! returning clique status 'no account'"); - reply(CliqueStatusNoCloudKitAccount, nil, nil, NO, NULL); + reply(CliqueStatusNoCloudKitAccount, nil, nil, NO, NO, NULL); return; } @@ -2512,7 +2693,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; CKKSAccountStatus ckAccountStatus = [self checkForCKAccount:configuration]; if(ckAccountStatus == CKKSAccountStatusNoAccount) { secnotice("octagon", "No cloudkit account present"); - reply(CliqueStatusNoCloudKitAccount, nil, nil, NO, NULL); + reply(CliqueStatusNoCloudKitAccount, nil, nil, NO, NO, NULL); return; } else if(ckAccountStatus == CKKSAccountStatusUnknown) { secnotice("octagon", "Unknown cloudkit account status, returning cached trust value"); @@ -2524,6 +2705,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; __block NSDictionary* peerModelCounts = nil; __block BOOL excluded = NO; __block CliqueStatus trustStatus = CliqueStatusError; + __block BOOL isLocked = NO; [self.cuttlefishXPCWrapper trustStatusWithContainer:self.containerName context:self.contextID @@ -2533,6 +2715,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; peerID = egoStatus.egoPeerID; excluded = egoStatus.isExcluded; peerModelCounts = egoStatus.viablePeerCountsByModelID; + isLocked = egoStatus.isLocked; localError = xpcError; if(xpcError) { @@ -2573,7 +2756,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } }]; - reply(trustStatus, peerID, peerModelCounts, excluded, localError); + reply(trustStatus, peerID, peerModelCounts, excluded, isLocked, localError); } - (void)rpcFetchAllViableBottles:(void (^)(NSArray* _Nullable sortedBottleIDs, NSArray* _Nullable sortedPartialEscrowRecordIDs, NSError* _Nullable error))reply @@ -2599,6 +2782,51 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; }]; } +- (void)rpcFetchAllViableEscrowRecords:(BOOL)forceFetch reply:(void (^)(NSArray* _Nullable records, + NSError* _Nullable error))reply +{ + if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { + secnotice("octagon", "No cloudkit account present"); + reply(NULL, [self errorNoiCloudAccount]); + return; + } + + // As this isn't a state-modifying operation, we don't need to go through the state machine. + [self.cuttlefishXPCWrapper fetchViableEscrowRecordsWithContainer:self.containerName + context:self.contextID + forceFetch:(BOOL)forceFetch + reply:^(NSArray * _Nullable records, NSError * _Nullable error) { + if(error){ + secerror("octagon: error fetching all viable escrow records: %@", error); + reply(nil, error); + }else{ + secnotice("octagon", "fetched escrow records: %@", records); + + reply(records, error); + } + }]; +} + +- (void)rpcInvalidateEscrowCache:(void (^)(NSError* _Nullable error))reply +{ + if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { + secnotice("octagon", "No cloudkit account present"); + reply([self errorNoiCloudAccount]); + return; + } + + // As this isn't a state-modifying operation, we don't need to go through the state machine. + [self.cuttlefishXPCWrapper removeEscrowCacheWithContainer:self.containerName context:self.contextID reply:^(NSError * _Nullable removeError) { + if (removeError){ + secerror("octagon: failed to remove escrow cache: %@", removeError); + reply(removeError); + } else{ + secnotice("octagon", "successfully removed escrow cache"); + reply(nil); + } + }]; +} + - (void)fetchEscrowContents:(void (^)(NSData* _Nullable entropy, NSString* _Nullable bottleID, NSData* _Nullable signingPublicKey, @@ -2659,10 +2887,127 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; reply:reply]; } -#pragma mark --- Testing -- (void) setAccountStateHolder:(OTCuttlefishAccountStateHolder*)accountMetadataStore +- (void)rpcFetchUserControllableViewsSyncingStatus:(void (^)(BOOL areSyncing, NSError* _Nullable error))reply +{ + if(self.viewManager.policy) { + BOOL syncing = self.viewManager.policy.syncUserControllableViewsAsBoolean; + + secnotice("octagon-ckks", "Returning user-controllable status as %@ (%@)", + syncing ? @"enabled" : @"disabled", + TPPBPeerStableInfo_UserControllableViewStatusAsString(self.viewManager.policy.syncUserControllableViews)); + + reply(syncing, nil); + return; + } + + // No loaded policy? Let's trigger a fetch. + [self rpcRefetchCKKSPolicy:^(NSError * _Nullable error) { + if(error) { + secnotice("octagon-ckks", "Failed to fetch policy: %@", error); + reply(NO, error); + return; + } + + if(self.viewManager.policy) { + BOOL syncing = self.viewManager.policy.syncUserControllableViewsAsBoolean; + + secnotice("octagon-ckks", "Returning user-controllable status as %@ (%@)", + syncing ? @"enabled" : @"disabled", + TPPBPeerStableInfo_UserControllableViewStatusAsString(self.viewManager.policy.syncUserControllableViews)); + + reply(syncing, nil); + return; + + } else { + // The tests sometimes don't have a viewManager. If we're in the tests, try this last-ditch effort: + if(SecCKKSTestsEnabled()) { + NSError* metadataError = nil; + OTAccountMetadataClassC* accountState = [self.accountMetadataStore loadOrCreateAccountMetadata:&metadataError]; + if(metadataError) { + secnotice("octagon-ckks", "Error fetching acount state: %@", metadataError); + } + TPSyncingPolicy* policy = [accountState getTPSyncingPolicy]; + if(policy) { + BOOL syncing = policy.syncUserControllableViewsAsBoolean; + secnotice("octagon-ckks", "Returning user-controllable status (fetched from account state) as %@ (%@)", + syncing ? @"enabled" : @"disabled", + TPPBPeerStableInfo_UserControllableViewStatusAsString(self.viewManager.policy.syncUserControllableViews)); + reply(syncing, nil); + return; + } + } + + secnotice("octagon-ckks", "Policy missing even after a refetch?"); + reply(NO, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorSyncPolicyMissing + description:@"Sync policy is missing even after refetching"]); + return; + } + }]; +} + +- (void)rpcSetUserControllableViewsSyncingStatus:(BOOL)status reply:(void (^)(BOOL areSyncing, NSError* _Nullable error))reply { - self.accountMetadataStore = accountMetadataStore; +#if TARGET_OS_TV + // TVs can't set this value. + secnotice("octagon-ckks", "Rejecting set of user-controllable sync status due to platform"); + reply(NO, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNotSupported + description:@"This platform does not support setting the user-controllable view syncing status"]); +#else + + OctagonState* firstState = status ? OctagonStateEnableUserControllableViews : OctagonStateDisableUserControllableViews; + + secnotice("octagon-ckks", "Settting user-controllable sync status as '%@'", status ? @"enabled" : @"disabled"); + + [self.stateMachine doWatchedStateMachineRPC:@"octagon-set-policy" + sourceStates:[NSMutableSet setWithArray: @[OctagonStateReady]] + path:[OctagonStateTransitionPath pathFromDictionary:@{ + firstState: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success], + }, + }, + }] + reply:^(NSError * _Nullable error) { + if(error) { + secnotice("octagon-ckks", "Failed to set sync policy to '%@': %@", status ? @"enabled" : @"disabled", error); + reply(NO, error); + return; + } + + if(self.viewManager.policy) { + BOOL finalStatus = self.viewManager.policy.syncUserControllableViewsAsBoolean; + secnotice("octagon-ckks", "User-controllable sync status is set as '%@'", finalStatus ? @"enabled" : @"disabled"); + reply(finalStatus, nil); + return; + } + + // The tests sometimes don't have a viewManager. If we're in the tests, try this last-ditch effort: + if(SecCKKSTestsEnabled()) { + NSError* metadataError = nil; + OTAccountMetadataClassC* accountState = [self.accountMetadataStore loadOrCreateAccountMetadata:&metadataError]; + if(metadataError) { + secnotice("octagon-ckks", "Error fetching acount state: %@", metadataError); + } + TPSyncingPolicy* policy = [accountState getTPSyncingPolicy]; + if(policy) { + BOOL syncing = policy.syncUserControllableViewsAsBoolean; + secnotice("octagon-ckks", "Returning user-controllable status (fetched from account state) as %@ (%@)", + syncing ? @"enabled" : @"disabled", + TPPBPeerStableInfo_UserControllableViewStatusAsString(self.viewManager.policy.syncUserControllableViews)); + reply(syncing, nil); + return; + } + } + + secnotice("octagon-ckks", "Policy missing even after a refetch?"); + reply(NO, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorSyncPolicyMissing + description:@"Sync policy is missing even after refetching"]); + return; + }]; +#endif } #pragma mark --- Health Checker @@ -2735,17 +3080,16 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; return YES; } -- (void)postConfirmPasscodeCFU:(NSError**)error +- (BOOL)postConfirmPasscodeCFU:(NSError**)error { + BOOL ret = NO; NSError* localError = nil; - [self.followupHandler postFollowUp:OTFollowupContextTypeOfflinePasscodeChange error:&localError]; + ret = [self.followupHandler postFollowUp:OTFollowupContextTypeOfflinePasscodeChange error:&localError]; if(localError){ secerror("octagon-health: CoreCDP offline passcode change failed: %@", localError); *error = localError; } - else{ - secnotice("octagon-health", "CoreCDP offline passcode change success"); - } + return ret; } - (void)checkOctagonHealth:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError * _Nullable error))reply @@ -2772,6 +3116,7 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; OctagonStateHealthCheckReset: [OctagonStateTransitionPathStep success], OctagonStateHealthCheckLeaveClique: [OctagonStateTransitionPathStep success], }, + OctagonStateWaitForUnlock: [OctagonStateTransitionPathStep success], }, }, OctagonStateWaitForCDP: [OctagonStateTransitionPathStep success], @@ -2782,52 +3127,27 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; reply:reply]; } -- (void)attemptSOSUpgrade:(void (^)(NSError* _Nullable error))reply -{ - secnotice("octagon-sos", "attempting to perform an sos upgrade"); - - if ([self checkForCKAccount:nil] != CKKSAccountStatusAvailable) { - secnotice("octagon-sos", "No cloudkit account present"); - reply([self errorNoiCloudAccount]); - return; - } - - NSSet* sourceStates = [NSSet setWithArray: @[OctagonStateUntrusted]]; - - OTSOSUpgradeOperation *pendingOp = [[OTSOSUpgradeOperation alloc] initWithDependencies:self.operationDependencies - intendedState:OctagonStateBecomeReady - ckksConflictState:OctagonStateBecomeUntrusted - errorState:OctagonStateBecomeUntrusted - deviceInfo:self.prepareInformation - policyOverride:self.policyOverride]; - - OctagonStateTransitionRequest* request = [[OctagonStateTransitionRequest alloc] init:@"attempt-sos-upgrade" - sourceStates:sourceStates - serialQueue:self.queue - timeout:OctagonStateTransitionDefaultTimeout - transitionOp:pendingOp]; - - CKKSResultOperation* callback = [CKKSResultOperation named:@"sos-upgrade-callback" - withBlock:^{ - secnotice("otrpc", "Returning from an sos upgrade attempt: %@", pendingOp.error); - [[CKKSAnalytics logger] logResultForEvent:OctagonEventUpgradePreapprovedJoinAfterPairing hardFailure:false result:pendingOp.error]; - reply(pendingOp.error); - }]; - - [callback addDependency:pendingOp]; - [self.operationQueue addOperation: callback]; - - [self.stateMachine handleExternalRequest:request]; -} - - (void)waitForOctagonUpgrade:(void (^)(NSError* error))reply { secnotice("octagon-sos", "waitForOctagonUpgrade"); + NSError* localError = nil; + if (!self.sosAdapter.sosEnabled) { secnotice("octagon-sos", "sos not enabled, nothing to do for waitForOctagonUpgrade"); reply(nil); return; + } else if ([self.sosAdapter circleStatus:&localError] != kSOSCCInCircle) { + secnotice("octagon-sos", "SOS circle status: %d, cannot perform sos upgrade", [self.sosAdapter circleStatus:&localError]); + if (localError == nil) { + localError = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:kSOSErrorNoCircle userInfo:@{NSLocalizedDescriptionKey : @"Not in circle"}]; + } else { + secerror("octagon-sos: error retrieving circle status: %@", localError); + } + reply(localError); + return; + } else { + secnotice("octagon-sos", "in sos circle!, attempting upgrade"); } if ([self.stateMachine isPaused]) { @@ -2846,12 +3166,15 @@ static dispatch_time_t OctagonStateTransitionDefaultTimeout = 10*NSEC_PER_SEC; } } - NSSet* sourceStates = [NSSet setWithArray: @[OctagonStateUntrusted]]; + NSSet* sourceStates = [NSSet setWithArray: @[OctagonStateWaitForCDP, + OctagonStateUntrusted]]; OctagonStateTransitionPath* path = [OctagonStateTransitionPath pathFromDictionary:@{ - OctagonStateAttemptSOSUpgrade: @{ - OctagonStateBecomeReady: @{ - OctagonStateReady: [OctagonStateTransitionPathStep success], + OctagonStateAttemptSOSUpgradeDetermineCDPState: @{ + OctagonStateAttemptSOSUpgrade: @{ + OctagonStateBecomeReady: @{ + OctagonStateReady: [OctagonStateTransitionPathStep success], + }, }, }, }]; diff --git a/keychain/ot/OTDefines.h b/keychain/ot/OTDefines.h index d391c48f..952a1bd5 100644 --- a/keychain/ot/OTDefines.h +++ b/keychain/ot/OTDefines.h @@ -36,11 +36,8 @@ extern NSString* const OctagonEventAttributeTimeSinceLastPostedFollowUp; extern NSString* OTCKContainerName; extern NSString* const CuttlefishTrustZone; -extern NSString* const CuttlefishErrorDomain; extern NSString* const TrustedPeersHelperErrorDomain; -extern NSString* const CuttlefishErrorRetryAfterKey; - /* Octagon Errors */ typedef NS_ERROR_ENUM(OctagonErrorDomain, OctagonError) { //OTErrorNoColumn = 1, @@ -91,6 +88,7 @@ typedef NS_ERROR_ENUM(OctagonErrorDomain, OctagonError) { OTAuthKitMachineIDMissing = 46, OTAuthKitPrimaryAccountHaveNoDSID = 47, OTErrorFailedToLeaveClique = 48, + OTErrorSyncPolicyMissing = 49, }; #define OTMasterSecretLength 72 @@ -100,6 +98,7 @@ typedef NS_ENUM(NSInteger, TrustedPeersHelperErrorCode) { TrustedPeersHelperErrorNoPeersPreapprovePreparedIdentity = 14, TrustedPeersHelperErrorCodeUntrustedRecoveryKeys = 32, TrustedPeersHelperErrorCodeNotEnrolled = 34, + TrustedPeersHelperErrorNoPeersPreapprovedBySelf = 47, }; // See cuttlefish/CuttlefishService/Sources/CuttlefishService/CuttlefishError.swift @@ -127,6 +126,9 @@ typedef NS_ENUM(NSInteger, CuttlefishErrorCode) { CuttlefishErrorPreflightGraphValidationError = 1022, CuttlefishErrorKeyHierarchyAlreadyExists = 1033, CuttlefishErrorDuplicatePeerIdUnderConsideration = 1034, + CuttlefishErrorIneligibleExclusionDenied = 1035, + CuttlefishErrorMultiplePreapprovedJoinDenied = 1036, + CuttlefishErrorUpdateTrustPeerNotFound = 1037, }; NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTDefines.m b/keychain/ot/OTDefines.m index 0aa95a36..476426dd 100644 --- a/keychain/ot/OTDefines.m +++ b/keychain/ot/OTDefines.m @@ -31,7 +31,5 @@ NSString* const OctagonEventAttributeTimeSinceLastPostedFollowUp = @"TimeSinceLa NSString* OTCKContainerName = @"com.apple.security.keychain"; NSString* const CuttlefishTrustZone = @"CuttlefishTrustZone"; -NSString* const CuttlefishErrorDomain = @"CuttlefishError"; NSString* const TrustedPeersHelperErrorDomain = @"com.apple.security.trustedpeers.container"; -NSString* const CuttlefishErrorRetryAfterKey = @"retryafter"; diff --git a/keychain/ot/OTDetermineCDPBitStatusOperation.m b/keychain/ot/OTDetermineCDPBitStatusOperation.m index 8ad69c12..b776287b 100644 --- a/keychain/ot/OTDetermineCDPBitStatusOperation.m +++ b/keychain/ot/OTDetermineCDPBitStatusOperation.m @@ -57,7 +57,7 @@ OTAccountMetadataClassC* account = [self.deps.stateHolder loadOrCreateAccountMetadata:&localError]; if(localError && [self.deps.lockStateTracker isLockedError:localError]) { secnotice("octagon-cdp-status", "Device is locked! restarting on unlock"); - self.nextState = OctagonStateWaitForUnlock; + self.nextState = OctagonStateWaitForClassCUnlock; return; } diff --git a/keychain/ot/OTDeviceInformationAdapter.h b/keychain/ot/OTDeviceInformationAdapter.h index 43279916..f283c950 100644 --- a/keychain/ot/OTDeviceInformationAdapter.h +++ b/keychain/ot/OTDeviceInformationAdapter.h @@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSString*)osVersion; /* Returns the serial number as a string. */ -- (NSString*)serialNumber; +- (NSString* _Nullable)serialNumber; /* register for deviceName updates */ - (void)registerForDeviceNameUpdates:(id)listener; diff --git a/keychain/ot/OTDeviceInformationAdapter.m b/keychain/ot/OTDeviceInformationAdapter.m index acd71ebe..9e8cf990 100644 --- a/keychain/ot/OTDeviceInformationAdapter.m +++ b/keychain/ot/OTDeviceInformationAdapter.m @@ -107,7 +107,7 @@ static void updateDeviceNameChanges(SCDynamicStoreRef store, CFArrayRef keys, vo #else -- (NSString*)serialNumber +- (NSString* _Nullable)serialNumber { io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); if (platformExpert == MACH_PORT_NULL) { diff --git a/keychain/ot/OTEnsureOctagonKeyConsistency.m b/keychain/ot/OTEnsureOctagonKeyConsistency.m index bb86a39c..965fb863 100644 --- a/keychain/ot/OTEnsureOctagonKeyConsistency.m +++ b/keychain/ot/OTEnsureOctagonKeyConsistency.m @@ -95,10 +95,16 @@ return; } - OctagonCKKSPeerAdapter* octagonAdapter = [[OctagonCKKSPeerAdapter alloc] initWithPeerID:octagonPeerID operationDependencies:self.deps]; + OctagonCKKSPeerAdapter* octagonAdapter = [[OctagonCKKSPeerAdapter alloc] initWithPeerID:octagonPeerID + containerName:self.deps.containerName + contextID:self.deps.contextID + cuttlefishXPC:self.deps.cuttlefishXPCWrapper]; + + secnotice("octagon", "Fetched SOS Self! Fetching Octagon Adapter now: %@", octagonAdapter); NSError* fetchSelfPeersError = nil; CKKSSelves *selfPeers = [octagonAdapter fetchSelfPeers:&fetchSelfPeersError]; + if((!selfPeers) || fetchSelfPeersError) { secnotice("octagon", "failed to retrieve self peers: %@", fetchSelfPeersError); self.error = fetchSelfPeersError; @@ -122,8 +128,8 @@ if(![octagonSigningKeyData isEqualToData:sosSigningKeyData] || ![octagonEncryptionKeyData isEqualToData:sosEncryptionKeyData]) { secnotice("octagon", "SOS and Octagon signing keys do NOT match! updating SOS"); NSError* updateError = nil; - [self.deps.sosAdapter updateOctagonKeySetWithAccount:currentSelfPeer error:&updateError]; - if(updateError) { + BOOL ret = [self.deps.sosAdapter updateOctagonKeySetWithAccount:currentSelfPeer error:&updateError]; + if(!ret) { self.error = updateError; [self runBeforeGroupFinished:self.finishOp]; return; diff --git a/keychain/ot/OTEstablishOperation.m b/keychain/ot/OTEstablishOperation.m index 0acbd9ff..93c6689c 100644 --- a/keychain/ot/OTEstablishOperation.m +++ b/keychain/ot/OTEstablishOperation.m @@ -75,7 +75,8 @@ [self dependOnBeforeGroupFinished:self.finishedOp]; // First, interrogate CKKS views, and see when they have a TLK proposal. - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.operationDependencies]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.operationDependencies + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"establish-with-keys" @@ -120,7 +121,10 @@ ckksKeys:viewKeySets tlkShares:pendingTLKShares preapprovedKeys:publicSigningSPKIs - reply:^(NSString * _Nullable peerID, NSArray* _Nullable keyHierarchyRecords, NSError * _Nullable error) { + reply:^(NSString * _Nullable peerID, + NSArray* _Nullable keyHierarchyRecords, + TPSyncingPolicy* _Nullable syncingPolicy, + NSError * _Nullable error) { STRONGIFY(self); [[CKKSAnalytics logger] logResultForEvent:OctagonEventEstablishIdentity hardFailure:true result:error]; @@ -141,10 +145,12 @@ NSError* localError = nil; BOOL persisted = [self.operationDependencies.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { - metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; - metadata.peerID = peerID; - return metadata; - } error:&localError]; + metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; + metadata.peerID = peerID; + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&localError]; + if(!persisted || localError) { secnotice("octagon", "Couldn't persist results: %@", localError); self.error = localError; @@ -152,6 +158,8 @@ self.nextState = self.intendedState; } + [self.operationDependencies.viewManager setCurrentSyncingPolicy:syncingPolicy]; + // Tell CKKS about our shiny new records! for (id key in self.operationDependencies.viewManager.views) { CKKSKeychainView* view = self.operationDependencies.viewManager.views[key]; diff --git a/keychain/ot/OTFetchCKKSKeysOperation.h b/keychain/ot/OTFetchCKKSKeysOperation.h index 5bd5a0ee..bb2e1d98 100644 --- a/keychain/ot/OTFetchCKKSKeysOperation.h +++ b/keychain/ot/OTFetchCKKSKeysOperation.h @@ -2,6 +2,7 @@ #if OCTAGON #import +#import #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ckks/CKKSKeychainBackedKey.h" @@ -24,7 +25,15 @@ NS_ASSUME_NONNULL_BEGIN // Any new TLKShares that CKKS suggested we upload along with this keyset @property NSArray* pendingTLKShares; -- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies; +// Any views that didn't provide a keyset within time +@property NSSet* viewsTimedOutWithoutKeysets; + +// Set this to configure how long to wait for CKKS to resonse +@property dispatch_time_t desiredTimeout; + +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + refetchNeeded:(BOOL)refetchNeeded; +; - (instancetype)initWithViews:(NSSet*)views; @end diff --git a/keychain/ot/OTFetchCKKSKeysOperation.m b/keychain/ot/OTFetchCKKSKeysOperation.m index 13613b2e..7380f780 100644 --- a/keychain/ot/OTFetchCKKSKeysOperation.m +++ b/keychain/ot/OTFetchCKKSKeysOperation.m @@ -8,11 +8,14 @@ @interface OTFetchCKKSKeysOperation () @property NSSet* views; @property CKKSViewManager* manager; + +@property BOOL fetchBeforeGettingKeyset; @end @implementation OTFetchCKKSKeysOperation - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + refetchNeeded:(BOOL)refetchNeeded { if((self = [super init])) { _manager = dependencies.viewManager; @@ -21,6 +24,12 @@ _tlkShares = @[]; _pendingTLKShares = @[]; _incompleteKeySets = @[]; + + _desiredTimeout = SecCKKSTestsEnabled() ? 5*NSEC_PER_SEC : 15*NSEC_PER_SEC; + + _fetchBeforeGettingKeyset = refetchNeeded; + + _viewsTimedOutWithoutKeysets = [NSSet set]; } return self; } @@ -34,6 +43,12 @@ _tlkShares = @[]; _pendingTLKShares = @[]; _incompleteKeySets = @[]; + + _desiredTimeout = SecCKKSTestsEnabled() ? 5*NSEC_PER_SEC : 15*NSEC_PER_SEC; + + _fetchBeforeGettingKeyset = NO; + + _viewsTimedOutWithoutKeysets = [NSSet set]; } return self; } @@ -53,60 +68,70 @@ for (CKKSKeychainView* view in self.views) { secnotice("octagon-ckks", "Waiting for %@", view); - [keyOps addObject:[[view findKeySet] timeout:45*NSEC_PER_SEC]]; + [keyOps addObject:[[view findKeySet:self.fetchBeforeGettingKeyset] timeout:self.desiredTimeout]]; } WEAKIFY(self); CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"proceed-with-ckks-keys" withBlock:^{ - STRONGIFY(self); - - NSMutableArray* viewKeySets = [NSMutableArray array]; - NSMutableArray* ckksBrokenKeySets = [NSMutableArray array]; - NSMutableArray* tlkShares = [NSMutableArray array]; - NSMutableArray* pendingTLKShares = [NSMutableArray array]; - - for(CKKSResultOperation* op in keyOps) { - if(op.error) { - secnotice("octagon-ckks", "No keys for zone %@: %@", op.zoneName, op.error); - continue; - } - - NSError* localerror = nil; - CKKSKeychainBackedKeySet* keyset = [op.keyset asKeychainBackedSet:&localerror]; - - if(keyset) { - secnotice("octagon-ckks", "Have proposed keys: %@", op.keyset); - [viewKeySets addObject:keyset]; - } else { - secnotice("octagon-ckks", "Unable to convert proposed keys: %@ %@", op.keyset, localerror); - if(op.keyset) { - [ckksBrokenKeySets addObject:op.keyset]; - } - } - - for(CKKSTLKShareRecord* tlkShareRecord in op.keyset.tlkShares) { - [tlkShares addObject:tlkShareRecord.share]; - } - secnotice("octagon-ckks", "Have %u tlk shares", (uint32_t)op.keyset.tlkShares.count); - - for(CKKSTLKShareRecord* tlkShareRecord in op.keyset.pendingTLKShares) { - [pendingTLKShares addObject:tlkShareRecord.share]; - } - secnotice("octagon-ckks", "Have %u pending tlk shares", (uint32_t)op.keyset.pendingTLKShares.count); - } - - self.viewKeySets = viewKeySets; - self.incompleteKeySets = ckksBrokenKeySets; - self.tlkShares = tlkShares; - self.pendingTLKShares = pendingTLKShares; - - secnotice("octagon-ckks", "Fetched %d key sets, %d broken key sets, %d tlk shares, and %d pendingTLKShares", - (int)self.viewKeySets.count, - (int)self.incompleteKeySets.count, - (int)self.tlkShares.count, - (int)self.pendingTLKShares.count); - }]; + STRONGIFY(self); + + NSMutableArray* viewKeySets = [NSMutableArray array]; + NSMutableArray* ckksBrokenKeySets = [NSMutableArray array]; + NSMutableArray* tlkShares = [NSMutableArray array]; + NSMutableArray* pendingTLKShares = [NSMutableArray array]; + + NSMutableSet* viewsMIA = [NSMutableSet set]; + + for(CKKSResultOperation* op in keyOps) { + if(op.error) { + secnotice("octagon-ckks", "No keys for zone %@: %@", op.zoneName, op.error); + + if([op.error.domain isEqualToString:CKKSResultErrorDomain] && op.error.code == CKKSResultTimedOut) { + [viewsMIA addObject:op.zoneName]; + } + continue; + } + + NSError* localerror = nil; + CKKSCurrentKeySet* keyset = op.keyset; + CKKSKeychainBackedKeySet* keychainBackedKeyset = [keyset asKeychainBackedSet:&localerror]; + + if(keychainBackedKeyset) { + secnotice("octagon-ckks", "Have proposed keys: %@", keyset); + [viewKeySets addObject:keychainBackedKeyset]; + } else { + if(keyset) { + secnotice("octagon-ckks", "Unable to convert proposed keys: %@ %@", keyset, localerror); + [ckksBrokenKeySets addObject:op.keyset]; + } + } + + for(CKKSTLKShareRecord* tlkShareRecord in op.keyset.tlkShares) { + [tlkShares addObject:tlkShareRecord.share]; + } + + for(CKKSTLKShareRecord* tlkShareRecord in op.keyset.pendingTLKShares) { + [pendingTLKShares addObject:tlkShareRecord.share]; + } + secnotice("octagon-ckks", "Have %u tlk shares, %u pending tlk shares", + (uint32_t)op.keyset.tlkShares.count, + (uint32_t)op.keyset.pendingTLKShares.count); + } + + self.viewKeySets = viewKeySets; + self.incompleteKeySets = ckksBrokenKeySets; + self.tlkShares = tlkShares; + self.pendingTLKShares = pendingTLKShares; + self.viewsTimedOutWithoutKeysets = viewsMIA; + + secnotice("octagon-ckks", "Fetched %d key sets, %d broken key sets, %d tlk shares, %d pendingTLKShares, and %d views timing out", + (int)self.viewKeySets.count, + (int)self.incompleteKeySets.count, + (int)self.tlkShares.count, + (int)self.pendingTLKShares.count, + (int)self.viewsTimedOutWithoutKeysets.count); + }]; for(CKKSResultOperation* op in keyOps) { [proceedWithKeys addDependency: op]; diff --git a/keychain/ot/OTFetchViewsOperation.m b/keychain/ot/OTFetchViewsOperation.m index 3b63b205..c7cbdacf 100644 --- a/keychain/ot/OTFetchViewsOperation.m +++ b/keychain/ot/OTFetchViewsOperation.m @@ -57,8 +57,9 @@ WEAKIFY(self); [self.deps.cuttlefishXPCWrapper fetchCurrentPolicyWithContainer:self.deps.containerName context:self.deps.contextID - reply:^(NSSet* _Nullable viewList, - TPPolicy* _Nullable policy, + modelIDOverride:nil + reply:^(TPSyncingPolicy* _Nullable syncingPolicy, + TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers, NSError* _Nullable error) { STRONGIFY(self); [[CKKSAnalytics logger] logResultForEvent:OctagonEventFetchViews hardFailure:true result:error]; @@ -69,13 +70,12 @@ return; } - secnotice("octagon-ckks", "Received policy %@ with view list: %@", policy, viewList); + secnotice("octagon-ckks", "Received syncing policy %@ with view list: %@", syncingPolicy, syncingPolicy.viewList); // Write them down before continuing NSError* stateError = nil; [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { - metadata.syncingViews = [viewList mutableCopy]; - [metadata setTPPolicy:policy]; + [metadata setTPSyncingPolicy:syncingPolicy]; return metadata; } error:&stateError]; @@ -85,7 +85,7 @@ return; } - [self.deps.viewManager setSyncingViews:viewList sortingPolicy:policy]; + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; self.nextState = self.intendedState; }]; diff --git a/keychain/ot/OTFollowup.h b/keychain/ot/OTFollowup.h index a7095929..073d2bd2 100644 --- a/keychain/ot/OTFollowup.h +++ b/keychain/ot/OTFollowup.h @@ -55,7 +55,7 @@ NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType); - (BOOL)clearFollowUp:(OTFollowupContextType)contextType error:(NSError **)error; -- (NSDictionary *)sysdiagnoseStatus; +- (NSDictionary *_Nullable)sysdiagnoseStatus; - (NSDictionary *)sfaStatus; @end diff --git a/keychain/ot/OTFollowup.m b/keychain/ot/OTFollowup.m index 649dc59d..5c58c5a8 100644 --- a/keychain/ot/OTFollowup.m +++ b/keychain/ot/OTFollowup.m @@ -133,7 +133,7 @@ NSString* OTFollowupContextTypeToString(OTFollowupContextType contextType) } -- (NSDictionary *)sysdiagnoseStatus +- (NSDictionary *_Nullable)sysdiagnoseStatus { NSMutableDictionary *pendingCFUs = nil; diff --git a/keychain/ot/OTJoinWithVoucherOperation.h b/keychain/ot/OTJoinWithVoucherOperation.h index c5a9addb..325bf4b9 100644 --- a/keychain/ot/OTJoinWithVoucherOperation.h +++ b/keychain/ot/OTJoinWithVoucherOperation.h @@ -38,14 +38,12 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState ckksConflictState:(OctagonState*)ckksConflictState - errorState:(OctagonState*)errorState - voucherData:(NSData*)voucherData - voucherSig:(NSData*)voucherSig; + errorState:(OctagonState*)errorState; -@property (nonatomic) NSData* voucherData; -@property (nonatomic) NSData* voucherSig; +@property (nullable) NSData* voucherData; +@property (nullable) NSData* voucherSig; -@property (nonatomic) NSString* peerID; +@property (nullable) NSString* peerID; @end diff --git a/keychain/ot/OTJoinWithVoucherOperation.m b/keychain/ot/OTJoinWithVoucherOperation.m index 6a7c5b97..d2d6a332 100644 --- a/keychain/ot/OTJoinWithVoucherOperation.m +++ b/keychain/ot/OTJoinWithVoucherOperation.m @@ -53,8 +53,6 @@ intendedState:(OctagonState*)intendedState ckksConflictState:(OctagonState*)ckksConflictState errorState:(OctagonState*)errorState - voucherData:(NSData*)voucherData - voucherSig:(NSData*)voucherSig { if((self = [super init])) { _deps = dependencies; @@ -63,22 +61,39 @@ _nextState = errorState; _ckksConflictState = ckksConflictState; - _voucherData = voucherData; - _voucherSig = voucherSig; + _peerID = nil; + _voucherData = nil; + _voucherSig = nil; } return self; } - (void)groupStart { - secnotice("octagon", "joining"); + // Load the voucher from the state handler + NSError* error = nil; + OTAccountMetadataClassC* metadata = [self.deps.stateHolder loadOrCreateAccountMetadata:&error]; + + if(!metadata.voucher || !metadata.voucherSignature || error) { + secnotice("octagon", "No voucher available: %@", error); + self.error = error; + return; + } + + self.voucherData = metadata.voucher; + self.voucherSig = metadata.voucherSignature; + + secnotice("octagon", "joining with a voucher: %@", self.voucherData); self.finishedOp = [[NSOperation alloc] init]; [self dependOnBeforeGroupFinished:self.finishedOp]; WEAKIFY(self); - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:NO]; + // We only care about TLKs that are ready for upload. Don't wait long. + fetchKeysOp.desiredTimeout = 2*NSEC_PER_SEC; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"vouch-with-keys" @@ -120,8 +135,7 @@ preapprovedKeys:publicSigningSPKIs reply:^(NSString * _Nullable peerID, NSArray* keyHierarchyRecords, - NSSet* _Nullable syncingViews, - TPPolicy* _Nullable syncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error) { STRONGIFY(self); if(error){ @@ -144,14 +158,17 @@ [[CKKSAnalytics logger] logSuccessForEventNamed:OctagonEventJoinWithVoucher]; - [self.deps.viewManager setSyncingViews:syncingViews sortingPolicy:syncingPolicy]; + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; NSError* localError = nil; BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; metadata.peerID = peerID; - metadata.syncingViews = [syncingViews mutableCopy]; - [metadata setTPPolicy:syncingPolicy]; + + metadata.voucher = nil; + metadata.voucherSignature = nil; + + [metadata setTPSyncingPolicy:syncingPolicy]; return metadata; } error:&localError]; if(!persisted || localError) { diff --git a/keychain/ot/OTJoiningConfiguration.m b/keychain/ot/OTJoiningConfiguration.m index f7442540..e0150f3a 100644 --- a/keychain/ot/OTJoiningConfiguration.m +++ b/keychain/ot/OTJoiningConfiguration.m @@ -42,8 +42,7 @@ NS_ASSUME_NONNULL_BEGIN epoch:(uint64_t)epoch isInitiator:(BOOL)isInitiator { - self = [super init]; - if (self){ + if ((self = [super init])) { self.protocolType = protocolType; self.uniqueDeviceID = uniqueDeviceID; self.uniqueClientID = uniqueClientID; @@ -71,8 +70,7 @@ NS_ASSUME_NONNULL_BEGIN } - (nullable instancetype)initWithCoder:(nonnull NSCoder *)decoder { - self = [super init]; - if (self) { + if ((self = [super init])) { _protocolType = [decoder decodeObjectOfClass:[NSString class] forKey:@"protocolType"]; _uniqueClientID = [decoder decodeObjectOfClass:[NSString class] forKey:@"uniqueClientID"]; _uniqueDeviceID = [decoder decodeObjectOfClass:[NSString class] forKey:@"uniqueDeviceID"]; diff --git a/keychain/ot/OTLocalCuttlefishReset.h b/keychain/ot/OTLocalCuttlefishReset.h index 90011df7..65f7c0df 100644 --- a/keychain/ot/OTLocalCuttlefishReset.h +++ b/keychain/ot/OTLocalCuttlefishReset.h @@ -27,17 +27,17 @@ #import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ot/OctagonStateMachineHelpers.h" -#import "keychain/ot/CuttlefishXPCWrapper.h" +#import "keychain/ot/OTOperationDependencies.h" + +@class OTOperationDependencies; NS_ASSUME_NONNULL_BEGIN @interface OTLocalResetOperation : CKKSGroupOperation -- (instancetype)init:(NSString*)containerName - contextID:(NSString*)contextID - intendedState:(OctagonState*)intendedState - errorState:(OctagonState*)errorState -cuttlefishXPCWrapper:(CuttlefishXPCWrapper*)cuttlefishXPCWrapper; +- (instancetype)initWithDependencies:(OTOperationDependencies*)deps + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTLocalCuttlefishReset.m b/keychain/ot/OTLocalCuttlefishReset.m index 30cd3608..7fcf57e6 100644 --- a/keychain/ot/OTLocalCuttlefishReset.m +++ b/keychain/ot/OTLocalCuttlefishReset.m @@ -30,9 +30,8 @@ #import "utilities/debugging.h" @interface OTLocalResetOperation () -@property NSString* containerName; -@property NSString* contextID; -@property CuttlefishXPCWrapper* cuttlefishXPCWrapper; +@property OTOperationDependencies* deps; + @property NSOperation* finishedOp; @end @@ -40,19 +39,15 @@ @synthesize intendedState = _intendedState; @synthesize nextState = _nextState; -- (instancetype)init:(NSString*)containerName - contextID:(NSString*)contextID - intendedState:(OctagonState*)intendedState - errorState:(OctagonState*)errorState -cuttlefishXPCWrapper:(CuttlefishXPCWrapper*)cuttlefishXPCWrapper +- (instancetype)initWithDependencies:(OTOperationDependencies *)deps + intendedState:(OctagonState *)intendedState + errorState:(OctagonState *)errorState { if((self = [super init])) { _intendedState = intendedState; _nextState = errorState; - _containerName = containerName; - _contextID = contextID; - _cuttlefishXPCWrapper = cuttlefishXPCWrapper; + _deps = deps; } return self; } @@ -65,16 +60,34 @@ cuttlefishXPCWrapper:(CuttlefishXPCWrapper*)cuttlefishXPCWrapper [self dependOnBeforeGroupFinished:self.finishedOp]; WEAKIFY(self); - [self.cuttlefishXPCWrapper localResetWithContainer:self.containerName - context:self.contextID - reply:^(NSError * _Nullable error) { + [self.deps.cuttlefishXPCWrapper localResetWithContainer:self.deps.containerName + context:self.deps.contextID + reply:^(NSError * _Nullable error) { STRONGIFY(self); if(error) { - secnotice("octagon", "Unable to reset local cuttlefish for (%@,%@): %@", self.containerName, self.contextID, error); + secnotice("octagon", "Unable to reset local cuttlefish for (%@,%@): %@", self.deps.containerName, self.deps.contextID, error); self.error = error; } else { secnotice("octagon", "Successfully reset local cuttlefish"); - self.nextState = self.intendedState; + + NSError* localError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.trustState = OTAccountMetadataClassC_TrustState_UNKNOWN; + metadata.peerID = nil; + metadata.syncingPolicy = nil; + + // Don't touch the CDP or account states; those can carry over + + return metadata; + } error:&localError]; + + if(localError) { + secnotice("octagon", "Error resetting local account state: %@", localError); + + } else { + secnotice("octagon", "Successfully reset local account state"); + self.nextState = self.intendedState; + } } [self runBeforeGroupFinished:self.finishedOp]; diff --git a/keychain/ot/OTManager.h b/keychain/ot/OTManager.h index d8fcd385..662362ea 100644 --- a/keychain/ot/OTManager.h +++ b/keychain/ot/OTManager.h @@ -148,6 +148,10 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithSOSAdapter:(id)sosAdapter lockStateTracker:(CKKSLockStateTracker*)lockStateTracker cloudKitClassDependencies:(CKKSCloudKitClassDependencies*)cloudKitClassDependencies; + +- (void)invalidateEscrowCache:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + reply:(nonnull void (^)(NSError * _Nullable error))reply; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTManager.m b/keychain/ot/OTManager.m index 79d43f93..20359984 100644 --- a/keychain/ot/OTManager.m +++ b/keychain/ot/OTManager.m @@ -270,6 +270,12 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; return nil; } + if([CKDatabase class] == nil) { + // CloudKit is not linked. We cannot bring Octagon up. + secerror("Octagon: CloudKit.framework appears to not be linked. Cannot create an Octagon manager (on pain of crash)."); + return nil; + } + return [self resetManager:false to:nil]; } @@ -674,6 +680,7 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; NSString * _Nullable peerID, NSDictionary * _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError * _Nullable error) { // Our clients don't need the whole breakout of peers, so just count for them long peerCount = 0; @@ -716,6 +723,7 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; NSString* egoPeerID, NSDictionary * _Nullable peerCountByModelID, BOOL isExcluded, + BOOL isLocked, NSError * _Nullable error) { reply(status, error); }]; @@ -1022,6 +1030,9 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; values[OctagonAnalyticCDPBitStatus] = metadata? @(metadata.cdpState) : nil; values[OctagonAnalyticsTrustState] = metadata ? @(metadata.trustState) : nil; + TPSyncingPolicy* syncingPolicy = [metadata getTPSyncingPolicy]; + values[OctagonAnalyticsUserControllableViewsSyncing] = syncingPolicy ? @(syncingPolicy.syncUserControllableViewsAsBoolean) : nil; + NSDate* healthCheck = [cuttlefishContext currentMemoizedLastHealthCheck]; values[OctagonAnalyticsLastHealthCheck] = @([CKKSAnalytics fuzzyDaysSinceDate:healthCheck]); @@ -1147,7 +1158,7 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; SFAnalyticsActivityTracker *tracker = [[self.loggerClass logger] startLogSystemMetricsForActivityNamed:OctagonActivitySetRecoveryKey]; if (!self.sosEnabledForPlatform) { - secnotice("octagon-recovery", "Device is considered a limited peer, cannot enroll recovery key in Octagon"); + secnotice("octagon-recovery", "Device does not participate in SOS; cannot enroll recovery key in Octagon"); NSError* notFullPeerError = [NSError errorWithDomain:OctagonErrorDomain code:OTErrorLimitedPeer userInfo:@{NSLocalizedDescriptionKey : @"Device is considered a limited peer, cannot enroll recovery key in Octagon"}]; [tracker stopWithEvent:OctagonEventRecoveryKey result:notFullPeerError]; reply(notFullPeerError); @@ -1218,7 +1229,16 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; [cfshContext joinWithRecoveryKey:recoveryKey reply:^(NSError *error) { if ((error.code == TrustedPeersHelperErrorCodeNotEnrolled || error.code == TrustedPeersHelperErrorCodeUntrustedRecoveryKeys) && [error.domain isEqualToString:TrustedPeersHelperErrorDomain]){ - // If we hit either of these errors, let's reset and establish octagon then enroll this recovery key in the new circle + // If we hit either of these errors, and the local device thinks it should be able to set a recovery key, + // let's reset and establish octagon then enroll this recovery key in the new circle + + if (!self.sosEnabledForPlatform) { + secerror("octagon: recovery key is not enrolled in octagon, and current device can't set recovery keys"); + [tracker stopWithEvent:OctagonEventJoinRecoveryKeyCircleResetFailed result:error]; + reply(error); + return; + } + secerror("octagon, recovery key is not enrolled in octagon, resetting octagon circle"); [[self.loggerClass logger] logResultForEvent:OctagonEventJoinRecoveryKeyCircleReset hardFailure:NO result:error]; @@ -1231,25 +1251,19 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; } else { // Now enroll the recovery key secnotice("octagon", "attempting enrolling recovery key"); - if (self.sosEnabledForPlatform) { - [self createRecoveryKey:containerName contextID:contextID recoveryKey:recoveryKey reply:^(NSError *enrollError) { - if(enrollError){ - secerror("octagon, failed to enroll new recovery key: %@", enrollError); - [tracker stopWithEvent:OctagonEventJoinRecoveryKeyEnrollFailed result:enrollError]; - reply(enrollError); - return; - }else{ - secnotice("octagon", "successfully enrolled recovery key"); - [tracker stopWithEvent:OctagonEventRecoveryKey result:nil]; - reply (nil); - return; - } - }]; - } else { - secnotice("octagon", "Limited Peer, can't enroll recovery key"); - reply (nil); - return; - } + [self createRecoveryKey:containerName contextID:contextID recoveryKey:recoveryKey reply:^(NSError *enrollError) { + if(enrollError){ + secerror("octagon, failed to enroll new recovery key: %@", enrollError); + [tracker stopWithEvent:OctagonEventJoinRecoveryKeyEnrollFailed result:enrollError]; + reply(enrollError); + return; + }else{ + secnotice("octagon", "successfully enrolled recovery key"); + [tracker stopWithEvent:OctagonEventRecoveryKey result:nil]; + reply (nil); + return; + } + }]; } }]; } else { @@ -1324,27 +1338,12 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; return true; } -- (void)attemptSosUpgrade:(NSString* _Nullable)containerName - context:(NSString*)context - reply:(void (^)(NSError* error))reply - -{ - secnotice("octagon-sos", "Attempting sos upgrade"); - OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:context]; - - [cfshContext startOctagonStateMachine]; - - [cfshContext attemptSOSUpgrade:^(NSError *error) { - reply(error); - }]; -} - - (void)waitForOctagonUpgrade:(NSString* _Nullable)containerName context:(NSString*)context reply:(void (^)(NSError* error))reply { - secnotice("octagon-sos", "waitForOctagonUpgrade"); + secnotice("octagon-sos", "Attempting wait for octagon upgrade"); OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:context]; [cfshContext startOctagonStateMachine]; @@ -1382,8 +1381,6 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; contextName:(NSString *)contextName reply:(void (^)(NSError *error))reply { - OTCuttlefishContext *cuttlefishContext = [self contextForContainerName:containerName contextID:contextName]; - NSString* metricName = [NSString stringWithFormat:@"%@%@", OctagonAnalyticsCDPStateRun, type]; NSString* countName = [NSString stringWithFormat:@"%@%@Tries", OctagonAnalyticsCDPStateRun, type]; @@ -1436,7 +1433,6 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; }]; } - - (void)getCDPStatus:(NSString * _Nullable)containerName contextID:(nonnull NSString *)contextID reply:(nonnull void (^)(OTCDPStatus, NSError * _Nullable))reply { @@ -1485,6 +1481,117 @@ static NSString* const kOTRampZoneName = @"metadata_zone"; reply(localError); } +- (void)fetchEscrowRecords:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + forceFetch:(BOOL)forceFetch + reply:(nonnull void (^)(NSArray * _Nullable records, + NSError * _Nullable error))reply { + + secnotice("octagon-fetch-escrow-records", "fetching records"); + if(!containerName) { + containerName = OTCKContainerName; + } + + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply(nil, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + [cfshContext rpcFetchAllViableEscrowRecords:forceFetch reply:^(NSArray * _Nullable records, NSError * _Nullable error) { + if(error) { + secerror("octagon-fetch-escrow-records: error fetching records: %@", error); + reply(nil, error); + return; + } + secnotice("octagon-fetch-escrow-records", "successfully fetched records"); + reply(records, nil); + }]; +} + +- (void)invalidateEscrowCache:(NSString * _Nullable)containerName + contextID:(NSString*)contextID + reply:(nonnull void (^)(NSError * _Nullable error))reply { + + secnotice("octagon-remove-escrow-cache", "beginning removing escrow cache!"); + if(!containerName) { + containerName = OTCKContainerName; + } + + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply([NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + [cfshContext rpcInvalidateEscrowCache:^(NSError * _Nullable invalidateError) { + if(invalidateError) { + secerror("octagon-remove-escrow-cache: error invalidating escrow cache: %@", invalidateError); + reply(invalidateError); + return; + } + secnotice("octagon-remove-escrow-caches", "successfully invalidated escrow cache"); + reply(nil); + }]; +} + +- (void)setUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + enabled:(BOOL)enabled + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply +{ + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply(NO, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + [cfshContext rpcSetUserControllableViewsSyncingStatus:enabled reply:^(BOOL areSyncing, NSError * _Nullable error) { + if(error) { + secerror("octagon-user-controllable-views: error setting status: %@", error); + reply(NO, error); + return; + } + + secnotice("octagon-user-controllable-views", "successfully set status to: %@", areSyncing ? @"enabled" : @"paused"); + reply(areSyncing, nil); + }]; +} + +- (void)fetchUserControllableViewsSyncStatus:(NSString* _Nullable)containerName + contextID:(NSString*)contextID + reply:(void (^)(BOOL nowSyncing, NSError* _Nullable error))reply +{ + OTCuttlefishContext* cfshContext = [self contextForContainerName:containerName contextID:contextID]; + + if(!cfshContext) { + reply(NO, [NSError errorWithDomain:OctagonErrorDomain + code:OTErrorNoSuchContext + description:[NSString stringWithFormat:@"No context for (%@,%@)", containerName, contextID]]); + return; + } + + [cfshContext rpcFetchUserControllableViewsSyncingStatus:^(BOOL areSyncing, NSError * _Nullable error) { + if(error) { + secerror("octagon-user-controllable-views: error fetching status: %@", error); + reply(NO, error); + return; + } + + secerror("octagon-user-controllable-views: succesfully fetched status as: %@", areSyncing ? @"enabled" : @"paused"); + reply(areSyncing, nil); + }]; +} + @end #endif diff --git a/keychain/ot/OTModifyUserControllableViewStatusOperation.h b/keychain/ot/OTModifyUserControllableViewStatusOperation.h new file mode 100644 index 00000000..17ccd75f --- /dev/null +++ b/keychain/ot/OTModifyUserControllableViewStatusOperation.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 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@ + */ + +#if OCTAGON + +#import + +#import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ot/OTOperationDependencies.h" +#import "keychain/ot/OTOperationDependencies.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface OTModifyUserControllableViewStatusOperation : CKKSGroupOperation + +// Pass 'unknown' to intendedViewStatus to set your peer view status to the opinion of your peers +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedViewStatus:(TPPBPeerStableInfo_UserControllableViewStatus)intendedViewStatus + intendedState:(OctagonState*)intendedState + peerMissingState:(OctagonState*)peerMissingState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ot/OTModifyUserControllableViewStatusOperation.m b/keychain/ot/OTModifyUserControllableViewStatusOperation.m new file mode 100644 index 00000000..c0e77b23 --- /dev/null +++ b/keychain/ot/OTModifyUserControllableViewStatusOperation.m @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2020 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@ + */ + +#if OCTAGON + +#import +#import "keychain/ckks/CKKSAnalytics.h" +#import "keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h" +#import "keychain/ot/OTModifyUserControllableViewStatusOperation.h" +#import "keychain/ot/OTStates.h" +#import "keychain/ot/ObjCImprovements.h" +#import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" + +@interface OTModifyUserControllableViewStatusOperation () +@property OTOperationDependencies* deps; + +@property OctagonState* peerMissingState; + +@property TPPBPeerStableInfo_UserControllableViewStatus intendedViewStatus; +@end + +@implementation OTModifyUserControllableViewStatusOperation +@synthesize intendedState = _intendedState; +@synthesize nextState = _nextState; + +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedViewStatus:(TPPBPeerStableInfo_UserControllableViewStatus)intendedViewStatus + intendedState:(OctagonState*)intendedState + peerMissingState:(OctagonState*)peerMissingState + errorState:(OctagonState*)errorState +{ + if ((self = [super init])) { + _deps = dependencies; + + _intendedViewStatus = intendedViewStatus; + + _intendedState = intendedState; + _peerMissingState = peerMissingState; + _nextState = errorState; + } + return self; +} + +- (void)groupStart +{ + + if(self.intendedViewStatus == TPPBPeerStableInfo_UserControllableViewStatus_FOLLOWING) { +#if TARGET_OS_WATCH || TARGET_OS_TV + // Watches and TVs want to be able to set the FOLLOWING state + [self performWithStatus:self.intendedViewStatus]; +#else + // For other platforms, we want to determine the actual state by asking + WEAKIFY(self); + + // Should we ask SOS? Or Octagon? + if(self.deps.sosAdapter.sosEnabled) { + NSError* error = nil; + BOOL safariViewEnabled = [self.deps.sosAdapter safariViewSyncingEnabled:&error]; + + if(error) { + secerror("octagon-ckks: Unable to fetch SOS Safari view status: %@", error); + self.error = error; + return; + } + + secnotice("octagon-ckks", "Currently SOS believes the safari view is '%@'", safariViewEnabled ? @"enabled" : @"disabled"); + + TPPBPeerStableInfo_UserControllableViewStatus status = safariViewEnabled ? + TPPBPeerStableInfo_UserControllableViewStatus_ENABLED : + TPPBPeerStableInfo_UserControllableViewStatus_DISABLED; + + [self performWithStatus:status]; + return; + } + + secnotice("octagon-ckks", "Determining peers' user-controllable views policy"); + + [self.deps.cuttlefishXPCWrapper fetchCurrentPolicyWithContainer:self.deps.containerName + context:self.deps.contextID + modelIDOverride:nil + reply:^(TPSyncingPolicy* _Nullable syncingPolicy, + TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers, + NSError* _Nullable error) { + STRONGIFY(self); + + if(error) { + secnotice("octagon-ckks", "Determining peers' user-controllable views policy failed: %@", error); + self.error = error; + return; + } + + secnotice("octagon-ckks", "Retrieved peers' user-controllable views policy as: %@", + TPPBPeerStableInfo_UserControllableViewStatusAsString(userControllableViewStatusOfPeers)); + + [self performWithStatus:userControllableViewStatusOfPeers]; + return; + }]; +#endif + + } else { + [self performWithStatus:self.intendedViewStatus]; + } +} + +- (void)performWithStatus:(TPPBPeerStableInfo_UserControllableViewStatus)intendedViewStatus +{ + WEAKIFY(self); + + secnotice("octagon-ckks", "Setting user-controllable views to %@", TPPBPeerStableInfo_UserControllableViewStatusAsString(self.intendedViewStatus)); + + [self.deps.cuttlefishXPCWrapper updateWithContainer:self.deps.containerName + context:self.deps.contextID + deviceName:nil + serialNumber:nil + osVersion:nil + policyVersion:nil + policySecrets:nil + syncUserControllableViews:[NSNumber numberWithInt:intendedViewStatus] + reply:^(TrustedPeersHelperPeerState* peerState, TPSyncingPolicy* syncingPolicy, NSError* error) { + STRONGIFY(self); + if(error || !syncingPolicy) { + secerror("octagon-ckks: setting user-controllable views status errored: %@", error); + self.error = error; + + if([self.deps.lockStateTracker isLockedError:self.error]) { + secnotice("octagon-ckks", "Updating user-controllable view status failed because of lock state, will retry once unlocked: %@", self.error); + OctagonPendingFlag* pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptUserControllableViewStatusUpgrade + conditions:OctagonPendingConditionsDeviceUnlocked]; + + [self.deps.flagHandler handlePendingFlag:pendingFlag]; + } + if(peerState.peerStatus & (TPPeerStatusExcluded | TPPeerStatusUnknown)) { + secnotice("octagon-ckks", "Updating user-controllable view status failed because our self peer is excluded or missing"); + self.nextState = self.peerMissingState; + } + return; + } + + secnotice("octagon-ckks", "Received syncing policy %@ with view list: %@", syncingPolicy, syncingPolicy.viewList); + + NSError* stateError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&stateError]; + + if(stateError) { + secerror("octagon: failed to save policy+views: %@", stateError); + self.error = stateError; + return; + } + + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; + + self.nextState = self.intendedState; + }]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ot/OTPreloadOctagonKeysOperation.h b/keychain/ot/OTPreloadOctagonKeysOperation.h new file mode 100644 index 00000000..cd2e7a6b --- /dev/null +++ b/keychain/ot/OTPreloadOctagonKeysOperation.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 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@ + */ + +#if OCTAGON + +#import + +#import "keychain/ckks/CKKSGroupOperation.h" +#import "keychain/ot/OctagonStateMachineHelpers.h" +#import "keychain/ot/OTOperationDependencies.h" + +@class OTCuttlefishContext; + +NS_ASSUME_NONNULL_BEGIN + +@interface OTPreloadOctagonKeysOperation : CKKSGroupOperation +@property OctagonState* nextState; +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState; + +@end + +NS_ASSUME_NONNULL_END + +#endif // OCTAGON diff --git a/keychain/ot/OTPreloadOctagonKeysOperation.m b/keychain/ot/OTPreloadOctagonKeysOperation.m new file mode 100644 index 00000000..58952f96 --- /dev/null +++ b/keychain/ot/OTPreloadOctagonKeysOperation.m @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 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@ + */ + +#if OCTAGON + +#import + +#import +#import "keychain/ot/OTPreloadOctagonKeysOperation.h" +#import "keychain/ot/OTClientStateMachine.h" +#import "keychain/ot/OTCuttlefishContext.h" +#import "keychain/ot/OTFetchCKKSKeysOperation.h" +#import "keychain/ot/OTDefines.h" +#import "keychain/ot/OTConstants.h" +#import "keychain/ot/OctagonCKKSPeerAdapter.h" +#import "utilities/debugging.h" +#import +#import + +#import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" +#import "keychain/ot/ObjCImprovements.h" +#import "keychain/securityd/SOSCloudCircleServer.h" + +@interface OTPreloadOctagonKeysOperation () +@property OTOperationDependencies* deps; + +@property NSOperation* finishOp; +@end + +@implementation OTPreloadOctagonKeysOperation +@synthesize intendedState = _intendedState; + +- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies + intendedState:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if((self = [super init])) { + _deps = dependencies; + _intendedState = intendedState; + _nextState = errorState; + } + return self; +} + +- (void)groupStart +{ + secnotice("octagon-preload-keys", "Beginning operation that preloads the SOSAccount with newly created Octagon Keys"); + + self.finishOp = [[NSOperation alloc] init]; + [self dependOnBeforeGroupFinished:self.finishOp]; + + if(!self.deps.sosAdapter.sosEnabled) { + self.error = [NSError errorWithDomain:OctagonErrorDomain code:OTErrorSOSAdapter userInfo:@{NSLocalizedDescriptionKey : @"sos adapter not enabled"}]; + [self runBeforeGroupFinished:self.finishOp]; + return; + } + + NSError* fetchSelfPeersError = nil; + CKKSSelves *selfPeers = [self.deps.octagonAdapter fetchSelfPeers:&fetchSelfPeersError]; + if((!selfPeers) || fetchSelfPeersError) { + secnotice("octagon-preload-keys", "failed to retrieve self peers: %@", fetchSelfPeersError); + self.error = fetchSelfPeersError; + [self runBeforeGroupFinished:self.finishOp]; + return; + } + + id currentSelfPeer = selfPeers.currentSelf; + if(currentSelfPeer == nil) { + secnotice("octagon-preload-keys", "failed to retrieve current self"); + self.error = [NSError errorWithDomain:OctagonErrorDomain code:OTErrorOctagonAdapter userInfo: @{ NSLocalizedDescriptionKey : @"failed to retrieve current self"}]; + [self runBeforeGroupFinished:self.finishOp]; + return; + } + + NSError* updateError = nil; + BOOL ret = [self.deps.sosAdapter preloadOctagonKeySetOnAccount:currentSelfPeer error:&updateError]; + if(!ret) { + self.error = updateError; + [self runBeforeGroupFinished:self.finishOp]; + return; + } + + self.nextState = self.intendedState; + [self runBeforeGroupFinished:self.finishOp]; +} + +@end + +#endif // OCTAGON diff --git a/keychain/ot/OTPrepareOperation.m b/keychain/ot/OTPrepareOperation.m index d0e0ca45..f6de077b 100644 --- a/keychain/ot/OTPrepareOperation.m +++ b/keychain/ot/OTPrepareOperation.m @@ -135,6 +135,9 @@ secerror("octagon: failed to save 'attempted join' state: %@", persistError); } + // Note: we pass syncUserControllableViews as FOLLOWING here, with the intention that + // it will be set later, when this peer decides who it trusts and accepts their value. + [self.deps.cuttlefishXPCWrapper prepareWithContainer:self.deps.containerName context:self.deps.contextID epoch:self.epoch @@ -147,6 +150,7 @@ osVersion:self.deviceInfo.osVersion policyVersion:self.policyOverride policySecrets:nil + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_FOLLOWING signingPrivKeyPersistentRef:signingKeyPersistRef encPrivKeyPersistentRef:encryptionKeyPersistRef reply:^(NSString * _Nullable peerID, @@ -154,8 +158,7 @@ NSData * _Nullable permanentInfoSig, NSData * _Nullable stableInfo, NSData * _Nullable stableInfoSig, - NSSet* _Nullable syncingViews, - TPPolicy* _Nullable syncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error) { STRONGIFY(self); [[CKKSAnalytics logger] logResultForEvent:OctagonEventPrepareIdentity hardFailure:true result:error]; @@ -173,13 +176,12 @@ NSError* localError = nil; - secnotice("octagon-ckks", "New syncing policy: %@ views: %@", syncingPolicy, syncingViews); + secnotice("octagon-ckks", "New syncing policy: %@ views: %@", syncingPolicy, syncingPolicy.viewList); BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { metadata.peerID = peerID; - metadata.syncingViews = [syncingViews mutableCopy]; - [metadata setTPPolicy:syncingPolicy]; + [metadata setTPSyncingPolicy:syncingPolicy]; return metadata; } error:&localError]; @@ -191,7 +193,7 @@ } // Let CKKS know of the new policy, so it can spin up - [self.deps.viewManager setSyncingViews:syncingViews sortingPolicy:syncingPolicy]; + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; self.nextState = self.intendedState; [self runBeforeGroupFinished:self.finishedOp]; diff --git a/keychain/ot/OTRamping.m b/keychain/ot/OTRamping.m index 11fdfedb..72a7d8c3 100644 --- a/keychain/ot/OTRamping.m +++ b/keychain/ot/OTRamping.m @@ -87,8 +87,7 @@ static NSString* kRampPriorityKey = @"RampPriority"; fetchRecordRecordsOperationClass:(Class) fetchRecordRecordsOperationClass { - self = [super init]; - if(self){ + if ((self = [super init])) { _container = container; _recordName = [recordName copy]; _localSettingName = [localSettingName copy]; diff --git a/keychain/ot/OTResetCKKSZonesLackingTLKsOperation.m b/keychain/ot/OTResetCKKSZonesLackingTLKsOperation.m index 0f2dbc38..84883ebf 100644 --- a/keychain/ot/OTResetCKKSZonesLackingTLKsOperation.m +++ b/keychain/ot/OTResetCKKSZonesLackingTLKsOperation.m @@ -49,7 +49,8 @@ }]; [self dependOnBeforeGroupFinished:self.finishedOp]; - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"continue-ckks-resets" @@ -84,13 +85,10 @@ if(incompleteKeySet.currentTLKPointer != nil && incompleteKeySet.tlk == nil) { - BOOL otherDevicesAlive = [viewMatchingSet otherDevicesReportHavingTLKs:incompleteKeySet]; - if(otherDevicesAlive) { - secnotice("octagon-ckks", "Recently active devices claim to have TLK from key set %@; not scheduling for reset", incompleteKeySet); - } else { - secnotice("octagon-ckks", "Key set %@ has no TLK; scheduling for reset", incompleteKeySet); - [viewsToReset addObject:viewMatchingSet]; - } + // We used to not reset the TLKs if there was a recent device claiming to have them, but + // in our Octagon-primary world, an Octagon reset should take precedence over existing Cloud-based data + secnotice("octagon-ckks", "Key set %@ has no TLK; scheduling for reset", incompleteKeySet); + [viewsToReset addObject:viewMatchingSet]; } } else { secnotice("octagon-ckks", "Error loading key set %@; not attempting reset", incompleteKeySet); @@ -116,7 +114,9 @@ // Use an intermediary operation, just to ensure we have a timeout CKKSResultOperation* waitOp = [CKKSResultOperation named:[NSString stringWithFormat:@"wait-for-%@", view.zoneName] - withBlock:^{}]; + withBlock:^{ + secnotice("octagon-ckks", "Successfully reset %@", view); + }]; [waitOp timeout:120*NSEC_PER_SEC]; [waitOp addDependency:op]; [self.operationQueue addOperation:waitOp]; diff --git a/keychain/ot/OTSOSAdapter.h b/keychain/ot/OTSOSAdapter.h index 976476e1..0403f382 100644 --- a/keychain/ot/OTSOSAdapter.h +++ b/keychain/ot/OTSOSAdapter.h @@ -12,7 +12,11 @@ NS_ASSUME_NONNULL_BEGIN - (SOSCCStatus)circleStatus:(NSError**)error; - (id _Nullable)currentSOSSelf:(NSError**)error; - (NSSet>* _Nullable)fetchTrustedPeers:(NSError**)error; -- (void)updateOctagonKeySetWithAccount:(id)currentSelfPeer error:(NSError**)error; +- (BOOL)updateOctagonKeySetWithAccount:(id)currentSelfPeer error:(NSError**)error; +- (BOOL)preloadOctagonKeySetOnAccount:(id)currentSelfPeer error:(NSError**)error; +- (BOOL)updateCKKS4AllStatus:(BOOL)status error:(NSError**)error; + +- (BOOL)safariViewSyncingEnabled:(NSError**)error __attribute__((swift_error(nonnull_error))); @end @interface OTSOSActualAdapter : NSObject diff --git a/keychain/ot/OTSOSAdapter.m b/keychain/ot/OTSOSAdapter.m index 4513d980..51ec8864 100644 --- a/keychain/ot/OTSOSAdapter.m +++ b/keychain/ot/OTSOSAdapter.m @@ -229,12 +229,60 @@ return peerSet; } -- (void)updateOctagonKeySetWithAccount:(id)currentSelfPeer error:(NSError**)error { + +- (BOOL)preloadOctagonKeySetOnAccount:(id)currentSelfPeer error:(NSError**)error { + // in case we don't have the keys, don't try to update them + if (currentSelfPeer.publicSigningKey.secKey == NULL || currentSelfPeer.publicEncryptionKey.secKey == NULL) { + secnotice("octagon-preload-keys", "no octagon keys available skipping updating SOS record"); + return YES; + } + + __block CFDataRef signingFullKey = CFBridgingRetain(currentSelfPeer.signingKey.keyData); + __block CFDataRef encryptionFullKey = CFBridgingRetain(currentSelfPeer.encryptionKey.keyData); + __block SecKeyRef octagonSigningPubSecKey = CFRetainSafe(currentSelfPeer.publicSigningKey.secKey); + __block SecKeyRef octagonEncryptionPubSecKey = CFRetainSafe(currentSelfPeer.publicEncryptionKey.secKey); + __block SecKeyRef signingFullKeyRef = CFRetainSafe(currentSelfPeer.signingKey.secKey); + __block SecKeyRef encryptionFullKeyRef = CFRetainSafe(currentSelfPeer.encryptionKey.secKey); + + SFAnalyticsActivityTracker *tracker = [[[CKKSAnalytics class] logger] startLogSystemMetricsForActivityNamed:OctagonSOSAdapterUpdateKeys]; + + __block BOOL ret; + __block NSError *localError = nil; + + /* WARNING! Please be very very careful passing keys to this routine. Note the slightly different variations of keys*/ + SOSCCPerformPreloadOfAllOctagonKeys(signingFullKey, encryptionFullKey, + signingFullKeyRef, encryptionFullKeyRef, + octagonSigningPubSecKey, octagonEncryptionPubSecKey, + ^(CFErrorRef cferror) { + [tracker stopWithEvent: OctagonSOSAdapterUpdateKeys result:(__bridge NSError * _Nullable)(cferror)]; + if(cferror) { + secerror("octagon-preload-keys: failed to preload Octagon keys in SOS:%@", cferror); + ret = NO; + localError = (__bridge NSError *)cferror; + } else { + ret = YES; + secnotice("octagon-preload-keys", "successfully preloaded Octagon keys in SOS!"); + } + CFRelease(signingFullKey); + CFRelease(encryptionFullKey); + CFRelease(octagonSigningPubSecKey); + CFRelease(octagonEncryptionPubSecKey); + CFRelease(signingFullKeyRef); + CFRelease(encryptionFullKeyRef); + }); + if (error) { + *error = localError; + } + return ret; + +} + +- (BOOL)updateOctagonKeySetWithAccount:(id)currentSelfPeer error:(NSError**)error { // in case we don't have the keys, don't try to update them if (currentSelfPeer.publicSigningKey.secKey == NULL || currentSelfPeer.publicEncryptionKey.secKey == NULL) { secnotice("octagon-sos", "no octagon keys available skipping updating SOS record"); - return; + return YES; } __block CFDataRef signingFullKey = CFBridgingRetain(currentSelfPeer.signingKey.keyData); @@ -246,15 +294,21 @@ SFAnalyticsActivityTracker *tracker = [[[CKKSAnalytics class] logger] startLogSystemMetricsForActivityNamed:OctagonSOSAdapterUpdateKeys]; + __block BOOL ret; + __block NSError *localError = nil; + /* WARNING! Please be very very careful passing keys to this routine. Note the slightly different variations of keys*/ SOSCCPerformUpdateOfAllOctagonKeys(signingFullKey, encryptionFullKey, signingPublicKey, encryptionPublicKey, octagonSigningPubSecKey, octagonEncryptionPubSecKey, - ^(CFErrorRef error) { - [tracker stopWithEvent: OctagonSOSAdapterUpdateKeys result:(__bridge NSError * _Nullable)(error)]; - if(error){ - secerror("octagon-sos: failed to update Octagon keys in SOS:%@", error); - }else { + ^(CFErrorRef cferror) { + [tracker stopWithEvent: OctagonSOSAdapterUpdateKeys result:(__bridge NSError * _Nullable)(cferror)]; + if(cferror) { + secerror("octagon-sos: failed to update Octagon keys in SOS:%@", cferror); + ret = NO; + localError = (__bridge NSError *)cferror; + } else { + ret = YES; secnotice("octagon-sos", "successfully updated Octagon keys in SOS!"); } CFRelease(signingFullKey); @@ -264,6 +318,29 @@ CFRelease(octagonSigningPubSecKey); CFRelease(octagonEncryptionPubSecKey); }); + if (error) { + *error = localError; + } + return ret; +} + +- (BOOL)updateCKKS4AllStatus:(BOOL)status error:(NSError**)error +{ + CFErrorRef cferror = nil; + bool result = SOSCCSetCKKS4AllStatus(status, &cferror); + + NSError* localerror = CFBridgingRelease(cferror); + + if(!result || localerror) { + secerror("octagon-sos: failed to update CKKS4All status in SOS: %@", localerror); + } else { + secnotice("octagon-sos", "successfully updated CKKS4All status in SOS to '%@'", status ? @"supported" : @"not supported"); + } + + if(error && localerror) { + *error = localerror; + } + return result; } - (void)registerForPeerChangeUpdates:(nonnull id)listener { @@ -302,6 +379,23 @@ return result; } + +- (BOOL)safariViewSyncingEnabled:(NSError**)error +{ + CFErrorRef viewCFError = NULL; + SOSViewResultCode result = SOSCCView(kSOSViewAutofillPasswords, kSOSCCViewQuery, &viewCFError); + + if(viewCFError) { + if(error) { + *error = CFBridgingRelease(viewCFError); + } else { + CFReleaseNull(viewCFError); + } + return NO; + } + + return result == kSOSCCViewMember; +} @end @implementation OTSOSMissingAdapter @@ -345,12 +439,23 @@ return nil; } -- (void)updateOctagonKeySetWithAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { +- (BOOL)updateOctagonKeySetWithAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { if(error) { *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecUnimplemented description:@"SOS unsupported on this platform"]; } + return NO; +} + +- (BOOL)updateCKKS4AllStatus:(BOOL)status error:(NSError**)error +{ + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:errSecUnimplemented + description:@"SOS unsupported on this platform"]; + } + return NO; } - (CKKSSelves * _Nullable)fetchSelfPeers:(NSError * _Nullable __autoreleasing * _Nullable)error @@ -390,6 +495,20 @@ trustedPeersError:unimplementedError]; } +- (BOOL)safariViewSyncingEnabled:(NSError**)error +{ + return NO; +} + +- (BOOL)preloadOctagonKeySetOnAccount:(nonnull id)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error { + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:errSecUnimplemented + description:@"SOS unsupported on this platform"]; + } + return NO; +} + @end @implementation OTSOSAdapterHelpers diff --git a/keychain/ot/OTSOSUpgradeOperation.m b/keychain/ot/OTSOSUpgradeOperation.m index 4972beed..a7df524a 100644 --- a/keychain/ot/OTSOSUpgradeOperation.m +++ b/keychain/ot/OTSOSUpgradeOperation.m @@ -34,6 +34,8 @@ @property NSOperation* finishedOp; @property OTUpdateTrustedDeviceListOperation* updateOp; + +@property (nullable) NSArray* peerPreapprovedSPKIs; @end @implementation OTSOSUpgradeOperation @@ -163,6 +165,11 @@ fatal = true; } + if([self.error.domain isEqualToString:TrustedPeersHelperErrorDomain] && self.error.code == TrustedPeersHelperErrorNoPeersPreapprovedBySelf) { + secnotice("octagon-sos", "SOS upgrade error is 'we don't preapprove anyone'; retrying immediately is useless: %@", self.error); + fatal = true; + } + if(!fatal) { secnotice("octagon-sos", "SOS upgrade error is not fatal: requesting retry in %0.2fs: %@", delay, self.error); [self.deps.flagHandler handlePendingFlag:[[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptSOSUpgrade @@ -172,6 +179,20 @@ }]; [self dependOnBeforeGroupFinished:self.finishedOp]; + secnotice("octagon-sos", "Fetching trusted peers from SOS"); + + NSError* sosPreapprovalError = nil; + self.peerPreapprovedSPKIs = [OTSOSAdapterHelpers peerPublicSigningKeySPKIsForCircle:self.deps.sosAdapter error:&sosPreapprovalError]; + + if(self.peerPreapprovedSPKIs) { + secnotice("octagon-sos", "SOS preapproved keys are %@", self.peerPreapprovedSPKIs); + } else { + secnotice("octagon-sos", "Unable to fetch SOS preapproved keys: %@", sosPreapprovalError); + self.error = sosPreapprovalError; + [self runBeforeGroupFinished:self.finishedOp]; + return; + } + NSString* bottleSalt = nil; NSError *authKitError = nil; @@ -192,6 +213,14 @@ } } + NSError* sosViewError = nil; + BOOL safariViewEnabled = [self.deps.sosAdapter safariViewSyncingEnabled:&sosViewError]; + if(sosViewError) { + secnotice("octagon-sos", "Unable to check safari view status: %@", sosViewError); + } + + secnotice("octagon-sos", "Safari view is: %@", safariViewEnabled ? @"enabled" : @"disabled"); + [self.deps.cuttlefishXPCWrapper prepareWithContainer:self.deps.containerName context:self.deps.contextID epoch:self.deviceInfo.epoch @@ -204,6 +233,9 @@ osVersion:self.deviceInfo.osVersion policyVersion:self.policyOverride policySecrets:nil + syncUserControllableViews:safariViewEnabled ? + TPPBPeerStableInfo_UserControllableViewStatus_ENABLED : + TPPBPeerStableInfo_UserControllableViewStatus_DISABLED signingPrivKeyPersistentRef:signingKeyPersistRef encPrivKeyPersistentRef:encryptionKeyPersistRef reply:^(NSString * _Nullable peerID, @@ -211,8 +243,7 @@ NSData * _Nullable permanentInfoSig, NSData * _Nullable stableInfo, NSData * _Nullable stableInfoSig, - NSSet* syncingViews, - TPPolicy* _Nullable syncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error) { STRONGIFY(self); @@ -231,8 +262,7 @@ NSError* localError = nil; BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { - metadata.syncingViews = [syncingViews mutableCopy]; - [metadata setTPPolicy:syncingPolicy]; + [metadata setTPSyncingPolicy:syncingPolicy]; return metadata; } error:&localError]; @@ -244,7 +274,7 @@ return; } - [self.deps.viewManager setSyncingViews:syncingViews sortingPolicy:syncingPolicy]; + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; [self afterPrepare]; }]; @@ -255,12 +285,10 @@ WEAKIFY(self); [self.deps.cuttlefishXPCWrapper preflightPreapprovedJoinWithContainer:self.deps.containerName context:self.deps.contextID + preapprovedKeys:self.peerPreapprovedSPKIs reply:^(BOOL launchOkay, NSError * _Nullable error) { STRONGIFY(self); - // Preflight preapprovedjoin should return the policy used by the peers we eventually will trust - // Octagon: ensure we use appropriate CKKS policy when joining octagon with future policy - [[CKKSAnalytics logger] logResultForEvent:OctagonEventUpgradePreflightPreapprovedJoin hardFailure:true result:error]; if(error) { secerror("octagon-sos: preflightPreapprovedJoin failed: %@", error); @@ -349,7 +377,8 @@ { WEAKIFY(self); - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; secnotice("octagon-sos", "Fetching keys from CKKS"); @@ -366,34 +395,16 @@ { WEAKIFY(self); - secnotice("octagon-sos", "Fetching trusted peers from SOS"); - - NSArray* publicSigningSPKIs = nil; - if(self.deps.sosAdapter.sosEnabled) { - NSError* sosPreapprovalError = nil; - publicSigningSPKIs = [OTSOSAdapterHelpers peerPublicSigningKeySPKIsForCircle:self.deps.sosAdapter error:&sosPreapprovalError]; - - if(publicSigningSPKIs) { - secnotice("octagon-sos", "SOS preapproved keys are %@", publicSigningSPKIs); - } else { - secnotice("octagon-sos", "Unable to fetch SOS preapproved keys: %@", sosPreapprovalError); - } - - } else { - secnotice("octagon-sos", "SOS not enabled; no preapproved keys"); - } - - secnotice("octagon-sos", "Beginning SOS upgrade with %d key sets and %d SOS peers", (int)viewKeySets.count, (int)publicSigningSPKIs.count); + secnotice("octagon-sos", "Beginning SOS upgrade with %d key sets and %d SOS peers", (int)viewKeySets.count, (int)self.peerPreapprovedSPKIs.count); [self.deps.cuttlefishXPCWrapper attemptPreapprovedJoinWithContainer:self.deps.containerName context:self.deps.contextID ckksKeys:viewKeySets tlkShares:pendingTLKShares - preapprovedKeys:publicSigningSPKIs + preapprovedKeys:self.peerPreapprovedSPKIs reply:^(NSString * _Nullable peerID, NSArray* keyHierarchyRecords, - NSSet* _Nullable syncingViewList, - TPPolicy* _Nullable syncingPolicy, + TPSyncingPolicy* _Nullable syncingPolicy, NSError * _Nullable error) { STRONGIFY(self); @@ -415,15 +426,14 @@ [self requestSilentEscrowUpdate]; secerror("octagon-sos: attemptPreapprovedJoin succeded"); - [self.deps.viewManager setSyncingViews:syncingViewList sortingPolicy:syncingPolicy]; + [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy]; NSError* localError = nil; BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { metadata.trustState = OTAccountMetadataClassC_TrustState_TRUSTED; metadata.peerID = peerID; - metadata.syncingViews = [syncingViewList mutableCopy]; - [metadata setTPPolicy:syncingPolicy]; + [metadata setTPSyncingPolicy:syncingPolicy]; return metadata; } error:&localError]; diff --git a/keychain/ot/OTSetRecoveryKeyOperation.m b/keychain/ot/OTSetRecoveryKeyOperation.m index 4761d525..b66d44a2 100644 --- a/keychain/ot/OTSetRecoveryKeyOperation.m +++ b/keychain/ot/OTSetRecoveryKeyOperation.m @@ -81,7 +81,8 @@ WEAKIFY(self); - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"setting-recovery-tlks" @@ -103,7 +104,8 @@ recoveryKey:self.recoveryKey salt:salt ckksKeys:viewKeySets - reply:^(NSError * _Nullable setError) { + reply:^(NSArray* _Nullable keyHierarchyRecords, + NSError * _Nullable setError) { STRONGIFY(self); if(setError){ [[CKKSAnalytics logger] logResultForEvent:OctagonEventSetRecoveryKey hardFailure:true result:setError]; @@ -112,6 +114,12 @@ [self runBeforeGroupFinished:self.finishOp]; } else { secnotice("octagon", "successfully set recovery key"); + + for (id key in self.deps.viewManager.views) { + CKKSKeychainView* view = self.deps.viewManager.views[key]; + secnotice("octagon-ckks", "Providing setRecoveryKey() records to %@", view); + [view receiveTLKUploadRecords:keyHierarchyRecords]; + } [self runBeforeGroupFinished:self.finishOp]; } }]; diff --git a/keychain/ot/OTStates.h b/keychain/ot/OTStates.h index 52cee05b..10250713 100644 --- a/keychain/ot/OTStates.h +++ b/keychain/ot/OTStates.h @@ -45,6 +45,9 @@ extern OctagonState* const OctagonStateBecomeUntrusted; // WaitForUnlock indicates that Octagon is waiting for the device to unlock before attempting the pended operation extern OctagonState* const OctagonStateWaitForUnlock; +// Similar to the above, but we can't even be sure there's an account until the device unlocks for the first time. +extern OctagonState* const OctagonStateWaitForClassCUnlock; + // 'ready' indicates that this machine believes it is trusted by its peers // and has no pending things to do. extern OctagonState* const OctagonStateReady; @@ -55,6 +58,11 @@ extern OctagonState* const OctagonStateBecomeReady; // BecomeReady might go here, if it's not actually ready extern OctagonState* const OctagonStateRefetchCKKSPolicy; +// Used in RPCs to set CKKS sync status +extern OctagonState* const OctagonStateEnableUserControllableViews; +extern OctagonState* const OctagonStateDisableUserControllableViews; +extern OctagonState* const OctagonStateSetUserControllableViewsToPeerConsensus; + // Enter this state if you'd like the state machine to double-check everything extern OctagonState* const OctagonStateEnsureConsistency; extern OctagonState* const OctagonStateEnsureOctagonKeysAreConsistent; @@ -83,6 +91,7 @@ extern OctagonState* const OctagonStateDeviceListUpdated; /* used for join with bottle */ extern OctagonState* const OctagonStateBottleJoinCreateIdentity; +extern OctagonState* const OctagonStateBottlePreloadOctagonKeysInSOS; /* used for join with recovery key */ extern OctagonState* const OctagonStateCreateIdentityForRecoveryKey; @@ -129,6 +138,7 @@ extern OctagonState* const OctagonStateUpdateSOSPreapprovals; extern OctagonState* const OctagonStateError; extern OctagonState* const OctagonStateDisabled; +extern OctagonState* const OctagonStateAttemptSOSUpgradeDetermineCDPState; extern OctagonState* const OctagonStateAttemptSOSUpgrade; extern OctagonState* const OctagonStateSOSUpgradeCKKSReset; extern OctagonState* const OctagonStateSOSUpgradeAfterCKKSReset; @@ -170,6 +180,10 @@ extern OctagonFlag* const OctagonFlagIDMSLevelChanged; extern OctagonFlag* const OctagonFlagEgoPeerPreapproved; extern OctagonFlag* const OctagonFlagCKKSRequestsTLKUpload; +extern OctagonFlag* const OctagonFlagCKKSRequestsPolicyCheck; + +// Set by Octagon when the CKKS view set has changed. Indicates a need to re-tell CKKS if it's trusted or not. +extern OctagonFlag* const OctagonFlagCKKSViewSetChanged; // We've received a change notification from cuttlefish; we should probably see what's new extern OctagonFlag* const OctagonFlagCuttlefishNotification NS_SWIFT_NAME(OctagonFlagCuttlefishNotification); @@ -187,6 +201,12 @@ extern OctagonFlag* const OctagonFlagAttemptSOSUpdatePreapprovals; extern OctagonFlag* const OctagonFlagAttemptSOSConsistency; extern OctagonFlag* const OctagonFlagEscrowRequestInformCloudServicesOperation; +extern OctagonFlag* const OctagonFlagWarmEscrowRecordCache; + +extern OctagonFlag* const OctagonFlagAttemptBottleTLKExtraction; +extern OctagonFlag* const OctagonFlagAttemptRecoveryKeyTLKExtraction; + +extern OctagonFlag* const OctagonFlagAttemptUserControllableViewStatusUpgrade; NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTStates.m b/keychain/ot/OTStates.m index 5db76711..340ee221 100644 --- a/keychain/ot/OTStates.m +++ b/keychain/ot/OTStates.m @@ -52,6 +52,10 @@ OctagonState* const OctagonStateRefetchCKKSPolicy = (OctagonState*) @"ckks_fetch OctagonState* const OctagonStateDetermineCDPState = (OctagonState*) @"check_cdp_state"; OctagonState* const OctagonStateCheckTrustState = (OctagonState*) @"check_trust_state"; +OctagonState* const OctagonStateEnableUserControllableViews = (OctagonState*) @"ckks_set_user_controllable_views_on"; +OctagonState* const OctagonStateDisableUserControllableViews = (OctagonState*) @"ckks_set_user_controlable_views_off"; +OctagonState* const OctagonStateSetUserControllableViewsToPeerConsensus = (OctagonState*) @"ckks_set_user_controlable_views_peer_consensus"; + OctagonState* const OctagonStateUpdateSOSPreapprovals = (OctagonState*) @"update_sos_preapprovals"; /*Piggybacking and ProximitySetup as Initiator Octagon only*/ @@ -66,6 +70,7 @@ OctagonState* const OctagonStateInitiatorJoinAfterCKKSReset = (OctagonState*)@"j OctagonState* const OctagonStateBottleJoinCreateIdentity = (OctagonState*)@"bottle_join_create_identity"; OctagonState* const OctagonStateBottleJoinVouchWithBottle = (OctagonState*)@"bottle_join_vouch_with_bottle"; OctagonState* const OctagonStateCreateIdentityForRecoveryKey = (OctagonState*)@"vouchWithRecovery"; +OctagonState* const OctagonStateBottlePreloadOctagonKeysInSOS = (OctagonState*)@"bottle_preload_octagon_keys_in_sos"; /* used in resotre (join with recovery key)*/ OctagonState* const OctagonStateVouchWithRecoveryKey = (OctagonState*)@"vouchWithRecoveryKey"; @@ -84,6 +89,8 @@ OctagonState* const OctagonStateError = (OctagonState*) @"error"; OctagonState* const OctagonStateDisabled = (OctagonState*) @"disabled"; OctagonState* const OctagonStateDetermineiCloudAccountState = (OctagonState*) @"determine_icloud_account"; + +OctagonState* const OctagonStateAttemptSOSUpgradeDetermineCDPState = (OctagonState*) @"sosupgrade_cdp_check"; OctagonState* const OctagonStateAttemptSOSUpgrade = (OctagonState*) @"sosupgrade"; OctagonState* const OctagonStateSOSUpgradeCKKSReset = (OctagonState*) @"sosupgrade_ckks_reset"; OctagonState* const OctagonStateSOSUpgradeAfterCKKSReset = (OctagonState*) @"sosupgrade_after_ckks_reset"; @@ -112,6 +119,7 @@ OctagonState* const OctagonStateHealthCheckReset = (OctagonState*) @"health_chec OctagonState* const OctagonStateNoAccountDoReset = (OctagonState*) @"no_account_do_reset"; OctagonState* const OctagonStateWaitForUnlock = (OctagonState*) @"wait_for_unlock"; +OctagonState* const OctagonStateWaitForClassCUnlock = (OctagonState*) @"wait_for_class_c_unlock"; OctagonState* const OctagonStateAssistCKKSTLKUpload = (OctagonState*) @"assist_ckks_tlk_upload"; OctagonState* const OctagonStateAssistCKKSTLKUploadCKKSReset = (OctagonState*) @"assist_ckks_tlk_upload_ckks_reset"; @@ -199,6 +207,12 @@ NSDictionary* OctagonStateMap(void) { OctagonStateCDPHealthCheck: @58U, OctagonStateHealthCheckLeaveClique: @59U, OctagonStateRefetchCKKSPolicy: @60U, + OctagonStateEnableUserControllableViews: @61U, + OctagonStateDisableUserControllableViews: @62U, + OctagonStateSetUserControllableViewsToPeerConsensus: @63U, + OctagonStateWaitForClassCUnlock: @64U, + OctagonStateBottlePreloadOctagonKeysInSOS: @65U, + OctagonStateAttemptSOSUpgradeDetermineCDPState: @66U, }; }); return map; @@ -231,6 +245,9 @@ NSSet* OctagonInAccountStates(void) [sourceStates removeObject:OctagonStateCloudKitNewlyAvailable]; [sourceStates removeObject:OctagonStateWaitForHSA2]; + // If the device hasn't unlocked yet, we don't know what we wrote down for iCloud account status + [sourceStates removeObject:OctagonStateWaitForClassCUnlock]; + s = sourceStates; }); return s; @@ -258,7 +275,9 @@ NSSet* OctagonHealthSourceStates(void) // Flags OctagonFlag* const OctagonFlagIDMSLevelChanged = (OctagonFlag*) @"idms_level"; OctagonFlag* const OctagonFlagEgoPeerPreapproved = (OctagonFlag*) @"preapproved"; -OctagonFlag* const OctagonFlagCKKSRequestsTLKUpload = (OctagonFlag*) @"tlk_upload_needed"; +OctagonFlag* const OctagonFlagCKKSRequestsTLKUpload = (OctagonFlag*) @"tlk_upload_needed"; +OctagonFlag* const OctagonFlagCKKSRequestsPolicyCheck = (OctagonFlag*) @"policy_check_needed";; +OctagonFlag* const OctagonFlagCKKSViewSetChanged = (OctagonFlag*) @"ckks_views_changed"; OctagonFlag* const OctagonFlagCuttlefishNotification = (OctagonFlag*) @"recd_push"; OctagonFlag* const OctagonFlagAccountIsAvailable = (OctagonFlag*)@"account_available"; OctagonFlag* const OctagonFlagCDPEnabled = (OctagonFlag*) @"cdp_enabled"; @@ -268,6 +287,11 @@ OctagonFlag* const OctagonFlagUnlocked = (OctagonFlag*)@"unlocked"; OctagonFlag* const OctagonFlagAttemptSOSUpdatePreapprovals = (OctagonFlag*)@"attempt_sos_update_preapprovals"; OctagonFlag* const OctagonFlagAttemptSOSConsistency = (OctagonFlag*)@"attempt_sos_consistency"; OctagonFlag* const OctagonFlagEscrowRequestInformCloudServicesOperation = (OctagonFlag*)@"escrowrequest_inform_cloudservices"; +OctagonFlag* const OctagonFlagWarmEscrowRecordCache = (OctagonFlag*)@"warm_escrow_cache"; +OctagonFlag* const OctagonFlagAttemptBottleTLKExtraction = (OctagonFlag*)@"retry_bottle_tlk_extraction"; +OctagonFlag* const OctagonFlagAttemptRecoveryKeyTLKExtraction = (OctagonFlag*)@"retry_rk_tlk_extraction"; + +OctagonFlag* const OctagonFlagAttemptUserControllableViewStatusUpgrade = (OctagonFlag*)@"attempt_ucv_upgrade"; NSSet* AllOctagonFlags(void) { @@ -279,6 +303,8 @@ NSSet* AllOctagonFlags(void) [flags addObject:OctagonFlagIDMSLevelChanged]; [flags addObject:OctagonFlagEgoPeerPreapproved]; [flags addObject:OctagonFlagCKKSRequestsTLKUpload]; + [flags addObject:OctagonFlagCKKSRequestsPolicyCheck]; + [flags addObject:OctagonFlagCKKSViewSetChanged]; [flags addObject:OctagonFlagCuttlefishNotification]; [flags addObject:OctagonFlagAccountIsAvailable]; [flags addObject:OctagonFlagCDPEnabled]; @@ -287,6 +313,10 @@ NSSet* AllOctagonFlags(void) [flags addObject:OctagonFlagUnlocked]; [flags addObject:OctagonFlagAttemptSOSUpdatePreapprovals]; [flags addObject:OctagonFlagAttemptSOSConsistency]; + [flags addObject:OctagonFlagWarmEscrowRecordCache]; + [flags addObject:OctagonFlagAttemptUserControllableViewStatusUpgrade]; + [flags addObject:OctagonFlagAttemptBottleTLKExtraction]; + [flags addObject:OctagonFlagAttemptRecoveryKeyTLKExtraction]; f = flags; }); diff --git a/keychain/ot/OTUpdateTPHOperation.m b/keychain/ot/OTUpdateTPHOperation.m index c31589f0..1dec19ce 100644 --- a/keychain/ot/OTUpdateTPHOperation.m +++ b/keychain/ot/OTUpdateTPHOperation.m @@ -105,20 +105,42 @@ osVersion:self.deps.deviceInformationAdapter.osVersion policyVersion:nil policySecrets:nil - reply:^(TrustedPeersHelperPeerState* peerState, NSError* error) { + syncUserControllableViews:nil + reply:^(TrustedPeersHelperPeerState* peerState, TPSyncingPolicy* syncingPolicy, NSError* error) { STRONGIFY(self); if(error || !peerState) { secerror("octagon: update errored: %@", error); self.error = error; - // On an error, for now, go back to the intended state - // Octagon: handle lock state errors in update() - self.nextState = self.intendedState; + if ([error isCuttlefishError:CuttlefishErrorUpdateTrustPeerNotFound]) { + secnotice("octagon-ckks", "Cuttlefish reports we no longer exist."); + self.nextState = self.peerUnknownState; + } else { + // On an error, for now, go back to the intended state + // Octagon: handle lock state errors in update() + self.nextState = self.intendedState; + } [self runBeforeGroupFinished:self.finishedOp]; return; } - secnotice("octagon", "update complete: %@", peerState); + secnotice("octagon", "update complete: %@, %@", peerState, syncingPolicy); + + NSError* localError = nil; + BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nonnull(OTAccountMetadataClassC * _Nonnull metadata) { + [metadata setTPSyncingPolicy:syncingPolicy]; + return metadata; + } error:&localError]; + if(!persisted || localError) { + secerror("octagon: Unable to save new syncing state: %@", localError); + + } else { + // After an update(), we're sure that we have a fresh policy + BOOL viewSetChanged = [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy policyIsFresh:YES]; + if(viewSetChanged) { + [self.deps.flagHandler handleFlag:OctagonFlagCKKSViewSetChanged]; + } + } if(peerState.identityIsPreapproved) { secnotice("octagon-sos", "Self peer is now preapproved!"); @@ -134,14 +156,17 @@ [self.deps.flagHandler handleFlag:OctagonFlagFetchAuthKitMachineIDList]; } - if(peerState.peerStatus & TPPeerStatusExcluded) { + if (peerState.peerStatus & TPPeerStatusExcluded) { secnotice("octagon", "Self peer (%@) is excluded; moving to untrusted", peerState.peerID); self.nextState = OctagonStateBecomeUntrusted; - } else if(peerState.peerStatus & TPPeerStatusUnknown) { - secnotice("octagon", "Self peer (%@) is unknown; moving to '%@''", peerState.peerID, self.peerUnknownState); - self.nextState = self.peerUnknownState; - + if (peerState.identityIsPreapproved) { + secnotice("octagon", "Self peer (%@) is excluded but is preapproved, moving to sosuprade", peerState.peerID); + self.nextState = OctagonStateAttemptSOSUpgrade; + } else { + secnotice("octagon", "Self peer (%@) is unknown; moving to '%@''", peerState.peerID, self.peerUnknownState); + self.nextState = self.peerUnknownState; + } } else { self.nextState = self.intendedState; } diff --git a/keychain/ot/OTUpdateTrustedDeviceListOperation.m b/keychain/ot/OTUpdateTrustedDeviceListOperation.m index 0e6cb278..ca7d5f7d 100644 --- a/keychain/ot/OTUpdateTrustedDeviceListOperation.m +++ b/keychain/ot/OTUpdateTrustedDeviceListOperation.m @@ -95,8 +95,12 @@ [self.deps.authKitAdapter fetchCurrentDeviceList:^(NSSet * _Nullable machineIDs, NSError * _Nullable error) { STRONGIFY(self); - if(!machineIDs || error) { + + if (error) { secerror("octagon-authkit: Unable to fetch machine ID list: %@", error); + [self fetchCurrentDeviceListAfterCuttlefishUpdate:isAccountDemo]; + } else if (!machineIDs) { + secerror("octagon-authkit: empty machine id list"); if (self.logForUpgrade) { [[CKKSAnalytics logger] logRecoverableError:error forEvent:OctagonEventUpgradeFetchDeviceIDs @@ -114,6 +118,60 @@ }]; } +- (void)fetchCurrentDeviceListAfterCuttlefishUpdate:(BOOL)isAccountDemo +{ + secnotice("octagon-authkit", "beginning update trust fetch"); + + WEAKIFY(self); + [self.deps.cuttlefishXPCWrapper updateWithContainer:self.deps.containerName + context:self.deps.contextID + deviceName:nil + serialNumber:nil + osVersion:nil + policyVersion:nil + policySecrets:nil + syncUserControllableViews:nil + reply:^(TrustedPeersHelperPeerState* peerState, TPSyncingPolicy* syncingPolicy, NSError* error) { + STRONGIFY(self); + if(error) { + secerror("octagon-authkit: fetching updates from cuttlefish failed: %@", error); + self.error = error; + + if([self.deps.lockStateTracker isLockedError:self.error]) { + secnotice("octagon-authkit", "Feching changes from Cuttlefish failed because of lock state, will retry once unlocked: %@", self.error); + OctagonPendingFlag* pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagFetchAuthKitMachineIDList + conditions:OctagonPendingConditionsDeviceUnlocked]; + + [self.deps.flagHandler handlePendingFlag:pendingFlag]; + } + + [self runBeforeGroupFinished:self.finishedOp]; + return; + } + secnotice("octagon-authkit", "re-attempting fetching current device list"); + + [self.deps.authKitAdapter fetchCurrentDeviceList:^(NSSet * _Nullable machineIDs, NSError * _Nullable error) { + STRONGIFY(self); + if(!machineIDs || error) { + secerror("octagon-authkit: STILL unable to fetch machine ID list: %@", error); + if (self.logForUpgrade) { + [[CKKSAnalytics logger] logRecoverableError:error + forEvent:OctagonEventUpgradeFetchDeviceIDs + withAttributes:NULL]; + } + self.error = error; + [self runBeforeGroupFinished:self.finishedOp]; + + } else { + if (self.logForUpgrade) { + [[CKKSAnalytics logger] logSuccessForEventNamed:OctagonEventUpgradeFetchDeviceIDs]; + } + [self afterAuthKitFetch:machineIDs accountIsDemo:isAccountDemo]; + } + }]; + }]; +} + - (void)afterAuthKitFetch:(NSSet*)allowedMachineIDs accountIsDemo:(BOOL)accountIsDemo { WEAKIFY(self); diff --git a/keychain/ot/OTUploadNewCKKSTLKsOperation.h b/keychain/ot/OTUploadNewCKKSTLKsOperation.h index 3feeab6a..205e130e 100644 --- a/keychain/ot/OTUploadNewCKKSTLKsOperation.h +++ b/keychain/ot/OTUploadNewCKKSTLKsOperation.h @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState ckksConflictState:(OctagonState*)ckksConflictState + peerMissingState:(OctagonState*)peerMissingState errorState:(OctagonState*)errorState; @property OctagonState* nextState; diff --git a/keychain/ot/OTUploadNewCKKSTLKsOperation.m b/keychain/ot/OTUploadNewCKKSTLKsOperation.m index 5c74b845..15968b1b 100644 --- a/keychain/ot/OTUploadNewCKKSTLKsOperation.m +++ b/keychain/ot/OTUploadNewCKKSTLKsOperation.m @@ -8,6 +8,7 @@ #import "keychain/ot/OTUploadNewCKKSTLKsOperation.h" #import "keychain/ot/OTCuttlefishAccountStateHolder.h" #import "keychain/ot/OTFetchCKKSKeysOperation.h" +#import "keychain/ot/OTStates.h" #import "keychain/ckks/CKKSCurrentKeyPointer.h" #import "keychain/ckks/CKKSKeychainView.h" #import "keychain/ckks/CKKSNearFutureScheduler.h" @@ -20,6 +21,7 @@ @property OTOperationDependencies* deps; @property OctagonState* ckksConflictState; +@property OctagonState* peerMissingState; @property NSOperation* finishedOp; @end @@ -30,6 +32,7 @@ - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState ckksConflictState:(OctagonState*)ckksConflictState + peerMissingState:(OctagonState*)peerMissingState errorState:(OctagonState*)errorState { if((self = [super init])) { @@ -37,6 +40,7 @@ _intendedState = intendedState; _ckksConflictState = ckksConflictState; + _peerMissingState = peerMissingState; _nextState = errorState; } return self; @@ -44,7 +48,7 @@ - (void)groupStart { - secnotice("octagon", "Beginning to upload any pending CKKS tlks operation"); + secnotice("octagon", "Beginning an operation to upload any pending CKKS tlks"); WEAKIFY(self); @@ -53,8 +57,7 @@ // One (or more) of our sub-CKKSes believes it needs to upload new TLKs. CKKSViewManager* viewManager = self.deps.viewManager; for(CKKSKeychainView* view in viewManager.currentViews) { - if([view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload] || - [view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation]) { + if([view requiresTLKUpload]) { secnotice("octagon-ckks", "CKKS view %@ needs TLK uploads!", view); [viewsToUpload addObject: view]; } @@ -106,6 +109,11 @@ if ([error isCuttlefishError:CuttlefishErrorKeyHierarchyAlreadyExists]) { secnotice("octagon-ckks", "A CKKS key hierarchy is out of date; moving to '%@'", self.ckksConflictState); self.nextState = self.ckksConflictState; + } else if ([error isCuttlefishError:CuttlefishErrorUpdateTrustPeerNotFound]) { + secnotice("octagon-ckks", "Cuttlefish reports we no longer exist."); + self.nextState = self.peerMissingState; + self.error = error; + } else { secerror("octagon: Error calling tlk upload: %@", error); self.error = error; diff --git a/keychain/ot/OTVouchWithBottleOperation.h b/keychain/ot/OTVouchWithBottleOperation.h index dc3ef075..f9960c81 100644 --- a/keychain/ot/OTVouchWithBottleOperation.h +++ b/keychain/ot/OTVouchWithBottleOperation.h @@ -41,7 +41,8 @@ NS_ASSUME_NONNULL_BEGIN errorState:(OctagonState*)errorState bottleID:(NSString*)bottleID entropy:(NSData*)entropy - bottleSalt:(NSString*)bottleSalt; + bottleSalt:(NSString*)bottleSalt + saveVoucher:(BOOL)saveVoucher; @property (weak) OTCuttlefishContext* cuttlefishContext; @property (nonatomic) NSString* bottleID; @@ -50,6 +51,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) NSData* voucher; @property (nonatomic) NSData* voucherSig; + +// Controls whether or not to save the received voucher in the state handler. +@property (readonly) BOOL saveVoucher; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTVouchWithBottleOperation.m b/keychain/ot/OTVouchWithBottleOperation.m index d47c452d..da298b6d 100644 --- a/keychain/ot/OTVouchWithBottleOperation.m +++ b/keychain/ot/OTVouchWithBottleOperation.m @@ -29,6 +29,7 @@ #import "keychain/ot/OTClientStateMachine.h" #import "keychain/ot/OTCuttlefishContext.h" #import "keychain/ot/OTFetchCKKSKeysOperation.h" +#import "keychain/ot/OTStates.h" #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" #import "keychain/ot/ObjCImprovements.h" @@ -48,6 +49,7 @@ bottleID:(NSString*)bottleID entropy:(NSData*)entropy bottleSalt:(NSString*)bottleSalt + saveVoucher:(BOOL)saveVoucher { if((self = [super init])) { _deps = dependencies; @@ -57,6 +59,8 @@ _bottleID = bottleID; _entropy = entropy; _bottleSalt = bottleSalt; + + _saveVoucher = saveVoucher; } return self; } @@ -101,8 +105,8 @@ context:self.deps.contextID bottleID:self.bottleID reply:^(NSString * _Nullable peerID, - NSSet* peerSyncingViews, - TPPolicy* peerSyncingPolicy, + TPSyncingPolicy* peerSyncingPolicy, + BOOL refetchWasNeeded, NSError * _Nullable error) { STRONGIFY(self); [[CKKSAnalytics logger] logResultForEvent:OctagonEventPreflightVouchWithBottle hardFailure:true result:error]; @@ -118,18 +122,19 @@ // Tell CKKS to spin up the new views and policy // But, do not persist this view set! We'll do that when we actually manager to join - [self.deps.viewManager setSyncingViews:peerSyncingViews sortingPolicy:peerSyncingPolicy]; + [self.deps.viewManager setCurrentSyncingPolicy:peerSyncingPolicy]; - [self proceedWithPeerID:peerID]; + [self proceedWithPeerID:peerID refetchWasNeeded:refetchWasNeeded]; }]; } -- (void)proceedWithPeerID:(NSString*)peerID +- (void)proceedWithPeerID:(NSString*)peerID refetchWasNeeded:(BOOL)refetchWasNeeded { WEAKIFY(self); // After a vouch, we also want to acquire all TLKs that the bottled peer might have had - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:refetchWasNeeded]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"bottle-tlks" @@ -144,6 +149,15 @@ } } + if(fetchKeysOp.viewsTimedOutWithoutKeysets.count > 0) { + // At least one view failed to find a keyset in time. + // Set up a retry with this bottle, once CKKS is done fetching + secnotice("octagon", "Timed out fetching key hierarchy for CKKS views; marking for TLK recovery follow up: %@", fetchKeysOp.viewsTimedOutWithoutKeysets); + OctagonPendingFlag* flag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptBottleTLKExtraction + after:self.deps.viewManager.zoneChangeFetcher.inflightFetch]; + [self.deps.flagHandler handlePendingFlag:flag]; + } + [self proceedWithKeys:fetchKeysOp.viewKeySets filteredTLKShares:filteredTLKShares]; }]; @@ -207,10 +221,25 @@ } [self noteMetric:OctagonAnalyticsBottledTLKUniqueViewCount count:views.count]; - secnotice("octagon", "Received bottle voucher"); - self.voucher = voucher; self.voucherSig = voucherSig; + + if(self.saveVoucher) { + secnotice("octagon", "Saving voucher for later use..."); + NSError* saveError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.voucher = voucher; + metadata.voucherSignature = voucherSig; + return metadata; + } error:&saveError]; + if(saveError) { + secnotice("octagon", "unable to save voucher: %@", saveError); + [self runBeforeGroupFinished:self.finishedOp]; + return; + } + } + + secnotice("octagon", "Successfully vouched with a bottle: %@, %@", voucher, voucherSig); self.nextState = self.intendedState; [self runBeforeGroupFinished:self.finishedOp]; }]; diff --git a/keychain/ot/OTVouchWithRecoveryKeyOperation.h b/keychain/ot/OTVouchWithRecoveryKeyOperation.h index 1203d715..ba3f884a 100644 --- a/keychain/ot/OTVouchWithRecoveryKeyOperation.h +++ b/keychain/ot/OTVouchWithRecoveryKeyOperation.h @@ -39,12 +39,16 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies intendedState:(OctagonState*)intendedState errorState:(OctagonState*)errorState - recoveryKey:(NSString*)recoveryKey; + recoveryKey:(NSString*)recoveryKey + saveVoucher:(BOOL)saveVoucher; @property (weak) OTCuttlefishContext* cuttlefishContext; @property (nonatomic) NSData* voucher; @property (nonatomic) NSData* voucherSig; + +// Controls whether or not to save the received voucher in the state handler. +@property (readonly) BOOL saveVoucher; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OTVouchWithRecoveryKeyOperation.m b/keychain/ot/OTVouchWithRecoveryKeyOperation.m index 24809b5c..89012c95 100644 --- a/keychain/ot/OTVouchWithRecoveryKeyOperation.m +++ b/keychain/ot/OTVouchWithRecoveryKeyOperation.m @@ -29,6 +29,7 @@ #import "keychain/ot/OTClientStateMachine.h" #import "keychain/ot/OTCuttlefishContext.h" #import "keychain/ot/OTFetchCKKSKeysOperation.h" +#import "keychain/ot/OTStates.h" #import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h" #import "keychain/ot/ObjCImprovements.h" @@ -49,6 +50,7 @@ intendedState:(OctagonState*)intendedState errorState:(OctagonState*)errorState recoveryKey:(NSString*)recoveryKey + saveVoucher:(BOOL)saveVoucher { if((self = [super init])) { _deps = dependencies; @@ -56,6 +58,8 @@ _nextState = errorState; _recoveryKey = recoveryKey; + + _saveVoucher = saveVoucher; } return self; } @@ -92,8 +96,7 @@ recoveryKey:self.recoveryKey salt:self.salt reply:^(NSString * _Nullable recoveryKeyID, - NSSet* peerSyncingViews, - TPPolicy* peerSyncingPolicy, + TPSyncingPolicy* _Nullable peerSyncingPolicy, NSError * _Nullable error) { STRONGIFY(self); [[CKKSAnalytics logger] logResultForEvent:OctagonEventPreflightVouchWithRecoveryKey hardFailure:true result:error]; @@ -109,7 +112,7 @@ // Tell CKKS to spin up the new views and policy // But, do not persist this view set! We'll do that when we actually manage to join - [self.deps.viewManager setSyncingViews:peerSyncingViews sortingPolicy:peerSyncingPolicy]; + [self.deps.viewManager setCurrentSyncingPolicy:peerSyncingPolicy]; [self proceedWithRecoveryKeyID:recoveryKeyID]; }]; @@ -120,7 +123,8 @@ WEAKIFY(self); // After a vouch, we also want to acquire all TLKs that the bottled peer might have had - OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps]; + OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps + refetchNeeded:NO]; [self runBeforeGroupFinished:fetchKeysOp]; CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"recovery-tlks" @@ -135,6 +139,15 @@ } } + if(fetchKeysOp.viewsTimedOutWithoutKeysets.count > 0) { + // At least one view failed to find a keyset in time. + // Set up a retry with this recovery key, once CKKS is done fetching + secnotice("octagon", "Timed out fetching key hierarchy for CKKS views; marking for TLK recovery follow up: %@", fetchKeysOp.viewsTimedOutWithoutKeysets); + OctagonPendingFlag* flag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptRecoveryKeyTLKExtraction + after:self.deps.viewManager.zoneChangeFetcher.inflightFetch]; + [self.deps.flagHandler handlePendingFlag:flag]; + } + [self proceedWithKeys:fetchKeysOp.viewKeySets tlkShares:filteredTLKShares salt:self.salt]; }]; @@ -162,6 +175,23 @@ } self.voucher = voucher; self.voucherSig = voucherSig; + + if(self.saveVoucher) { + secnotice("octagon", "Saving voucher for later use..."); + NSError* saveError = nil; + [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) { + metadata.voucher = voucher; + metadata.voucherSignature = voucherSig; + return metadata; + } error:&saveError]; + if(saveError) { + secnotice("octagon", "unable to save voucher: %@", saveError); + [self runBeforeGroupFinished:self.finishOp]; + return; + } + } + + secnotice("octagon", "Successfully vouched with a recovery key: %@, %@", voucher, voucherSig); self.nextState = self.intendedState; [self runBeforeGroupFinished:self.finishOp]; }]; diff --git a/keychain/ot/OctagonCKKSPeerAdapter.h b/keychain/ot/OctagonCKKSPeerAdapter.h index 4936cc22..ead418ae 100644 --- a/keychain/ot/OctagonCKKSPeerAdapter.h +++ b/keychain/ot/OctagonCKKSPeerAdapter.h @@ -2,8 +2,9 @@ #if OCTAGON #import -#import "keychain/ot/OTOperationDependencies.h" #import "keychain/ckks/CKKSPeer.h" +#import "keychain/ckks/CKKSPeerProvider.h" +#import "keychain/ot/CuttlefishXPCWrapper.h" NS_ASSUME_NONNULL_BEGIN @@ -19,10 +20,15 @@ NS_ASSUME_NONNULL_BEGIN @interface OctagonCKKSPeerAdapter : NSObject @property (nullable) NSString* peerID; -@property OTOperationDependencies* deps; +@property (readonly) CuttlefishXPCWrapper* cuttlefishXPCWrapper; +@property (readonly) NSString* containerName; +@property (readonly) NSString* contextID; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithPeerID:(NSString*)peerID operationDependencies:(OTOperationDependencies*)deps; +- (instancetype)initWithPeerID:(NSString*)peerID + containerName:(NSString*)containerName + contextID:(NSString*)contextID + cuttlefishXPC:(CuttlefishXPCWrapper*)cuttlefishXPCWrapper; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OctagonCKKSPeerAdapter.m b/keychain/ot/OctagonCKKSPeerAdapter.m index b7707e9e..b664f8c7 100644 --- a/keychain/ot/OctagonCKKSPeerAdapter.m +++ b/keychain/ot/OctagonCKKSPeerAdapter.m @@ -80,12 +80,19 @@ @synthesize essential = _essential; @synthesize providerID = _providerID; -- (instancetype)initWithPeerID:(NSString*)peerID operationDependencies:(OTOperationDependencies*)deps + +- (instancetype)initWithPeerID:(NSString*)peerID + containerName:(NSString*)containerName + contextID:(NSString*)contextID + cuttlefishXPC:(CuttlefishXPCWrapper*)cuttlefishXPCWrapper { if((self = [super init])) { _providerID = [NSString stringWithFormat:@"[OctagonCKKSPeerAdapter:%@]", peerID]; _peerID = peerID; - _deps = deps; + + _containerName = containerName; + _contextID = contextID; + _cuttlefishXPCWrapper = cuttlefishXPCWrapper; _peerChangeListeners = [[CKKSListenerCollection alloc] initWithName:@"ckks-sos"]; @@ -181,14 +188,14 @@ __block NSMutableSet> * peers = nil; WEAKIFY(self); - [self.deps.cuttlefishXPCWrapper fetchTrustStateWithContainer:self.deps.containerName - context:self.deps.contextID - reply:^(TrustedPeersHelperPeerState * _Nullable selfPeerState, - NSArray * _Nullable trustedPeers, - NSError * _Nullable operror) { + [self.cuttlefishXPCWrapper fetchTrustStateWithContainer:self.containerName + context:self.contextID + reply:^(TrustedPeersHelperPeerState * _Nullable selfPeerState, + NSArray * _Nullable trustedPeers, + NSError * _Nullable operror) { STRONGIFY(self); if(operror) { - secnotice("octagon", "Unable to fetch trusted peers for (%@,%@): %@", self.deps.containerName, self.deps.contextID, operror); + secnotice("octagon", "Unable to fetch trusted peers for (%@,%@): %@", self.containerName, self.contextID, operror); localerror = operror; } else { @@ -203,8 +210,6 @@ encryptionPublicKey:encryptionKey signingPublicKey:signingKey viewList:peer.viewList]; - secnotice("octagon", "Have trusted peer %@", ckkspeer); - [peers addObject:ckkspeer]; } } diff --git a/keychain/ot/OctagonCheckTrustStateOperation.m b/keychain/ot/OctagonCheckTrustStateOperation.m index 9fe406bf..254d3278 100644 --- a/keychain/ot/OctagonCheckTrustStateOperation.m +++ b/keychain/ot/OctagonCheckTrustStateOperation.m @@ -79,7 +79,7 @@ if(localError) { if([self.deps.lockStateTracker isLockedError:localError]) { secerror("octagon-consistency: Unable to fetch current account state due to lock state: %@", localError); - self.nextState = OctagonStateWaitForUnlock; + self.nextState = OctagonStateWaitForClassCUnlock; [self runBeforeGroupFinished:self.finishedOp]; return; } @@ -148,7 +148,7 @@ if(!persisted || localError) { if([self.deps.lockStateTracker isLockedError:localError]) { secerror("octagon-consistency: Unable to save new account state due to lock state: %@", localError); - self.nextState = OctagonStateWaitForUnlock; + self.nextState = OctagonStateWaitForClassCUnlock; [self runBeforeGroupFinished:self.finishedOp]; return; } diff --git a/keychain/ot/OctagonControlServer.m b/keychain/ot/OctagonControlServer.m index 9d67c837..97350422 100644 --- a/keychain/ot/OctagonControlServer.m +++ b/keychain/ot/OctagonControlServer.m @@ -115,7 +115,7 @@ return NO; } - secnotice("octagon", "received connection from client pid %d", [newConnection processIdentifier]); + secinfo("octagon", "received connection from client pid %d", [newConnection processIdentifier]); newConnection.exportedInterface = OTSetupControlProtocol([NSXPCInterface interfaceWithProtocol:@protocol(OTControlProtocol)]); newConnection.exportedObject = [OctagonXPCEntitlementChecker createWithManager:[OTManager manager] entitlementBearer:newConnection]; diff --git a/keychain/ot/OctagonFlags.m b/keychain/ot/OctagonFlags.m index b42fc447..455ee795 100644 --- a/keychain/ot/OctagonFlags.m +++ b/keychain/ot/OctagonFlags.m @@ -22,9 +22,9 @@ _flagConditions = [[NSMutableDictionary alloc] init]; _allowableFlags = possibleFlags; - [possibleFlags enumerateObjectsUsingBlock:^(OctagonState * _Nonnull obj, BOOL * _Nonnull stop) { - self.flagConditions[obj] = [[CKKSCondition alloc] init]; - }]; + for(OctagonFlag* flag in possibleFlags) { + self.flagConditions[flag] = [[CKKSCondition alloc] init]; + } } return self; } diff --git a/keychain/ot/OctagonPendingFlag.h b/keychain/ot/OctagonPendingFlag.h index a130fcef..09794be4 100644 --- a/keychain/ot/OctagonPendingFlag.h +++ b/keychain/ot/OctagonPendingFlag.h @@ -25,8 +25,11 @@ NSString* OctagonPendingConditionsToString(OctagonPendingConditions cond); @property (readonly) OctagonPendingConditions conditions; +@property (nullable) NSOperation* afterOperation; + - (instancetype)initWithFlag:(OctagonFlag*)flag delayInSeconds:(NSTimeInterval)delay; - (instancetype)initWithFlag:(OctagonFlag*)flag conditions:(OctagonPendingConditions)conditions; +- (instancetype)initWithFlag:(OctagonFlag*)flag after:(NSOperation*)op; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OctagonPendingFlag.m b/keychain/ot/OctagonPendingFlag.m index d192ae41..20467870 100644 --- a/keychain/ot/OctagonPendingFlag.m +++ b/keychain/ot/OctagonPendingFlag.m @@ -21,6 +21,7 @@ NSString* OctagonPendingConditionsToString(OctagonPendingConditions cond) if ((self = [super init])) { _flag = flag; _fireTime = [NSDate dateWithTimeIntervalSinceNow:delay]; + _afterOperation = nil; _conditions = 0; } return self; @@ -32,14 +33,28 @@ NSString* OctagonPendingConditionsToString(OctagonPendingConditions cond) if ((self = [super init])) { _flag = flag; _fireTime = nil; + _afterOperation = nil; _conditions = conditions; } return self; } +- (instancetype)initWithFlag:(OctagonFlag*)flag after:(NSOperation*)op +{ + if ((self = [super init])) { + _flag = flag; + _fireTime = nil; + _afterOperation = op; + _conditions = 0; + } + return self; +} + - (NSString*)description { if(self.fireTime) { return [NSString stringWithFormat:@"", self.flag, self.fireTime]; + } else if(self.afterOperation) { + return [NSString stringWithFormat:@"", self.flag, self.afterOperation]; } else { return [NSString stringWithFormat:@"", self.flag, OctagonPendingConditionsToString(self.conditions)]; } diff --git a/keychain/ot/OctagonStateMachine.h b/keychain/ot/OctagonStateMachine.h index 4aeabe1c..d463578c 100644 --- a/keychain/ot/OctagonStateMachine.h +++ b/keychain/ot/OctagonStateMachine.h @@ -33,6 +33,9 @@ NS_ASSUME_NONNULL_BEGIN @protocol OctagonStateFlagHandler - (void)handleFlag:(OctagonFlag*)flag; - (void)handlePendingFlag:(OctagonPendingFlag*)pendingFlag; + +// If you've truly broken your queue ordering, then call this from whatever queue your flag handler is using. +- (void)_onqueueHandleFlag:(OctagonFlag*)flag; @end @interface OctagonStateMachine : NSObject @@ -70,6 +73,7 @@ NS_ASSUME_NONNULL_BEGIN // This will set the given flag, and ensure that the state machine spins to handle it. - (void)handleFlag:(OctagonFlag*)flag; +- (void)_onqueueHandleFlag:(OctagonFlag*)flag; // This will schedule the flag for future addition - (void)handlePendingFlag:(OctagonPendingFlag *)pendingFlag; @@ -80,17 +84,19 @@ NS_ASSUME_NONNULL_BEGIN - (void)disablePendingFlags; - (void)handleExternalRequest:(OctagonStateTransitionRequest*>*)request; + - (void)registerStateTransitionWatcher:(OctagonStateTransitionWatcher*)watcher; +- (void)registerMultiStateArrivalWatcher:(OctagonStateMultiStateArrivalWatcher*)watcher; - (void)doSimpleStateMachineRPC:(NSString*)name op:(CKKSResultOperation*)op sourceStates:(NSSet*)sourceStates reply:(nonnull void (^)(NSError * _Nullable))reply; -- (void)doWatchedStateMachineRPC:(NSString*)name - sourceStates:(NSSet*)sourceStates - path:(OctagonStateTransitionPath*)path - reply:(nonnull void (^)(NSError *error))reply; +- (CKKSResultOperation*)doWatchedStateMachineRPC:(NSString*)name + sourceStates:(NSSet*)sourceStates + path:(OctagonStateTransitionPath*)path + reply:(nonnull void (^)(NSError *error))reply; - (void)setWatcherTimeout:(uint64_t)timeout; - (BOOL)isPaused; diff --git a/keychain/ot/OctagonStateMachine.m b/keychain/ot/OctagonStateMachine.m index 3e4f4efe..c470bda2 100644 --- a/keychain/ot/OctagonStateMachine.m +++ b/keychain/ot/OctagonStateMachine.m @@ -39,7 +39,7 @@ format, @property (nullable) CKKSResultOperation* nextStateMachineCycleOperation; @property NSMutableArray*>*>* stateMachineRequests; -@property NSMutableArray* stateMachineWatchers; +@property NSMutableArray>* stateMachineWatchers; @property BOOL halted; @property bool allowPendingFlags; @@ -246,7 +246,7 @@ format, op, op.error ?: @"(no error)"); - for(OctagonStateTransitionWatcher* watcher in self.stateMachineWatchers) { + for(id watcher in self.stateMachineWatchers) { statemachinelog("state", "notifying watcher: %@", watcher); [watcher onqueueHandleTransition:op]; } @@ -286,11 +286,18 @@ format, - (void)handleFlag:(OctagonFlag*)flag { dispatch_sync(self.queue, ^{ - [self.currentFlags _onqueueSetFlag:flag]; - [self _onqueuePokeStateMachine]; + [self _onqueueHandleFlag:flag]; }); } + +- (void)_onqueueHandleFlag:(OctagonFlag*)flag +{ + dispatch_assert_queue(self.queue); + [self.currentFlags _onqueueSetFlag:flag]; + [self _onqueuePokeStateMachine]; +} + - (void)handlePendingFlag:(OctagonPendingFlag *)pendingFlag { dispatch_sync(self.queue, ^{ [self _onqueueHandlePendingFlag:pendingFlag]; @@ -310,6 +317,20 @@ format, self.currentConditions &= ~recheck; } + if(pendingFlag.afterOperation) { + WEAKIFY(self); + NSOperation* after = [NSBlockOperation blockOperationWithBlock:^{ + STRONGIFY(self); + dispatch_sync(self.queue, ^{ + statemachinelog("pending-flag", "Finished waiting for operation"); + [self _onqueueSendAnyPendingFlags]; + }); + }]; + + [after addNullableDependency:pendingFlag.afterOperation]; + [self.operationQueue addOperation:after]; + } + [self _onqueueRecheckConditions]; [self _onqueueSendAnyPendingFlags]; } @@ -409,6 +430,14 @@ format, } } + if(pendingFlag.afterOperation) { + if(![pendingFlag.afterOperation isFinished]) { + send = false; + } else { + statemachinelog("pending-flag", "Operation has ended for pending flag %@: %@", pendingFlag.flag, pendingFlag.afterOperation); + } + } + if(pendingFlag.conditions != 0x0) { // Also, send the flag if the conditions are right if((pendingFlag.conditions & self.currentConditions) == pendingFlag.conditions) { @@ -485,6 +514,7 @@ format, }); } + - (void)registerStateTransitionWatcher:(OctagonStateTransitionWatcher*)watcher { dispatch_sync(self.queue, ^{ @@ -493,6 +523,18 @@ format, }); } +- (void)registerMultiStateArrivalWatcher:(OctagonStateMultiStateArrivalWatcher*)watcher +{ + dispatch_sync(self.queue, ^{ + if([watcher.states containsObject:self.currentState]) { + [watcher onqueueEnterState:self.currentState]; + } else { + [self.stateMachineWatchers addObject:watcher]; + [self _onqueuePokeStateMachine]; + } + }); +} + #pragma mark - RPC Helpers - (void)doSimpleStateMachineRPC:(NSString*)name @@ -525,10 +567,10 @@ format, self.timeout = timeout; } -- (void)doWatchedStateMachineRPC:(NSString*)name - sourceStates:(NSSet*)sourceStates - path:(OctagonStateTransitionPath*)path - reply:(nonnull void (^)(NSError *error))reply +- (CKKSResultOperation*)doWatchedStateMachineRPC:(NSString*)name + sourceStates:(NSSet*)sourceStates + path:(OctagonStateTransitionPath*)path + reply:(nonnull void (^)(NSError *error))reply { statemachinelog("state-rpc", "Beginning a '%@' rpc", name); @@ -551,18 +593,21 @@ format, [self registerStateTransitionWatcher:watcher]; - WEAKIFY(self); CKKSResultOperation* replyOp = [CKKSResultOperation named:[NSString stringWithFormat: @"%@-callback", name] - withBlock:^{ - STRONGIFY(self); - statemachinelog("state-rpc", "Returning '%@' result: %@", name, watcher.result.error ?: @"no error"); - reply(watcher.result.error); - }]; + withBlockTakingSelf:^(CKKSResultOperation * _Nonnull op) { + statemachinelog("state-rpc", "Returning '%@' result: %@", name, watcher.result.error ?: @"no error"); + if(reply) { + reply(watcher.result.error); + } + op.error = watcher.result.error; + }]; + [replyOp addDependency:watcher.result]; [self.operationQueue addOperation:replyOp]; [self handleExternalRequest:request]; + return replyOp; } @end diff --git a/keychain/ot/OctagonStateMachineHelpers.h b/keychain/ot/OctagonStateMachineHelpers.h index d936223d..886eed85 100644 --- a/keychain/ot/OctagonStateMachineHelpers.h +++ b/keychain/ot/OctagonStateMachineHelpers.h @@ -25,6 +25,7 @@ #import #import "keychain/ckks/CKKSResultOperation.h" +#import "keychain/ckks/CKKSGroupOperation.h" #import "keychain/ckks/CKKSAnalytics.h" NS_ASSUME_NONNULL_BEGIN @@ -66,6 +67,17 @@ extern OctagonState* const OctagonStateMachineHalted; entering:(OctagonState*)intendedState NS_SWIFT_NAME(init(name:entering:)); @end +// Just like OctagonStateTransitionOperation, but as a Group Operation +@interface OctagonStateTransitionGroupOperation : CKKSGroupOperation +@property OctagonState* nextState; +@property (readonly) OctagonState* intendedState; + ++ (instancetype)named:(NSString*)name + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState + withBlockTakingSelf:(void(^)(OctagonStateTransitionGroupOperation* op))block; +@end + @interface OctagonStateTransitionRequest<__covariant OperationType : CKKSResultOperation*> : NSObject @property (readonly) NSString* name; diff --git a/keychain/ot/OctagonStateMachineHelpers.m b/keychain/ot/OctagonStateMachineHelpers.m index a2362e32..c20803f7 100644 --- a/keychain/ot/OctagonStateMachineHelpers.m +++ b/keychain/ot/OctagonStateMachineHelpers.m @@ -32,7 +32,9 @@ OctagonState* const OctagonStateMachineNotStarted = (OctagonState*) @"not_started"; OctagonState* const OctagonStateMachineHalted = (OctagonState*) @"halted"; -@implementation OctagonStateTransitionOperation : CKKSResultOperation +#pragma mark -- OctagonStateTransitionOperation + +@implementation OctagonStateTransitionOperation - (instancetype)initIntending:(OctagonState*)intendedState errorState:(OctagonState*)errorState { @@ -75,6 +77,43 @@ OctagonState* const OctagonStateMachineHalted = (OctagonState*) @"halted"; @end +#pragma mark -- OctagonStateTransitionGroupOperation + +@implementation OctagonStateTransitionGroupOperation +- (instancetype)initIntending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState +{ + if((self = [super init])) { + _nextState = errorState; + _intendedState = intendedState; + } + return self; +} + +- (NSString*)description +{ + return [NSString stringWithFormat:@"", self.name, self.intendedState, self.nextState]; +} + ++ (instancetype)named:(NSString*)name + intending:(OctagonState*)intendedState + errorState:(OctagonState*)errorState + withBlockTakingSelf:(void(^)(OctagonStateTransitionGroupOperation* op))block +{ + OctagonStateTransitionGroupOperation* op = [[self alloc] initIntending:intendedState + errorState:errorState]; + WEAKIFY(op); + [op runBeforeGroupFinished:[NSBlockOperation blockOperationWithBlock:^{ + STRONGIFY(op); + block(op); + }]]; + op.name = name; + return op; +} +@end + +#pragma mark -- OctagonStateTransitionRequest + @interface OctagonStateTransitionRequest () @property dispatch_queue_t queue; @property bool timeoutCanOccur; @@ -104,7 +143,7 @@ OctagonState* const OctagonStateMachineHalted = (OctagonState*) @"halted"; - (NSString*)description { - return [NSString stringWithFormat:@"", self.name, self.transitionOperation, self.sourceStates]; + return [NSString stringWithFormat:@"", self.name, self.transitionOperation, (unsigned int)[self.sourceStates count]]; } - (CKKSResultOperation* _Nullable)_onqueueStart diff --git a/keychain/ot/OctagonStateMachineObservers.h b/keychain/ot/OctagonStateMachineObservers.h index afa30844..806da455 100644 --- a/keychain/ot/OctagonStateMachineObservers.h +++ b/keychain/ot/OctagonStateMachineObservers.h @@ -44,7 +44,13 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface OctagonStateTransitionWatcher : NSObject + +@protocol OctagonStateTransitionWatcherProtocol +@property (readonly) CKKSResultOperation* result; +- (void)onqueueHandleTransition:(CKKSResultOperation*)attempt; +@end + +@interface OctagonStateTransitionWatcher : NSObject @property (readonly) NSString* name; @property (readonly) CKKSResultOperation* result; @property (readonly) OctagonStateTransitionPath* intendedPath; @@ -57,7 +63,22 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)timeout:(dispatch_time_t)timeout; -- (void)onqueueHandleTransition:(CKKSResultOperation*)attempt; +@end + +// Reports on if any of the given states are entered +@interface OctagonStateMultiStateArrivalWatcher : NSObject +@property (readonly) NSString* name; +@property (readonly) CKKSResultOperation* result; +@property (readonly) NSSet* states; + +- (instancetype)initNamed:(NSString*)name + serialQueue:(dispatch_queue_t)queue + states:(NSSet*)states; + +// Called by the state machine if it's already in a state at registration time +- (void)onqueueEnterState:(OctagonState*)state; + +- (instancetype)timeout:(dispatch_time_t)timeout; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/OctagonStateMachineObservers.m b/keychain/ot/OctagonStateMachineObservers.m index d7e86808..e7a819f2 100644 --- a/keychain/ot/OctagonStateMachineObservers.m +++ b/keychain/ot/OctagonStateMachineObservers.m @@ -268,4 +268,91 @@ @end +#pragma mark - OctagonStateMultiStateArrivalWatcher + +@interface OctagonStateMultiStateArrivalWatcher () +@property BOOL completed; +@property NSOperationQueue* operationQueue; + +@property (nullable) CKKSResultOperation* initialTimeoutListenerOp; + +@property bool timeoutCanOccur; +@property dispatch_queue_t queue; +@end + + +@implementation OctagonStateMultiStateArrivalWatcher +- (instancetype)initNamed:(NSString*)name + serialQueue:(dispatch_queue_t)queue + states:(NSSet*)states +{ + if((self = [super init])) { + _name = name; + _states = states; + + _result = [CKKSResultOperation named:[NSString stringWithFormat:@"watcher-%@", name] withBlock:^{}]; + _operationQueue = [[NSOperationQueue alloc] init]; + + _queue = queue; + _timeoutCanOccur = true; + + _completed = NO; + } + return self; +} + +- (void)onqueueHandleTransition:(CKKSResultOperation*)attempt +{ + dispatch_assert_queue(self.queue); + [self onqueueEnterState:attempt.nextState]; +} + +- (void)onqueueEnterState:(OctagonState*)state +{ + if(!self.completed) { + if([self.states containsObject:state]) { + [self onqueueStartFinishOperation]; + } + } +} + +- (void)_onqueuePerformTimeoutWithUnderlyingError +{ + dispatch_assert_queue(self.queue); + + if(self.timeoutCanOccur) { + self.timeoutCanOccur = false; + + NSString* description = [NSString stringWithFormat:@"Operation(%@) timed out waiting to start for any state in [%@]", + self.name, + self.states]; + + self.result.error = [NSError errorWithDomain:CKKSResultErrorDomain + code:CKKSResultTimedOut + description:description]; + [self onqueueStartFinishOperation]; + } +} + +- (instancetype)timeout:(dispatch_time_t)timeout +{ + WEAKIFY(self); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeout), self.queue, ^{ + STRONGIFY(self); + [self _onqueuePerformTimeoutWithUnderlyingError]; + }); + + return self; +} + +- (void)onqueueStartFinishOperation { + dispatch_assert_queue(self.queue); + + self.timeoutCanOccur = false; + [self.operationQueue addOperation:self.result]; + self.completed = TRUE; +} +@end + + #endif diff --git a/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h b/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h index b60e47ea..015ea20b 100644 --- a/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h +++ b/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.h @@ -15,10 +15,10 @@ NS_ASSUME_NONNULL_BEGIN + (OTAccountMetadataClassC* _Nullable)loadFromKeychainForContainer:(NSString*)containerName contextID:(NSString*)contextID error:(NSError**)error; @end -@class TPPolicy; +@class TPSyncingPolicy; @interface OTAccountMetadataClassC (NSSecureCodingSupport) -- (void)setTPPolicy:(TPPolicy* _Nullable)policy; -- (TPPolicy* _Nullable)getTPPolicy; +- (void)setTPSyncingPolicy:(TPSyncingPolicy* _Nullable)policy; +- (TPSyncingPolicy* _Nullable)getTPSyncingPolicy; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.m b/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.m index ced8b4d2..11731a47 100644 --- a/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.m +++ b/keychain/ot/categories/OTAccountMetadataClassC+KeychainSupport.m @@ -12,7 +12,7 @@ #import "keychain/ot/OTDefines.h" #import "keychain/ot/OTConstants.h" -#import +#import @implementation OTAccountMetadataClassC (KeychainSupport) @@ -161,7 +161,7 @@ #pragma mark - Field Coding support -- (void)setTPPolicy:(TPPolicy*)policy +- (void)setTPSyncingPolicy:(TPSyncingPolicy*)policy { if(policy) { NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; @@ -172,10 +172,10 @@ } } -- (TPPolicy* _Nullable)getTPPolicy +- (TPSyncingPolicy* _Nullable)getTPSyncingPolicy { NSKeyedUnarchiver *coder = [[NSKeyedUnarchiver alloc] initForReadingFromData:self.syncingPolicy error:nil]; - TPPolicy* policy = [[TPPolicy alloc] initWithCoder:coder]; + TPSyncingPolicy* policy = [[TPSyncingPolicy alloc] initWithCoder:coder]; [coder finishDecoding]; return policy; diff --git a/keychain/ot/categories/OctagonEscrowRecoverer.h b/keychain/ot/categories/OctagonEscrowRecoverer.h index 204e720c..e69060b8 100644 --- a/keychain/ot/categories/OctagonEscrowRecoverer.h +++ b/keychain/ot/categories/OctagonEscrowRecoverer.h @@ -4,16 +4,12 @@ #ifndef OctagonEscrowRecoverer_h #define OctagonEscrowRecoverer_h -#import - @protocol OctagonEscrowRecovererPrococol - (NSError*)recoverWithInfo:(NSDictionary*)info results:(NSDictionary**)results; +- (NSError *)getAccountInfoWithInfo:(NSDictionary *)info results:(NSDictionary**)results; - (NSError *)disableWithInfo:(NSDictionary *)info; @end -@interface SecureBackup (OctagonProtocolConformance) -@end - #endif /* OctagonEscrowRecoverer_h */ #endif // OCTAGON diff --git a/keychain/ot/proto/OTAccountMetadataClassC.proto b/keychain/ot/proto/OTAccountMetadataClassC.proto index d706b6d9..8bf438e2 100644 --- a/keychain/ot/proto/OTAccountMetadataClassC.proto +++ b/keychain/ot/proto/OTAccountMetadataClassC.proto @@ -55,7 +55,14 @@ message AccountMetadataClassC { optional CDPState cdpState = 8; - // These store the current policy and view list, so that we don't need to re-ask TPH every time - optional bytes syncingPolicy = 9; - repeated string syncingView = 10; + // Used during development + //reserved 9; + //reserved 10; + + // This holds the current syncing policy for the local peer, including the view list. + optional bytes syncingPolicy = 11; + + // This might contain a voucher for use in joining Octagon. + optional bytes voucher = 12; + optional bytes voucherSignature = 13; } diff --git a/keychain/ot/proto/OTCDPRecoveryInformation.proto b/keychain/ot/proto/OTCDPRecoveryInformation.proto new file mode 100644 index 00000000..04f28dbc --- /dev/null +++ b/keychain/ot/proto/OTCDPRecoveryInformation.proto @@ -0,0 +1,37 @@ +syntax = "proto2"; + +option objc_class_naming = "extended"; + +package OT; +import "OTEscrowRecord.proto"; + +message CDPRecoveryInformation { + optional string recovery_secret = 1; + optional bool use_cached_secret = 2; + optional string recovery_key = 3; + optional bool use_previously_cached_recovery_key = 4; + optional bool silent_recovery_attempt = 5; + optional bool contains_icdp_data = 6; + optional bool uses_multiple_icsc = 7; +} + +message EscrowAuthenticationInformation { + optional string authentication_password = 1; + optional string authentication_dsid = 2; + optional string authentication_appleid = 3; + optional string fmip_uuid = 4; + optional bool fmip_recovery = 5; + optional bool idms_recovery = 6; + optional string authentication_auth_token = 7; + optional string authentication_escrowproxy_url = 8; + optional string authentication_icloud_environment = 9; +} + +message ICDPRecordContext { + optional CDPRecoveryInformation cdpInfo = 1; + optional EscrowAuthenticationInformation authInfo = 2; +} +message ICDPRecordSilentContext { + optional CDPRecoveryInformation cdpInfo = 1; + optional EscrowAuthenticationInformation authInfo = 2; +} diff --git a/keychain/ot/proto/OTEscrowRecord.proto b/keychain/ot/proto/OTEscrowRecord.proto new file mode 100644 index 00000000..3da70f01 --- /dev/null +++ b/keychain/ot/proto/OTEscrowRecord.proto @@ -0,0 +1,74 @@ +syntax = "proto2"; + +option objc_class_naming = "extended"; + +package OT; + +message EscrowRecord { + optional uint64 creation_date = 1; + optional uint64 remaining_attempts = 2; + message Metadata { + optional bytes backup_keybag_digest = 1; + message ClientMetadata { + optional uint64 secure_backup_metadata_timestamp = 1; + optional uint64 secure_backup_numeric_passphrase_length = 2; + optional uint64 secure_backup_uses_complex_passphrase = 3; + optional uint64 secure_backup_uses_numeric_passphrase = 4; + optional string device_color = 5; + optional string device_enclosure_color = 6; + optional string device_mid = 7; + optional string device_model = 8; + optional string device_model_class = 9; + optional string device_model_version = 10; + optional string device_name = 11; + optional uint64 device_platform = 12; + } + optional ClientMetadata client_metadata = 2; + optional uint64 secure_backup_uses_multiple_icscs = 3; + optional string bottle_id = 4; + optional uint64 secure_backup_timestamp = 5; + optional bytes escrowed_spki = 6; + optional bytes peer_info = 7; + optional string bottle_validity = 8; + optional string serial = 9; + } + optional Metadata escrow_information_metadata = 3; + optional string label = 4; + // optional reserved string reserved5 = 5; + // optional reserved string reserved6 = 6; + // optional reserved string reserved7 = 7; + // optional reserved string reserved8 = 8; + + optional uint64 silent_attempt_allowed = 9; + + enum RecordStatus { + RECORD_STATUS_VALID = 0; + RECORD_STATUS_INVALID = 1; + } + + optional RecordStatus record_status = 10; + optional string record_id = 11; + + enum RecoveryStatus { + RECOVERY_STATUS_VALID = 0; + RECOVERY_STATUS_SOFT_LIMIT_REACHED = 1; + RECOVERY_STATUS_HARD_LIMIT_REACHED = 2; + } + optional RecoveryStatus recovery_status = 12; + optional uint64 cool_off_end = 13; + optional string serial_number = 14; + + enum RecordViability { + RECORD_VIABILITY_FULLY_VIABLE = 0; + RECORD_VIABILITY_PARTIALLY_VIABLE = 1; + RECORD_VIABILITY_LEGACY = 2; + } + optional RecordViability record_viability = 15; + + enum SOSViability { + SOS_VIABLE_UNKNOWN = 0; + SOS_VIABLE = 1; + SOS_NOT_VIABLE = 2; + } + optional SOSViability viability_status = 16; +} diff --git a/keychain/ot/proto/OTPairingMessage.proto b/keychain/ot/proto/OTPairingMessage.proto index edc46473..d6e3fe63 100644 --- a/keychain/ot/proto/OTPairingMessage.proto +++ b/keychain/ot/proto/OTPairingMessage.proto @@ -28,6 +28,19 @@ option objc_class_visibility = "hidden"; package OT; +enum SupportType { + unknown = 0; + supported = 1; + not_supported = 2; +} + +message supportSOSMessage { + optional SupportType supported = 1; +} + +message supportOctagonMessage { + optional SupportType supported = 1; +} message SponsorToApplicantRound1M2 { optional uint64 epoch = 1; @@ -54,4 +67,6 @@ message PairingMessage { optional SponsorToApplicantRound2M2 voucher = 3; // reserved is not a keyword (it should be) // reserved 4; + optional supportOctagonMessage supportsOctagon = 5; + optional supportSOSMessage supportsSOS = 6; } diff --git a/keychain/ot/proto/generated_source/OTAccountMetadataClassC.h b/keychain/ot/proto/generated_source/OTAccountMetadataClassC.h index 295d83b6..1f645a69 100644 --- a/keychain/ot/proto/generated_source/OTAccountMetadataClassC.h +++ b/keychain/ot/proto/generated_source/OTAccountMetadataClassC.h @@ -138,8 +138,9 @@ __attribute__((visibility("hidden"))) OTAccountMetadataClassC_AccountState _icloudAccountState; NSString *_peerID; NSData *_syncingPolicy; - NSMutableArray *_syncingViews; OTAccountMetadataClassC_TrustState _trustState; + NSData *_voucher; + NSData *_voucherSignature; struct { int epoch:1; int lastHealthCheckup:1; @@ -185,15 +186,20 @@ __attribute__((visibility("hidden"))) - (OTAccountMetadataClassC_CDPState)StringAsCdpState:(NSString *)str; @property (nonatomic, readonly) BOOL hasSyncingPolicy; -/** These store the current policy and view list, so that we don't need to re-ask TPH every time */ +/** + * Used during development + * reserved 9; + * reserved 10; + * This holds the current syncing policy for the local peer, including the view list. + */ @property (nonatomic, retain) NSData *syncingPolicy; -@property (nonatomic, retain) NSMutableArray *syncingViews; -- (void)clearSyncingViews; -- (void)addSyncingView:(NSString *)i; -- (NSUInteger)syncingViewsCount; -- (NSString *)syncingViewAtIndex:(NSUInteger)idx; -+ (Class)syncingViewType; +@property (nonatomic, readonly) BOOL hasVoucher; +/** This might contain a voucher for use in joining Octagon. */ +@property (nonatomic, retain) NSData *voucher; + +@property (nonatomic, readonly) BOOL hasVoucherSignature; +@property (nonatomic, retain) NSData *voucherSignature; // Performs a shallow copy into other - (void)copyTo:(OTAccountMetadataClassC *)other; diff --git a/keychain/ot/proto/generated_source/OTAccountMetadataClassC.m b/keychain/ot/proto/generated_source/OTAccountMetadataClassC.m index 40c4de46..5dbcb98f 100644 --- a/keychain/ot/proto/generated_source/OTAccountMetadataClassC.m +++ b/keychain/ot/proto/generated_source/OTAccountMetadataClassC.m @@ -160,31 +160,16 @@ return _syncingPolicy != nil; } @synthesize syncingPolicy = _syncingPolicy; -@synthesize syncingViews = _syncingViews; -- (void)clearSyncingViews +- (BOOL)hasVoucher { - [_syncingViews removeAllObjects]; + return _voucher != nil; } -- (void)addSyncingView:(NSString *)i +@synthesize voucher = _voucher; +- (BOOL)hasVoucherSignature { - if (!_syncingViews) - { - _syncingViews = [[NSMutableArray alloc] init]; - } - [_syncingViews addObject:i]; -} -- (NSUInteger)syncingViewsCount -{ - return [_syncingViews count]; -} -- (NSString *)syncingViewAtIndex:(NSUInteger)idx -{ - return [_syncingViews objectAtIndex:idx]; -} -+ (Class)syncingViewType -{ - return [NSString class]; + return _voucherSignature != nil; } +@synthesize voucherSignature = _voucherSignature; - (NSString *)description { @@ -230,9 +215,13 @@ { [dict setObject:self->_syncingPolicy forKey:@"syncingPolicy"]; } - if (self->_syncingViews) + if (self->_voucher) + { + [dict setObject:self->_voucher forKey:@"voucher"]; + } + if (self->_voucherSignature) { - [dict setObject:self->_syncingViews forKey:@"syncingView"]; + [dict setObject:self->_voucherSignature forKey:@"voucherSignature"]; } return dict; } @@ -301,19 +290,22 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC self->_cdpState = PBReaderReadInt32(reader); } break; - case 9 /* syncingPolicy */: + case 11 /* syncingPolicy */: { NSData *new_syncingPolicy = PBReaderReadData(reader); self->_syncingPolicy = new_syncingPolicy; } break; - case 10 /* syncingViews */: + case 12 /* voucher */: { - NSString *new_syncingViews = PBReaderReadString(reader); - if (new_syncingViews) - { - [self addSyncingView:new_syncingViews]; - } + NSData *new_voucher = PBReaderReadData(reader); + self->_voucher = new_voucher; + } + break; + case 13 /* voucherSignature */: + { + NSData *new_voucherSignature = PBReaderReadData(reader); + self->_voucherSignature = new_voucherSignature; } break; default: @@ -391,14 +383,21 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC { if (self->_syncingPolicy) { - PBDataWriterWriteDataField(writer, self->_syncingPolicy, 9); + PBDataWriterWriteDataField(writer, self->_syncingPolicy, 11); } } - /* syncingViews */ + /* voucher */ { - for (NSString *s_syncingViews in self->_syncingViews) + if (self->_voucher) { - PBDataWriterWriteStringField(writer, s_syncingViews, 10); + PBDataWriterWriteDataField(writer, self->_voucher, 12); + } + } + /* voucherSignature */ + { + if (self->_voucherSignature) + { + PBDataWriterWriteDataField(writer, self->_voucherSignature, 13); } } } @@ -447,14 +446,13 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC { other.syncingPolicy = _syncingPolicy; } - if ([self syncingViewsCount]) + if (_voucher) { - [other clearSyncingViews]; - NSUInteger syncingViewsCnt = [self syncingViewsCount]; - for (NSUInteger i = 0; i < syncingViewsCnt; i++) - { - [other addSyncingView:[self syncingViewAtIndex:i]]; - } + other.voucher = _voucher; + } + if (_voucherSignature) + { + other.voucherSignature = _voucherSignature; } } @@ -494,11 +492,8 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC copy->_has.cdpState = YES; } copy->_syncingPolicy = [_syncingPolicy copyWithZone:zone]; - for (NSString *v in _syncingViews) - { - NSString *vCopy = [v copyWithZone:zone]; - [copy addSyncingView:vCopy]; - } + copy->_voucher = [_voucher copyWithZone:zone]; + copy->_voucherSignature = [_voucherSignature copyWithZone:zone]; return copy; } @@ -525,7 +520,9 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC && ((!self->_syncingPolicy && !other->_syncingPolicy) || [self->_syncingPolicy isEqual:other->_syncingPolicy]) && - ((!self->_syncingViews && !other->_syncingViews) || [self->_syncingViews isEqual:other->_syncingViews]) + ((!self->_voucher && !other->_voucher) || [self->_voucher isEqual:other->_voucher]) + && + ((!self->_voucherSignature && !other->_voucherSignature) || [self->_voucherSignature isEqual:other->_voucherSignature]) ; } @@ -551,7 +548,9 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC ^ [self->_syncingPolicy hash] ^ - [self->_syncingViews hash] + [self->_voucher hash] + ^ + [self->_voucherSignature hash] ; } @@ -599,9 +598,13 @@ BOOL OTAccountMetadataClassCReadFrom(__unsafe_unretained OTAccountMetadataClassC { [self setSyncingPolicy:other->_syncingPolicy]; } - for (NSString *iter_syncingViews in other->_syncingViews) + if (other->_voucher) + { + [self setVoucher:other->_voucher]; + } + if (other->_voucherSignature) { - [self addSyncingView:iter_syncingViews]; + [self setVoucherSignature:other->_voucherSignature]; } } diff --git a/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.h b/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.h new file mode 100644 index 00000000..2e070eac --- /dev/null +++ b/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.h @@ -0,0 +1,66 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import +#import + +#ifdef __cplusplus +#define OTCDPRECOVERYINFORMATION_FUNCTION extern "C" +#else +#define OTCDPRECOVERYINFORMATION_FUNCTION extern +#endif + +@interface OTCDPRecoveryInformation : PBCodable +{ + NSString *_recoveryKey; + NSString *_recoverySecret; + BOOL _containsIcdpData; + BOOL _silentRecoveryAttempt; + BOOL _useCachedSecret; + BOOL _usePreviouslyCachedRecoveryKey; + BOOL _usesMultipleIcsc; + struct { + int containsIcdpData:1; + int silentRecoveryAttempt:1; + int useCachedSecret:1; + int usePreviouslyCachedRecoveryKey:1; + int usesMultipleIcsc:1; + } _has; +} + + +@property (nonatomic, readonly) BOOL hasRecoverySecret; +@property (nonatomic, retain) NSString *recoverySecret; + +@property (nonatomic) BOOL hasUseCachedSecret; +@property (nonatomic) BOOL useCachedSecret; + +@property (nonatomic, readonly) BOOL hasRecoveryKey; +@property (nonatomic, retain) NSString *recoveryKey; + +@property (nonatomic) BOOL hasUsePreviouslyCachedRecoveryKey; +@property (nonatomic) BOOL usePreviouslyCachedRecoveryKey; + +@property (nonatomic) BOOL hasSilentRecoveryAttempt; +@property (nonatomic) BOOL silentRecoveryAttempt; + +@property (nonatomic) BOOL hasContainsIcdpData; +@property (nonatomic) BOOL containsIcdpData; + +@property (nonatomic) BOOL hasUsesMultipleIcsc; +@property (nonatomic) BOOL usesMultipleIcsc; + +// Performs a shallow copy into other +- (void)copyTo:(OTCDPRecoveryInformation *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTCDPRecoveryInformation *)other; + +OTCDPRECOVERYINFORMATION_FUNCTION BOOL OTCDPRecoveryInformationReadFrom(__unsafe_unretained OTCDPRecoveryInformation *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.m b/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.m new file mode 100644 index 00000000..242d1634 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTCDPRecoveryInformation.m @@ -0,0 +1,409 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import "OTCDPRecoveryInformation.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTCDPRecoveryInformation + +- (BOOL)hasRecoverySecret +{ + return _recoverySecret != nil; +} +@synthesize recoverySecret = _recoverySecret; +@synthesize useCachedSecret = _useCachedSecret; +- (void)setUseCachedSecret:(BOOL)v +{ + _has.useCachedSecret = YES; + _useCachedSecret = v; +} +- (void)setHasUseCachedSecret:(BOOL)f +{ + _has.useCachedSecret = f; +} +- (BOOL)hasUseCachedSecret +{ + return _has.useCachedSecret != 0; +} +- (BOOL)hasRecoveryKey +{ + return _recoveryKey != nil; +} +@synthesize recoveryKey = _recoveryKey; +@synthesize usePreviouslyCachedRecoveryKey = _usePreviouslyCachedRecoveryKey; +- (void)setUsePreviouslyCachedRecoveryKey:(BOOL)v +{ + _has.usePreviouslyCachedRecoveryKey = YES; + _usePreviouslyCachedRecoveryKey = v; +} +- (void)setHasUsePreviouslyCachedRecoveryKey:(BOOL)f +{ + _has.usePreviouslyCachedRecoveryKey = f; +} +- (BOOL)hasUsePreviouslyCachedRecoveryKey +{ + return _has.usePreviouslyCachedRecoveryKey != 0; +} +@synthesize silentRecoveryAttempt = _silentRecoveryAttempt; +- (void)setSilentRecoveryAttempt:(BOOL)v +{ + _has.silentRecoveryAttempt = YES; + _silentRecoveryAttempt = v; +} +- (void)setHasSilentRecoveryAttempt:(BOOL)f +{ + _has.silentRecoveryAttempt = f; +} +- (BOOL)hasSilentRecoveryAttempt +{ + return _has.silentRecoveryAttempt != 0; +} +@synthesize containsIcdpData = _containsIcdpData; +- (void)setContainsIcdpData:(BOOL)v +{ + _has.containsIcdpData = YES; + _containsIcdpData = v; +} +- (void)setHasContainsIcdpData:(BOOL)f +{ + _has.containsIcdpData = f; +} +- (BOOL)hasContainsIcdpData +{ + return _has.containsIcdpData != 0; +} +@synthesize usesMultipleIcsc = _usesMultipleIcsc; +- (void)setUsesMultipleIcsc:(BOOL)v +{ + _has.usesMultipleIcsc = YES; + _usesMultipleIcsc = v; +} +- (void)setHasUsesMultipleIcsc:(BOOL)f +{ + _has.usesMultipleIcsc = f; +} +- (BOOL)hasUsesMultipleIcsc +{ + return _has.usesMultipleIcsc != 0; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_recoverySecret) + { + [dict setObject:self->_recoverySecret forKey:@"recovery_secret"]; + } + if (self->_has.useCachedSecret) + { + [dict setObject:[NSNumber numberWithBool:self->_useCachedSecret] forKey:@"use_cached_secret"]; + } + if (self->_recoveryKey) + { + [dict setObject:self->_recoveryKey forKey:@"recovery_key"]; + } + if (self->_has.usePreviouslyCachedRecoveryKey) + { + [dict setObject:[NSNumber numberWithBool:self->_usePreviouslyCachedRecoveryKey] forKey:@"use_previously_cached_recovery_key"]; + } + if (self->_has.silentRecoveryAttempt) + { + [dict setObject:[NSNumber numberWithBool:self->_silentRecoveryAttempt] forKey:@"silent_recovery_attempt"]; + } + if (self->_has.containsIcdpData) + { + [dict setObject:[NSNumber numberWithBool:self->_containsIcdpData] forKey:@"contains_icdp_data"]; + } + if (self->_has.usesMultipleIcsc) + { + [dict setObject:[NSNumber numberWithBool:self->_usesMultipleIcsc] forKey:@"uses_multiple_icsc"]; + } + return dict; +} + +BOOL OTCDPRecoveryInformationReadFrom(__unsafe_unretained OTCDPRecoveryInformation *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* recoverySecret */: + { + NSString *new_recoverySecret = PBReaderReadString(reader); + self->_recoverySecret = new_recoverySecret; + } + break; + case 2 /* useCachedSecret */: + { + self->_has.useCachedSecret = YES; + self->_useCachedSecret = PBReaderReadBOOL(reader); + } + break; + case 3 /* recoveryKey */: + { + NSString *new_recoveryKey = PBReaderReadString(reader); + self->_recoveryKey = new_recoveryKey; + } + break; + case 4 /* usePreviouslyCachedRecoveryKey */: + { + self->_has.usePreviouslyCachedRecoveryKey = YES; + self->_usePreviouslyCachedRecoveryKey = PBReaderReadBOOL(reader); + } + break; + case 5 /* silentRecoveryAttempt */: + { + self->_has.silentRecoveryAttempt = YES; + self->_silentRecoveryAttempt = PBReaderReadBOOL(reader); + } + break; + case 6 /* containsIcdpData */: + { + self->_has.containsIcdpData = YES; + self->_containsIcdpData = PBReaderReadBOOL(reader); + } + break; + case 7 /* usesMultipleIcsc */: + { + self->_has.usesMultipleIcsc = YES; + self->_usesMultipleIcsc = PBReaderReadBOOL(reader); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTCDPRecoveryInformationReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* recoverySecret */ + { + if (self->_recoverySecret) + { + PBDataWriterWriteStringField(writer, self->_recoverySecret, 1); + } + } + /* useCachedSecret */ + { + if (self->_has.useCachedSecret) + { + PBDataWriterWriteBOOLField(writer, self->_useCachedSecret, 2); + } + } + /* recoveryKey */ + { + if (self->_recoveryKey) + { + PBDataWriterWriteStringField(writer, self->_recoveryKey, 3); + } + } + /* usePreviouslyCachedRecoveryKey */ + { + if (self->_has.usePreviouslyCachedRecoveryKey) + { + PBDataWriterWriteBOOLField(writer, self->_usePreviouslyCachedRecoveryKey, 4); + } + } + /* silentRecoveryAttempt */ + { + if (self->_has.silentRecoveryAttempt) + { + PBDataWriterWriteBOOLField(writer, self->_silentRecoveryAttempt, 5); + } + } + /* containsIcdpData */ + { + if (self->_has.containsIcdpData) + { + PBDataWriterWriteBOOLField(writer, self->_containsIcdpData, 6); + } + } + /* usesMultipleIcsc */ + { + if (self->_has.usesMultipleIcsc) + { + PBDataWriterWriteBOOLField(writer, self->_usesMultipleIcsc, 7); + } + } +} + +- (void)copyTo:(OTCDPRecoveryInformation *)other +{ + if (_recoverySecret) + { + other.recoverySecret = _recoverySecret; + } + if (self->_has.useCachedSecret) + { + other->_useCachedSecret = _useCachedSecret; + other->_has.useCachedSecret = YES; + } + if (_recoveryKey) + { + other.recoveryKey = _recoveryKey; + } + if (self->_has.usePreviouslyCachedRecoveryKey) + { + other->_usePreviouslyCachedRecoveryKey = _usePreviouslyCachedRecoveryKey; + other->_has.usePreviouslyCachedRecoveryKey = YES; + } + if (self->_has.silentRecoveryAttempt) + { + other->_silentRecoveryAttempt = _silentRecoveryAttempt; + other->_has.silentRecoveryAttempt = YES; + } + if (self->_has.containsIcdpData) + { + other->_containsIcdpData = _containsIcdpData; + other->_has.containsIcdpData = YES; + } + if (self->_has.usesMultipleIcsc) + { + other->_usesMultipleIcsc = _usesMultipleIcsc; + other->_has.usesMultipleIcsc = YES; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTCDPRecoveryInformation *copy = [[[self class] allocWithZone:zone] init]; + copy->_recoverySecret = [_recoverySecret copyWithZone:zone]; + if (self->_has.useCachedSecret) + { + copy->_useCachedSecret = _useCachedSecret; + copy->_has.useCachedSecret = YES; + } + copy->_recoveryKey = [_recoveryKey copyWithZone:zone]; + if (self->_has.usePreviouslyCachedRecoveryKey) + { + copy->_usePreviouslyCachedRecoveryKey = _usePreviouslyCachedRecoveryKey; + copy->_has.usePreviouslyCachedRecoveryKey = YES; + } + if (self->_has.silentRecoveryAttempt) + { + copy->_silentRecoveryAttempt = _silentRecoveryAttempt; + copy->_has.silentRecoveryAttempt = YES; + } + if (self->_has.containsIcdpData) + { + copy->_containsIcdpData = _containsIcdpData; + copy->_has.containsIcdpData = YES; + } + if (self->_has.usesMultipleIcsc) + { + copy->_usesMultipleIcsc = _usesMultipleIcsc; + copy->_has.usesMultipleIcsc = YES; + } + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTCDPRecoveryInformation *other = (OTCDPRecoveryInformation *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_recoverySecret && !other->_recoverySecret) || [self->_recoverySecret isEqual:other->_recoverySecret]) + && + ((self->_has.useCachedSecret && other->_has.useCachedSecret && ((self->_useCachedSecret && other->_useCachedSecret) || (!self->_useCachedSecret && !other->_useCachedSecret))) || (!self->_has.useCachedSecret && !other->_has.useCachedSecret)) + && + ((!self->_recoveryKey && !other->_recoveryKey) || [self->_recoveryKey isEqual:other->_recoveryKey]) + && + ((self->_has.usePreviouslyCachedRecoveryKey && other->_has.usePreviouslyCachedRecoveryKey && ((self->_usePreviouslyCachedRecoveryKey && other->_usePreviouslyCachedRecoveryKey) || (!self->_usePreviouslyCachedRecoveryKey && !other->_usePreviouslyCachedRecoveryKey))) || (!self->_has.usePreviouslyCachedRecoveryKey && !other->_has.usePreviouslyCachedRecoveryKey)) + && + ((self->_has.silentRecoveryAttempt && other->_has.silentRecoveryAttempt && ((self->_silentRecoveryAttempt && other->_silentRecoveryAttempt) || (!self->_silentRecoveryAttempt && !other->_silentRecoveryAttempt))) || (!self->_has.silentRecoveryAttempt && !other->_has.silentRecoveryAttempt)) + && + ((self->_has.containsIcdpData && other->_has.containsIcdpData && ((self->_containsIcdpData && other->_containsIcdpData) || (!self->_containsIcdpData && !other->_containsIcdpData))) || (!self->_has.containsIcdpData && !other->_has.containsIcdpData)) + && + ((self->_has.usesMultipleIcsc && other->_has.usesMultipleIcsc && ((self->_usesMultipleIcsc && other->_usesMultipleIcsc) || (!self->_usesMultipleIcsc && !other->_usesMultipleIcsc))) || (!self->_has.usesMultipleIcsc && !other->_has.usesMultipleIcsc)) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_recoverySecret hash] + ^ + (self->_has.useCachedSecret ? PBHashInt((NSUInteger)self->_useCachedSecret) : 0) + ^ + [self->_recoveryKey hash] + ^ + (self->_has.usePreviouslyCachedRecoveryKey ? PBHashInt((NSUInteger)self->_usePreviouslyCachedRecoveryKey) : 0) + ^ + (self->_has.silentRecoveryAttempt ? PBHashInt((NSUInteger)self->_silentRecoveryAttempt) : 0) + ^ + (self->_has.containsIcdpData ? PBHashInt((NSUInteger)self->_containsIcdpData) : 0) + ^ + (self->_has.usesMultipleIcsc ? PBHashInt((NSUInteger)self->_usesMultipleIcsc) : 0) + ; +} + +- (void)mergeFrom:(OTCDPRecoveryInformation *)other +{ + if (other->_recoverySecret) + { + [self setRecoverySecret:other->_recoverySecret]; + } + if (other->_has.useCachedSecret) + { + self->_useCachedSecret = other->_useCachedSecret; + self->_has.useCachedSecret = YES; + } + if (other->_recoveryKey) + { + [self setRecoveryKey:other->_recoveryKey]; + } + if (other->_has.usePreviouslyCachedRecoveryKey) + { + self->_usePreviouslyCachedRecoveryKey = other->_usePreviouslyCachedRecoveryKey; + self->_has.usePreviouslyCachedRecoveryKey = YES; + } + if (other->_has.silentRecoveryAttempt) + { + self->_silentRecoveryAttempt = other->_silentRecoveryAttempt; + self->_has.silentRecoveryAttempt = YES; + } + if (other->_has.containsIcdpData) + { + self->_containsIcdpData = other->_containsIcdpData; + self->_has.containsIcdpData = YES; + } + if (other->_has.usesMultipleIcsc) + { + self->_usesMultipleIcsc = other->_usesMultipleIcsc; + self->_has.usesMultipleIcsc = YES; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.h b/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.h new file mode 100644 index 00000000..1956fd4d --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.h @@ -0,0 +1,71 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import +#import + +#ifdef __cplusplus +#define OTESCROWAUTHENTICATIONINFORMATION_FUNCTION extern "C" +#else +#define OTESCROWAUTHENTICATIONINFORMATION_FUNCTION extern +#endif + +@interface OTEscrowAuthenticationInformation : PBCodable +{ + NSString *_authenticationAppleid; + NSString *_authenticationAuthToken; + NSString *_authenticationDsid; + NSString *_authenticationEscrowproxyUrl; + NSString *_authenticationIcloudEnvironment; + NSString *_authenticationPassword; + NSString *_fmipUuid; + BOOL _fmipRecovery; + BOOL _idmsRecovery; + struct { + int fmipRecovery:1; + int idmsRecovery:1; + } _has; +} + + +@property (nonatomic, readonly) BOOL hasAuthenticationPassword; +@property (nonatomic, retain) NSString *authenticationPassword; + +@property (nonatomic, readonly) BOOL hasAuthenticationDsid; +@property (nonatomic, retain) NSString *authenticationDsid; + +@property (nonatomic, readonly) BOOL hasAuthenticationAppleid; +@property (nonatomic, retain) NSString *authenticationAppleid; + +@property (nonatomic, readonly) BOOL hasFmipUuid; +@property (nonatomic, retain) NSString *fmipUuid; + +@property (nonatomic) BOOL hasFmipRecovery; +@property (nonatomic) BOOL fmipRecovery; + +@property (nonatomic) BOOL hasIdmsRecovery; +@property (nonatomic) BOOL idmsRecovery; + +@property (nonatomic, readonly) BOOL hasAuthenticationAuthToken; +@property (nonatomic, retain) NSString *authenticationAuthToken; + +@property (nonatomic, readonly) BOOL hasAuthenticationEscrowproxyUrl; +@property (nonatomic, retain) NSString *authenticationEscrowproxyUrl; + +@property (nonatomic, readonly) BOOL hasAuthenticationIcloudEnvironment; +@property (nonatomic, retain) NSString *authenticationIcloudEnvironment; + +// Performs a shallow copy into other +- (void)copyTo:(OTEscrowAuthenticationInformation *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTEscrowAuthenticationInformation *)other; + +OTESCROWAUTHENTICATIONINFORMATION_FUNCTION BOOL OTEscrowAuthenticationInformationReadFrom(__unsafe_unretained OTEscrowAuthenticationInformation *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.m b/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.m new file mode 100644 index 00000000..c0b0c86f --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.m @@ -0,0 +1,434 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import "OTEscrowAuthenticationInformation.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTEscrowAuthenticationInformation + +- (BOOL)hasAuthenticationPassword +{ + return _authenticationPassword != nil; +} +@synthesize authenticationPassword = _authenticationPassword; +- (BOOL)hasAuthenticationDsid +{ + return _authenticationDsid != nil; +} +@synthesize authenticationDsid = _authenticationDsid; +- (BOOL)hasAuthenticationAppleid +{ + return _authenticationAppleid != nil; +} +@synthesize authenticationAppleid = _authenticationAppleid; +- (BOOL)hasFmipUuid +{ + return _fmipUuid != nil; +} +@synthesize fmipUuid = _fmipUuid; +@synthesize fmipRecovery = _fmipRecovery; +- (void)setFmipRecovery:(BOOL)v +{ + _has.fmipRecovery = YES; + _fmipRecovery = v; +} +- (void)setHasFmipRecovery:(BOOL)f +{ + _has.fmipRecovery = f; +} +- (BOOL)hasFmipRecovery +{ + return _has.fmipRecovery != 0; +} +@synthesize idmsRecovery = _idmsRecovery; +- (void)setIdmsRecovery:(BOOL)v +{ + _has.idmsRecovery = YES; + _idmsRecovery = v; +} +- (void)setHasIdmsRecovery:(BOOL)f +{ + _has.idmsRecovery = f; +} +- (BOOL)hasIdmsRecovery +{ + return _has.idmsRecovery != 0; +} +- (BOOL)hasAuthenticationAuthToken +{ + return _authenticationAuthToken != nil; +} +@synthesize authenticationAuthToken = _authenticationAuthToken; +- (BOOL)hasAuthenticationEscrowproxyUrl +{ + return _authenticationEscrowproxyUrl != nil; +} +@synthesize authenticationEscrowproxyUrl = _authenticationEscrowproxyUrl; +- (BOOL)hasAuthenticationIcloudEnvironment +{ + return _authenticationIcloudEnvironment != nil; +} +@synthesize authenticationIcloudEnvironment = _authenticationIcloudEnvironment; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_authenticationPassword) + { + [dict setObject:self->_authenticationPassword forKey:@"authentication_password"]; + } + if (self->_authenticationDsid) + { + [dict setObject:self->_authenticationDsid forKey:@"authentication_dsid"]; + } + if (self->_authenticationAppleid) + { + [dict setObject:self->_authenticationAppleid forKey:@"authentication_appleid"]; + } + if (self->_fmipUuid) + { + [dict setObject:self->_fmipUuid forKey:@"fmip_uuid"]; + } + if (self->_has.fmipRecovery) + { + [dict setObject:[NSNumber numberWithBool:self->_fmipRecovery] forKey:@"fmip_recovery"]; + } + if (self->_has.idmsRecovery) + { + [dict setObject:[NSNumber numberWithBool:self->_idmsRecovery] forKey:@"idms_recovery"]; + } + if (self->_authenticationAuthToken) + { + [dict setObject:self->_authenticationAuthToken forKey:@"authentication_auth_token"]; + } + if (self->_authenticationEscrowproxyUrl) + { + [dict setObject:self->_authenticationEscrowproxyUrl forKey:@"authentication_escrowproxy_url"]; + } + if (self->_authenticationIcloudEnvironment) + { + [dict setObject:self->_authenticationIcloudEnvironment forKey:@"authentication_icloud_environment"]; + } + return dict; +} + +BOOL OTEscrowAuthenticationInformationReadFrom(__unsafe_unretained OTEscrowAuthenticationInformation *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* authenticationPassword */: + { + NSString *new_authenticationPassword = PBReaderReadString(reader); + self->_authenticationPassword = new_authenticationPassword; + } + break; + case 2 /* authenticationDsid */: + { + NSString *new_authenticationDsid = PBReaderReadString(reader); + self->_authenticationDsid = new_authenticationDsid; + } + break; + case 3 /* authenticationAppleid */: + { + NSString *new_authenticationAppleid = PBReaderReadString(reader); + self->_authenticationAppleid = new_authenticationAppleid; + } + break; + case 4 /* fmipUuid */: + { + NSString *new_fmipUuid = PBReaderReadString(reader); + self->_fmipUuid = new_fmipUuid; + } + break; + case 5 /* fmipRecovery */: + { + self->_has.fmipRecovery = YES; + self->_fmipRecovery = PBReaderReadBOOL(reader); + } + break; + case 6 /* idmsRecovery */: + { + self->_has.idmsRecovery = YES; + self->_idmsRecovery = PBReaderReadBOOL(reader); + } + break; + case 7 /* authenticationAuthToken */: + { + NSString *new_authenticationAuthToken = PBReaderReadString(reader); + self->_authenticationAuthToken = new_authenticationAuthToken; + } + break; + case 8 /* authenticationEscrowproxyUrl */: + { + NSString *new_authenticationEscrowproxyUrl = PBReaderReadString(reader); + self->_authenticationEscrowproxyUrl = new_authenticationEscrowproxyUrl; + } + break; + case 9 /* authenticationIcloudEnvironment */: + { + NSString *new_authenticationIcloudEnvironment = PBReaderReadString(reader); + self->_authenticationIcloudEnvironment = new_authenticationIcloudEnvironment; + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTEscrowAuthenticationInformationReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* authenticationPassword */ + { + if (self->_authenticationPassword) + { + PBDataWriterWriteStringField(writer, self->_authenticationPassword, 1); + } + } + /* authenticationDsid */ + { + if (self->_authenticationDsid) + { + PBDataWriterWriteStringField(writer, self->_authenticationDsid, 2); + } + } + /* authenticationAppleid */ + { + if (self->_authenticationAppleid) + { + PBDataWriterWriteStringField(writer, self->_authenticationAppleid, 3); + } + } + /* fmipUuid */ + { + if (self->_fmipUuid) + { + PBDataWriterWriteStringField(writer, self->_fmipUuid, 4); + } + } + /* fmipRecovery */ + { + if (self->_has.fmipRecovery) + { + PBDataWriterWriteBOOLField(writer, self->_fmipRecovery, 5); + } + } + /* idmsRecovery */ + { + if (self->_has.idmsRecovery) + { + PBDataWriterWriteBOOLField(writer, self->_idmsRecovery, 6); + } + } + /* authenticationAuthToken */ + { + if (self->_authenticationAuthToken) + { + PBDataWriterWriteStringField(writer, self->_authenticationAuthToken, 7); + } + } + /* authenticationEscrowproxyUrl */ + { + if (self->_authenticationEscrowproxyUrl) + { + PBDataWriterWriteStringField(writer, self->_authenticationEscrowproxyUrl, 8); + } + } + /* authenticationIcloudEnvironment */ + { + if (self->_authenticationIcloudEnvironment) + { + PBDataWriterWriteStringField(writer, self->_authenticationIcloudEnvironment, 9); + } + } +} + +- (void)copyTo:(OTEscrowAuthenticationInformation *)other +{ + if (_authenticationPassword) + { + other.authenticationPassword = _authenticationPassword; + } + if (_authenticationDsid) + { + other.authenticationDsid = _authenticationDsid; + } + if (_authenticationAppleid) + { + other.authenticationAppleid = _authenticationAppleid; + } + if (_fmipUuid) + { + other.fmipUuid = _fmipUuid; + } + if (self->_has.fmipRecovery) + { + other->_fmipRecovery = _fmipRecovery; + other->_has.fmipRecovery = YES; + } + if (self->_has.idmsRecovery) + { + other->_idmsRecovery = _idmsRecovery; + other->_has.idmsRecovery = YES; + } + if (_authenticationAuthToken) + { + other.authenticationAuthToken = _authenticationAuthToken; + } + if (_authenticationEscrowproxyUrl) + { + other.authenticationEscrowproxyUrl = _authenticationEscrowproxyUrl; + } + if (_authenticationIcloudEnvironment) + { + other.authenticationIcloudEnvironment = _authenticationIcloudEnvironment; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTEscrowAuthenticationInformation *copy = [[[self class] allocWithZone:zone] init]; + copy->_authenticationPassword = [_authenticationPassword copyWithZone:zone]; + copy->_authenticationDsid = [_authenticationDsid copyWithZone:zone]; + copy->_authenticationAppleid = [_authenticationAppleid copyWithZone:zone]; + copy->_fmipUuid = [_fmipUuid copyWithZone:zone]; + if (self->_has.fmipRecovery) + { + copy->_fmipRecovery = _fmipRecovery; + copy->_has.fmipRecovery = YES; + } + if (self->_has.idmsRecovery) + { + copy->_idmsRecovery = _idmsRecovery; + copy->_has.idmsRecovery = YES; + } + copy->_authenticationAuthToken = [_authenticationAuthToken copyWithZone:zone]; + copy->_authenticationEscrowproxyUrl = [_authenticationEscrowproxyUrl copyWithZone:zone]; + copy->_authenticationIcloudEnvironment = [_authenticationIcloudEnvironment copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTEscrowAuthenticationInformation *other = (OTEscrowAuthenticationInformation *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_authenticationPassword && !other->_authenticationPassword) || [self->_authenticationPassword isEqual:other->_authenticationPassword]) + && + ((!self->_authenticationDsid && !other->_authenticationDsid) || [self->_authenticationDsid isEqual:other->_authenticationDsid]) + && + ((!self->_authenticationAppleid && !other->_authenticationAppleid) || [self->_authenticationAppleid isEqual:other->_authenticationAppleid]) + && + ((!self->_fmipUuid && !other->_fmipUuid) || [self->_fmipUuid isEqual:other->_fmipUuid]) + && + ((self->_has.fmipRecovery && other->_has.fmipRecovery && ((self->_fmipRecovery && other->_fmipRecovery) || (!self->_fmipRecovery && !other->_fmipRecovery))) || (!self->_has.fmipRecovery && !other->_has.fmipRecovery)) + && + ((self->_has.idmsRecovery && other->_has.idmsRecovery && ((self->_idmsRecovery && other->_idmsRecovery) || (!self->_idmsRecovery && !other->_idmsRecovery))) || (!self->_has.idmsRecovery && !other->_has.idmsRecovery)) + && + ((!self->_authenticationAuthToken && !other->_authenticationAuthToken) || [self->_authenticationAuthToken isEqual:other->_authenticationAuthToken]) + && + ((!self->_authenticationEscrowproxyUrl && !other->_authenticationEscrowproxyUrl) || [self->_authenticationEscrowproxyUrl isEqual:other->_authenticationEscrowproxyUrl]) + && + ((!self->_authenticationIcloudEnvironment && !other->_authenticationIcloudEnvironment) || [self->_authenticationIcloudEnvironment isEqual:other->_authenticationIcloudEnvironment]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_authenticationPassword hash] + ^ + [self->_authenticationDsid hash] + ^ + [self->_authenticationAppleid hash] + ^ + [self->_fmipUuid hash] + ^ + (self->_has.fmipRecovery ? PBHashInt((NSUInteger)self->_fmipRecovery) : 0) + ^ + (self->_has.idmsRecovery ? PBHashInt((NSUInteger)self->_idmsRecovery) : 0) + ^ + [self->_authenticationAuthToken hash] + ^ + [self->_authenticationEscrowproxyUrl hash] + ^ + [self->_authenticationIcloudEnvironment hash] + ; +} + +- (void)mergeFrom:(OTEscrowAuthenticationInformation *)other +{ + if (other->_authenticationPassword) + { + [self setAuthenticationPassword:other->_authenticationPassword]; + } + if (other->_authenticationDsid) + { + [self setAuthenticationDsid:other->_authenticationDsid]; + } + if (other->_authenticationAppleid) + { + [self setAuthenticationAppleid:other->_authenticationAppleid]; + } + if (other->_fmipUuid) + { + [self setFmipUuid:other->_fmipUuid]; + } + if (other->_has.fmipRecovery) + { + self->_fmipRecovery = other->_fmipRecovery; + self->_has.fmipRecovery = YES; + } + if (other->_has.idmsRecovery) + { + self->_idmsRecovery = other->_idmsRecovery; + self->_has.idmsRecovery = YES; + } + if (other->_authenticationAuthToken) + { + [self setAuthenticationAuthToken:other->_authenticationAuthToken]; + } + if (other->_authenticationEscrowproxyUrl) + { + [self setAuthenticationEscrowproxyUrl:other->_authenticationEscrowproxyUrl]; + } + if (other->_authenticationIcloudEnvironment) + { + [self setAuthenticationIcloudEnvironment:other->_authenticationIcloudEnvironment]; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecord.h b/keychain/ot/proto/generated_source/OTEscrowRecord.h new file mode 100644 index 00000000..54774d19 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecord.h @@ -0,0 +1,207 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import +#import + +@class OTEscrowRecordMetadata; + +typedef NS_ENUM(int32_t, OTEscrowRecord_RecordStatus) { + OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID = 0, + OTEscrowRecord_RecordStatus_RECORD_STATUS_INVALID = 1, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTEscrowRecord_RecordStatusAsString(OTEscrowRecord_RecordStatus value) +{ + switch (value) + { + case OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID: return @"RECORD_STATUS_VALID"; + case OTEscrowRecord_RecordStatus_RECORD_STATUS_INVALID: return @"RECORD_STATUS_INVALID"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTEscrowRecord_RecordStatus StringAsOTEscrowRecord_RecordStatus(NSString *value) +{ + if ([value isEqualToString:@"RECORD_STATUS_VALID"]) return OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; + if ([value isEqualToString:@"RECORD_STATUS_INVALID"]) return OTEscrowRecord_RecordStatus_RECORD_STATUS_INVALID; + return OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; +} +#endif /* __OBJC__ */ +typedef NS_ENUM(int32_t, OTEscrowRecord_RecoveryStatus) { + OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_VALID = 0, + OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_SOFT_LIMIT_REACHED = 1, + OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_HARD_LIMIT_REACHED = 2, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTEscrowRecord_RecoveryStatusAsString(OTEscrowRecord_RecoveryStatus value) +{ + switch (value) + { + case OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_VALID: return @"RECOVERY_STATUS_VALID"; + case OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_SOFT_LIMIT_REACHED: return @"RECOVERY_STATUS_SOFT_LIMIT_REACHED"; + case OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_HARD_LIMIT_REACHED: return @"RECOVERY_STATUS_HARD_LIMIT_REACHED"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTEscrowRecord_RecoveryStatus StringAsOTEscrowRecord_RecoveryStatus(NSString *value) +{ + if ([value isEqualToString:@"RECOVERY_STATUS_VALID"]) return OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_VALID; + if ([value isEqualToString:@"RECOVERY_STATUS_SOFT_LIMIT_REACHED"]) return OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_SOFT_LIMIT_REACHED; + if ([value isEqualToString:@"RECOVERY_STATUS_HARD_LIMIT_REACHED"]) return OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_HARD_LIMIT_REACHED; + return OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_VALID; +} +#endif /* __OBJC__ */ +typedef NS_ENUM(int32_t, OTEscrowRecord_RecordViability) { + OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE = 0, + OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE = 1, + OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY = 2, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTEscrowRecord_RecordViabilityAsString(OTEscrowRecord_RecordViability value) +{ + switch (value) + { + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE: return @"RECORD_VIABILITY_FULLY_VIABLE"; + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE: return @"RECORD_VIABILITY_PARTIALLY_VIABLE"; + case OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY: return @"RECORD_VIABILITY_LEGACY"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTEscrowRecord_RecordViability StringAsOTEscrowRecord_RecordViability(NSString *value) +{ + if ([value isEqualToString:@"RECORD_VIABILITY_FULLY_VIABLE"]) return OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE; + if ([value isEqualToString:@"RECORD_VIABILITY_PARTIALLY_VIABLE"]) return OTEscrowRecord_RecordViability_RECORD_VIABILITY_PARTIALLY_VIABLE; + if ([value isEqualToString:@"RECORD_VIABILITY_LEGACY"]) return OTEscrowRecord_RecordViability_RECORD_VIABILITY_LEGACY; + return OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE; +} +#endif /* __OBJC__ */ +typedef NS_ENUM(int32_t, OTEscrowRecord_SOSViability) { + OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN = 0, + OTEscrowRecord_SOSViability_SOS_VIABLE = 1, + OTEscrowRecord_SOSViability_SOS_NOT_VIABLE = 2, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTEscrowRecord_SOSViabilityAsString(OTEscrowRecord_SOSViability value) +{ + switch (value) + { + case OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN: return @"SOS_VIABLE_UNKNOWN"; + case OTEscrowRecord_SOSViability_SOS_VIABLE: return @"SOS_VIABLE"; + case OTEscrowRecord_SOSViability_SOS_NOT_VIABLE: return @"SOS_NOT_VIABLE"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTEscrowRecord_SOSViability StringAsOTEscrowRecord_SOSViability(NSString *value) +{ + if ([value isEqualToString:@"SOS_VIABLE_UNKNOWN"]) return OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN; + if ([value isEqualToString:@"SOS_VIABLE"]) return OTEscrowRecord_SOSViability_SOS_VIABLE; + if ([value isEqualToString:@"SOS_NOT_VIABLE"]) return OTEscrowRecord_SOSViability_SOS_NOT_VIABLE; + return OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN; +} +#endif /* __OBJC__ */ + +#ifdef __cplusplus +#define OTESCROWRECORD_FUNCTION extern "C" +#else +#define OTESCROWRECORD_FUNCTION extern +#endif + +@interface OTEscrowRecord : PBCodable +{ + uint64_t _coolOffEnd; + uint64_t _creationDate; + uint64_t _remainingAttempts; + uint64_t _silentAttemptAllowed; + OTEscrowRecordMetadata *_escrowInformationMetadata; + NSString *_label; + NSString *_recordId; + OTEscrowRecord_RecordStatus _recordStatus; + OTEscrowRecord_RecordViability _recordViability; + OTEscrowRecord_RecoveryStatus _recoveryStatus; + NSString *_serialNumber; + OTEscrowRecord_SOSViability _viabilityStatus; + struct { + int coolOffEnd:1; + int creationDate:1; + int remainingAttempts:1; + int silentAttemptAllowed:1; + int recordStatus:1; + int recordViability:1; + int recoveryStatus:1; + int viabilityStatus:1; + } _has; +} + + +@property (nonatomic) BOOL hasCreationDate; +@property (nonatomic) uint64_t creationDate; + +@property (nonatomic) BOOL hasRemainingAttempts; +@property (nonatomic) uint64_t remainingAttempts; + +@property (nonatomic, readonly) BOOL hasEscrowInformationMetadata; +@property (nonatomic, retain) OTEscrowRecordMetadata *escrowInformationMetadata; + +@property (nonatomic, readonly) BOOL hasLabel; +@property (nonatomic, retain) NSString *label; + +@property (nonatomic) BOOL hasSilentAttemptAllowed; +/** + * optional reserved string reserved5 = 5; + * optional reserved string reserved6 = 6; + * optional reserved string reserved7 = 7; + * optional reserved string reserved8 = 8; + */ +@property (nonatomic) uint64_t silentAttemptAllowed; + +@property (nonatomic) BOOL hasRecordStatus; +@property (nonatomic) OTEscrowRecord_RecordStatus recordStatus; +- (NSString *)recordStatusAsString:(OTEscrowRecord_RecordStatus)value; +- (OTEscrowRecord_RecordStatus)StringAsRecordStatus:(NSString *)str; + +@property (nonatomic, readonly) BOOL hasRecordId; +@property (nonatomic, retain) NSString *recordId; + +@property (nonatomic) BOOL hasRecoveryStatus; +@property (nonatomic) OTEscrowRecord_RecoveryStatus recoveryStatus; +- (NSString *)recoveryStatusAsString:(OTEscrowRecord_RecoveryStatus)value; +- (OTEscrowRecord_RecoveryStatus)StringAsRecoveryStatus:(NSString *)str; + +@property (nonatomic) BOOL hasCoolOffEnd; +@property (nonatomic) uint64_t coolOffEnd; + +@property (nonatomic, readonly) BOOL hasSerialNumber; +@property (nonatomic, retain) NSString *serialNumber; + +@property (nonatomic) BOOL hasRecordViability; +@property (nonatomic) OTEscrowRecord_RecordViability recordViability; +- (NSString *)recordViabilityAsString:(OTEscrowRecord_RecordViability)value; +- (OTEscrowRecord_RecordViability)StringAsRecordViability:(NSString *)str; + +@property (nonatomic) BOOL hasViabilityStatus; +@property (nonatomic) OTEscrowRecord_SOSViability viabilityStatus; +- (NSString *)viabilityStatusAsString:(OTEscrowRecord_SOSViability)value; +- (OTEscrowRecord_SOSViability)StringAsViabilityStatus:(NSString *)str; + +// Performs a shallow copy into other +- (void)copyTo:(OTEscrowRecord *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTEscrowRecord *)other; + +OTESCROWRECORD_FUNCTION BOOL OTEscrowRecordReadFrom(__unsafe_unretained OTEscrowRecord *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecord.m b/keychain/ot/proto/generated_source/OTEscrowRecord.m new file mode 100644 index 00000000..1650cf94 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecord.m @@ -0,0 +1,695 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import "OTEscrowRecord.h" +#import +#import +#import + +#import "OTEscrowRecordMetadata.h" + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTEscrowRecord + +@synthesize creationDate = _creationDate; +- (void)setCreationDate:(uint64_t)v +{ + _has.creationDate = YES; + _creationDate = v; +} +- (void)setHasCreationDate:(BOOL)f +{ + _has.creationDate = f; +} +- (BOOL)hasCreationDate +{ + return _has.creationDate != 0; +} +@synthesize remainingAttempts = _remainingAttempts; +- (void)setRemainingAttempts:(uint64_t)v +{ + _has.remainingAttempts = YES; + _remainingAttempts = v; +} +- (void)setHasRemainingAttempts:(BOOL)f +{ + _has.remainingAttempts = f; +} +- (BOOL)hasRemainingAttempts +{ + return _has.remainingAttempts != 0; +} +- (BOOL)hasEscrowInformationMetadata +{ + return _escrowInformationMetadata != nil; +} +@synthesize escrowInformationMetadata = _escrowInformationMetadata; +- (BOOL)hasLabel +{ + return _label != nil; +} +@synthesize label = _label; +@synthesize silentAttemptAllowed = _silentAttemptAllowed; +- (void)setSilentAttemptAllowed:(uint64_t)v +{ + _has.silentAttemptAllowed = YES; + _silentAttemptAllowed = v; +} +- (void)setHasSilentAttemptAllowed:(BOOL)f +{ + _has.silentAttemptAllowed = f; +} +- (BOOL)hasSilentAttemptAllowed +{ + return _has.silentAttemptAllowed != 0; +} +@synthesize recordStatus = _recordStatus; +- (OTEscrowRecord_RecordStatus)recordStatus +{ + return _has.recordStatus ? _recordStatus : OTEscrowRecord_RecordStatus_RECORD_STATUS_VALID; +} +- (void)setRecordStatus:(OTEscrowRecord_RecordStatus)v +{ + _has.recordStatus = YES; + _recordStatus = v; +} +- (void)setHasRecordStatus:(BOOL)f +{ + _has.recordStatus = f; +} +- (BOOL)hasRecordStatus +{ + return _has.recordStatus != 0; +} +- (NSString *)recordStatusAsString:(OTEscrowRecord_RecordStatus)value +{ + return OTEscrowRecord_RecordStatusAsString(value); +} +- (OTEscrowRecord_RecordStatus)StringAsRecordStatus:(NSString *)str +{ + return StringAsOTEscrowRecord_RecordStatus(str); +} +- (BOOL)hasRecordId +{ + return _recordId != nil; +} +@synthesize recordId = _recordId; +@synthesize recoveryStatus = _recoveryStatus; +- (OTEscrowRecord_RecoveryStatus)recoveryStatus +{ + return _has.recoveryStatus ? _recoveryStatus : OTEscrowRecord_RecoveryStatus_RECOVERY_STATUS_VALID; +} +- (void)setRecoveryStatus:(OTEscrowRecord_RecoveryStatus)v +{ + _has.recoveryStatus = YES; + _recoveryStatus = v; +} +- (void)setHasRecoveryStatus:(BOOL)f +{ + _has.recoveryStatus = f; +} +- (BOOL)hasRecoveryStatus +{ + return _has.recoveryStatus != 0; +} +- (NSString *)recoveryStatusAsString:(OTEscrowRecord_RecoveryStatus)value +{ + return OTEscrowRecord_RecoveryStatusAsString(value); +} +- (OTEscrowRecord_RecoveryStatus)StringAsRecoveryStatus:(NSString *)str +{ + return StringAsOTEscrowRecord_RecoveryStatus(str); +} +@synthesize coolOffEnd = _coolOffEnd; +- (void)setCoolOffEnd:(uint64_t)v +{ + _has.coolOffEnd = YES; + _coolOffEnd = v; +} +- (void)setHasCoolOffEnd:(BOOL)f +{ + _has.coolOffEnd = f; +} +- (BOOL)hasCoolOffEnd +{ + return _has.coolOffEnd != 0; +} +- (BOOL)hasSerialNumber +{ + return _serialNumber != nil; +} +@synthesize serialNumber = _serialNumber; +@synthesize recordViability = _recordViability; +- (OTEscrowRecord_RecordViability)recordViability +{ + return _has.recordViability ? _recordViability : OTEscrowRecord_RecordViability_RECORD_VIABILITY_FULLY_VIABLE; +} +- (void)setRecordViability:(OTEscrowRecord_RecordViability)v +{ + _has.recordViability = YES; + _recordViability = v; +} +- (void)setHasRecordViability:(BOOL)f +{ + _has.recordViability = f; +} +- (BOOL)hasRecordViability +{ + return _has.recordViability != 0; +} +- (NSString *)recordViabilityAsString:(OTEscrowRecord_RecordViability)value +{ + return OTEscrowRecord_RecordViabilityAsString(value); +} +- (OTEscrowRecord_RecordViability)StringAsRecordViability:(NSString *)str +{ + return StringAsOTEscrowRecord_RecordViability(str); +} +@synthesize viabilityStatus = _viabilityStatus; +- (OTEscrowRecord_SOSViability)viabilityStatus +{ + return _has.viabilityStatus ? _viabilityStatus : OTEscrowRecord_SOSViability_SOS_VIABLE_UNKNOWN; +} +- (void)setViabilityStatus:(OTEscrowRecord_SOSViability)v +{ + _has.viabilityStatus = YES; + _viabilityStatus = v; +} +- (void)setHasViabilityStatus:(BOOL)f +{ + _has.viabilityStatus = f; +} +- (BOOL)hasViabilityStatus +{ + return _has.viabilityStatus != 0; +} +- (NSString *)viabilityStatusAsString:(OTEscrowRecord_SOSViability)value +{ + return OTEscrowRecord_SOSViabilityAsString(value); +} +- (OTEscrowRecord_SOSViability)StringAsViabilityStatus:(NSString *)str +{ + return StringAsOTEscrowRecord_SOSViability(str); +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.creationDate) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_creationDate] forKey:@"creation_date"]; + } + if (self->_has.remainingAttempts) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_remainingAttempts] forKey:@"remaining_attempts"]; + } + if (self->_escrowInformationMetadata) + { + [dict setObject:[_escrowInformationMetadata dictionaryRepresentation] forKey:@"escrow_information_metadata"]; + } + if (self->_label) + { + [dict setObject:self->_label forKey:@"label"]; + } + if (self->_has.silentAttemptAllowed) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_silentAttemptAllowed] forKey:@"silent_attempt_allowed"]; + } + if (self->_has.recordStatus) + { + [dict setObject:OTEscrowRecord_RecordStatusAsString(self->_recordStatus) forKey:@"record_status"]; + } + if (self->_recordId) + { + [dict setObject:self->_recordId forKey:@"record_id"]; + } + if (self->_has.recoveryStatus) + { + [dict setObject:OTEscrowRecord_RecoveryStatusAsString(self->_recoveryStatus) forKey:@"recovery_status"]; + } + if (self->_has.coolOffEnd) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_coolOffEnd] forKey:@"cool_off_end"]; + } + if (self->_serialNumber) + { + [dict setObject:self->_serialNumber forKey:@"serial_number"]; + } + if (self->_has.recordViability) + { + [dict setObject:OTEscrowRecord_RecordViabilityAsString(self->_recordViability) forKey:@"record_viability"]; + } + if (self->_has.viabilityStatus) + { + [dict setObject:OTEscrowRecord_SOSViabilityAsString(self->_viabilityStatus) forKey:@"viability_status"]; + } + return dict; +} + +BOOL OTEscrowRecordReadFrom(__unsafe_unretained OTEscrowRecord *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* creationDate */: + { + self->_has.creationDate = YES; + self->_creationDate = PBReaderReadUint64(reader); + } + break; + case 2 /* remainingAttempts */: + { + self->_has.remainingAttempts = YES; + self->_remainingAttempts = PBReaderReadUint64(reader); + } + break; + case 3 /* escrowInformationMetadata */: + { + OTEscrowRecordMetadata *new_escrowInformationMetadata = [[OTEscrowRecordMetadata alloc] init]; + self->_escrowInformationMetadata = new_escrowInformationMetadata; + PBDataReaderMark mark_escrowInformationMetadata; + BOOL markError = !PBReaderPlaceMark(reader, &mark_escrowInformationMetadata); + if (markError) + { + return NO; + } + BOOL inError = !OTEscrowRecordMetadataReadFrom(new_escrowInformationMetadata, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_escrowInformationMetadata); + } + break; + case 4 /* label */: + { + NSString *new_label = PBReaderReadString(reader); + self->_label = new_label; + } + break; + case 9 /* silentAttemptAllowed */: + { + self->_has.silentAttemptAllowed = YES; + self->_silentAttemptAllowed = PBReaderReadUint64(reader); + } + break; + case 10 /* recordStatus */: + { + self->_has.recordStatus = YES; + self->_recordStatus = PBReaderReadInt32(reader); + } + break; + case 11 /* recordId */: + { + NSString *new_recordId = PBReaderReadString(reader); + self->_recordId = new_recordId; + } + break; + case 12 /* recoveryStatus */: + { + self->_has.recoveryStatus = YES; + self->_recoveryStatus = PBReaderReadInt32(reader); + } + break; + case 13 /* coolOffEnd */: + { + self->_has.coolOffEnd = YES; + self->_coolOffEnd = PBReaderReadUint64(reader); + } + break; + case 14 /* serialNumber */: + { + NSString *new_serialNumber = PBReaderReadString(reader); + self->_serialNumber = new_serialNumber; + } + break; + case 15 /* recordViability */: + { + self->_has.recordViability = YES; + self->_recordViability = PBReaderReadInt32(reader); + } + break; + case 16 /* viabilityStatus */: + { + self->_has.viabilityStatus = YES; + self->_viabilityStatus = PBReaderReadInt32(reader); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTEscrowRecordReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* creationDate */ + { + if (self->_has.creationDate) + { + PBDataWriterWriteUint64Field(writer, self->_creationDate, 1); + } + } + /* remainingAttempts */ + { + if (self->_has.remainingAttempts) + { + PBDataWriterWriteUint64Field(writer, self->_remainingAttempts, 2); + } + } + /* escrowInformationMetadata */ + { + if (self->_escrowInformationMetadata != nil) + { + PBDataWriterWriteSubmessage(writer, self->_escrowInformationMetadata, 3); + } + } + /* label */ + { + if (self->_label) + { + PBDataWriterWriteStringField(writer, self->_label, 4); + } + } + /* silentAttemptAllowed */ + { + if (self->_has.silentAttemptAllowed) + { + PBDataWriterWriteUint64Field(writer, self->_silentAttemptAllowed, 9); + } + } + /* recordStatus */ + { + if (self->_has.recordStatus) + { + PBDataWriterWriteInt32Field(writer, self->_recordStatus, 10); + } + } + /* recordId */ + { + if (self->_recordId) + { + PBDataWriterWriteStringField(writer, self->_recordId, 11); + } + } + /* recoveryStatus */ + { + if (self->_has.recoveryStatus) + { + PBDataWriterWriteInt32Field(writer, self->_recoveryStatus, 12); + } + } + /* coolOffEnd */ + { + if (self->_has.coolOffEnd) + { + PBDataWriterWriteUint64Field(writer, self->_coolOffEnd, 13); + } + } + /* serialNumber */ + { + if (self->_serialNumber) + { + PBDataWriterWriteStringField(writer, self->_serialNumber, 14); + } + } + /* recordViability */ + { + if (self->_has.recordViability) + { + PBDataWriterWriteInt32Field(writer, self->_recordViability, 15); + } + } + /* viabilityStatus */ + { + if (self->_has.viabilityStatus) + { + PBDataWriterWriteInt32Field(writer, self->_viabilityStatus, 16); + } + } +} + +- (void)copyTo:(OTEscrowRecord *)other +{ + if (self->_has.creationDate) + { + other->_creationDate = _creationDate; + other->_has.creationDate = YES; + } + if (self->_has.remainingAttempts) + { + other->_remainingAttempts = _remainingAttempts; + other->_has.remainingAttempts = YES; + } + if (_escrowInformationMetadata) + { + other.escrowInformationMetadata = _escrowInformationMetadata; + } + if (_label) + { + other.label = _label; + } + if (self->_has.silentAttemptAllowed) + { + other->_silentAttemptAllowed = _silentAttemptAllowed; + other->_has.silentAttemptAllowed = YES; + } + if (self->_has.recordStatus) + { + other->_recordStatus = _recordStatus; + other->_has.recordStatus = YES; + } + if (_recordId) + { + other.recordId = _recordId; + } + if (self->_has.recoveryStatus) + { + other->_recoveryStatus = _recoveryStatus; + other->_has.recoveryStatus = YES; + } + if (self->_has.coolOffEnd) + { + other->_coolOffEnd = _coolOffEnd; + other->_has.coolOffEnd = YES; + } + if (_serialNumber) + { + other.serialNumber = _serialNumber; + } + if (self->_has.recordViability) + { + other->_recordViability = _recordViability; + other->_has.recordViability = YES; + } + if (self->_has.viabilityStatus) + { + other->_viabilityStatus = _viabilityStatus; + other->_has.viabilityStatus = YES; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTEscrowRecord *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.creationDate) + { + copy->_creationDate = _creationDate; + copy->_has.creationDate = YES; + } + if (self->_has.remainingAttempts) + { + copy->_remainingAttempts = _remainingAttempts; + copy->_has.remainingAttempts = YES; + } + copy->_escrowInformationMetadata = [_escrowInformationMetadata copyWithZone:zone]; + copy->_label = [_label copyWithZone:zone]; + if (self->_has.silentAttemptAllowed) + { + copy->_silentAttemptAllowed = _silentAttemptAllowed; + copy->_has.silentAttemptAllowed = YES; + } + if (self->_has.recordStatus) + { + copy->_recordStatus = _recordStatus; + copy->_has.recordStatus = YES; + } + copy->_recordId = [_recordId copyWithZone:zone]; + if (self->_has.recoveryStatus) + { + copy->_recoveryStatus = _recoveryStatus; + copy->_has.recoveryStatus = YES; + } + if (self->_has.coolOffEnd) + { + copy->_coolOffEnd = _coolOffEnd; + copy->_has.coolOffEnd = YES; + } + copy->_serialNumber = [_serialNumber copyWithZone:zone]; + if (self->_has.recordViability) + { + copy->_recordViability = _recordViability; + copy->_has.recordViability = YES; + } + if (self->_has.viabilityStatus) + { + copy->_viabilityStatus = _viabilityStatus; + copy->_has.viabilityStatus = YES; + } + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTEscrowRecord *other = (OTEscrowRecord *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.creationDate && other->_has.creationDate && self->_creationDate == other->_creationDate) || (!self->_has.creationDate && !other->_has.creationDate)) + && + ((self->_has.remainingAttempts && other->_has.remainingAttempts && self->_remainingAttempts == other->_remainingAttempts) || (!self->_has.remainingAttempts && !other->_has.remainingAttempts)) + && + ((!self->_escrowInformationMetadata && !other->_escrowInformationMetadata) || [self->_escrowInformationMetadata isEqual:other->_escrowInformationMetadata]) + && + ((!self->_label && !other->_label) || [self->_label isEqual:other->_label]) + && + ((self->_has.silentAttemptAllowed && other->_has.silentAttemptAllowed && self->_silentAttemptAllowed == other->_silentAttemptAllowed) || (!self->_has.silentAttemptAllowed && !other->_has.silentAttemptAllowed)) + && + ((self->_has.recordStatus && other->_has.recordStatus && self->_recordStatus == other->_recordStatus) || (!self->_has.recordStatus && !other->_has.recordStatus)) + && + ((!self->_recordId && !other->_recordId) || [self->_recordId isEqual:other->_recordId]) + && + ((self->_has.recoveryStatus && other->_has.recoveryStatus && self->_recoveryStatus == other->_recoveryStatus) || (!self->_has.recoveryStatus && !other->_has.recoveryStatus)) + && + ((self->_has.coolOffEnd && other->_has.coolOffEnd && self->_coolOffEnd == other->_coolOffEnd) || (!self->_has.coolOffEnd && !other->_has.coolOffEnd)) + && + ((!self->_serialNumber && !other->_serialNumber) || [self->_serialNumber isEqual:other->_serialNumber]) + && + ((self->_has.recordViability && other->_has.recordViability && self->_recordViability == other->_recordViability) || (!self->_has.recordViability && !other->_has.recordViability)) + && + ((self->_has.viabilityStatus && other->_has.viabilityStatus && self->_viabilityStatus == other->_viabilityStatus) || (!self->_has.viabilityStatus && !other->_has.viabilityStatus)) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.creationDate ? PBHashInt((NSUInteger)self->_creationDate) : 0) + ^ + (self->_has.remainingAttempts ? PBHashInt((NSUInteger)self->_remainingAttempts) : 0) + ^ + [self->_escrowInformationMetadata hash] + ^ + [self->_label hash] + ^ + (self->_has.silentAttemptAllowed ? PBHashInt((NSUInteger)self->_silentAttemptAllowed) : 0) + ^ + (self->_has.recordStatus ? PBHashInt((NSUInteger)self->_recordStatus) : 0) + ^ + [self->_recordId hash] + ^ + (self->_has.recoveryStatus ? PBHashInt((NSUInteger)self->_recoveryStatus) : 0) + ^ + (self->_has.coolOffEnd ? PBHashInt((NSUInteger)self->_coolOffEnd) : 0) + ^ + [self->_serialNumber hash] + ^ + (self->_has.recordViability ? PBHashInt((NSUInteger)self->_recordViability) : 0) + ^ + (self->_has.viabilityStatus ? PBHashInt((NSUInteger)self->_viabilityStatus) : 0) + ; +} + +- (void)mergeFrom:(OTEscrowRecord *)other +{ + if (other->_has.creationDate) + { + self->_creationDate = other->_creationDate; + self->_has.creationDate = YES; + } + if (other->_has.remainingAttempts) + { + self->_remainingAttempts = other->_remainingAttempts; + self->_has.remainingAttempts = YES; + } + if (self->_escrowInformationMetadata && other->_escrowInformationMetadata) + { + [self->_escrowInformationMetadata mergeFrom:other->_escrowInformationMetadata]; + } + else if (!self->_escrowInformationMetadata && other->_escrowInformationMetadata) + { + [self setEscrowInformationMetadata:other->_escrowInformationMetadata]; + } + if (other->_label) + { + [self setLabel:other->_label]; + } + if (other->_has.silentAttemptAllowed) + { + self->_silentAttemptAllowed = other->_silentAttemptAllowed; + self->_has.silentAttemptAllowed = YES; + } + if (other->_has.recordStatus) + { + self->_recordStatus = other->_recordStatus; + self->_has.recordStatus = YES; + } + if (other->_recordId) + { + [self setRecordId:other->_recordId]; + } + if (other->_has.recoveryStatus) + { + self->_recoveryStatus = other->_recoveryStatus; + self->_has.recoveryStatus = YES; + } + if (other->_has.coolOffEnd) + { + self->_coolOffEnd = other->_coolOffEnd; + self->_has.coolOffEnd = YES; + } + if (other->_serialNumber) + { + [self setSerialNumber:other->_serialNumber]; + } + if (other->_has.recordViability) + { + self->_recordViability = other->_recordViability; + self->_has.recordViability = YES; + } + if (other->_has.viabilityStatus) + { + self->_viabilityStatus = other->_viabilityStatus; + self->_has.viabilityStatus = YES; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h b/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h new file mode 100644 index 00000000..1d75c3ad --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h @@ -0,0 +1,73 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import +#import + +@class OTEscrowRecordMetadataClientMetadata; + +#ifdef __cplusplus +#define OTESCROWRECORDMETADATA_FUNCTION extern "C" +#else +#define OTESCROWRECORDMETADATA_FUNCTION extern +#endif + +@interface OTEscrowRecordMetadata : PBCodable +{ + uint64_t _secureBackupTimestamp; + uint64_t _secureBackupUsesMultipleIcscs; + NSData *_backupKeybagDigest; + NSString *_bottleId; + NSString *_bottleValidity; + OTEscrowRecordMetadataClientMetadata *_clientMetadata; + NSData *_escrowedSpki; + NSData *_peerInfo; + NSString *_serial; + struct { + int secureBackupTimestamp:1; + int secureBackupUsesMultipleIcscs:1; + } _has; +} + + +@property (nonatomic, readonly) BOOL hasBackupKeybagDigest; +@property (nonatomic, retain) NSData *backupKeybagDigest; + +@property (nonatomic, readonly) BOOL hasClientMetadata; +@property (nonatomic, retain) OTEscrowRecordMetadataClientMetadata *clientMetadata; + +@property (nonatomic) BOOL hasSecureBackupUsesMultipleIcscs; +@property (nonatomic) uint64_t secureBackupUsesMultipleIcscs; + +@property (nonatomic, readonly) BOOL hasBottleId; +@property (nonatomic, retain) NSString *bottleId; + +@property (nonatomic) BOOL hasSecureBackupTimestamp; +@property (nonatomic) uint64_t secureBackupTimestamp; + +@property (nonatomic, readonly) BOOL hasEscrowedSpki; +@property (nonatomic, retain) NSData *escrowedSpki; + +@property (nonatomic, readonly) BOOL hasPeerInfo; +@property (nonatomic, retain) NSData *peerInfo; + +@property (nonatomic, readonly) BOOL hasBottleValidity; +@property (nonatomic, retain) NSString *bottleValidity; + +@property (nonatomic, readonly) BOOL hasSerial; +@property (nonatomic, retain) NSString *serial; + +// Performs a shallow copy into other +- (void)copyTo:(OTEscrowRecordMetadata *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTEscrowRecordMetadata *)other; + +OTESCROWRECORDMETADATA_FUNCTION BOOL OTEscrowRecordMetadataReadFrom(__unsafe_unretained OTEscrowRecordMetadata *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.m b/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.m new file mode 100644 index 00000000..ca48c520 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecordMetadata.m @@ -0,0 +1,452 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import "OTEscrowRecordMetadata.h" +#import +#import +#import + +#import "OTEscrowRecordMetadataClientMetadata.h" + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTEscrowRecordMetadata + +- (BOOL)hasBackupKeybagDigest +{ + return _backupKeybagDigest != nil; +} +@synthesize backupKeybagDigest = _backupKeybagDigest; +- (BOOL)hasClientMetadata +{ + return _clientMetadata != nil; +} +@synthesize clientMetadata = _clientMetadata; +@synthesize secureBackupUsesMultipleIcscs = _secureBackupUsesMultipleIcscs; +- (void)setSecureBackupUsesMultipleIcscs:(uint64_t)v +{ + _has.secureBackupUsesMultipleIcscs = YES; + _secureBackupUsesMultipleIcscs = v; +} +- (void)setHasSecureBackupUsesMultipleIcscs:(BOOL)f +{ + _has.secureBackupUsesMultipleIcscs = f; +} +- (BOOL)hasSecureBackupUsesMultipleIcscs +{ + return _has.secureBackupUsesMultipleIcscs != 0; +} +- (BOOL)hasBottleId +{ + return _bottleId != nil; +} +@synthesize bottleId = _bottleId; +@synthesize secureBackupTimestamp = _secureBackupTimestamp; +- (void)setSecureBackupTimestamp:(uint64_t)v +{ + _has.secureBackupTimestamp = YES; + _secureBackupTimestamp = v; +} +- (void)setHasSecureBackupTimestamp:(BOOL)f +{ + _has.secureBackupTimestamp = f; +} +- (BOOL)hasSecureBackupTimestamp +{ + return _has.secureBackupTimestamp != 0; +} +- (BOOL)hasEscrowedSpki +{ + return _escrowedSpki != nil; +} +@synthesize escrowedSpki = _escrowedSpki; +- (BOOL)hasPeerInfo +{ + return _peerInfo != nil; +} +@synthesize peerInfo = _peerInfo; +- (BOOL)hasBottleValidity +{ + return _bottleValidity != nil; +} +@synthesize bottleValidity = _bottleValidity; +- (BOOL)hasSerial +{ + return _serial != nil; +} +@synthesize serial = _serial; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_backupKeybagDigest) + { + [dict setObject:self->_backupKeybagDigest forKey:@"backup_keybag_digest"]; + } + if (self->_clientMetadata) + { + [dict setObject:[_clientMetadata dictionaryRepresentation] forKey:@"client_metadata"]; + } + if (self->_has.secureBackupUsesMultipleIcscs) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupUsesMultipleIcscs] forKey:@"secure_backup_uses_multiple_icscs"]; + } + if (self->_bottleId) + { + [dict setObject:self->_bottleId forKey:@"bottle_id"]; + } + if (self->_has.secureBackupTimestamp) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupTimestamp] forKey:@"secure_backup_timestamp"]; + } + if (self->_escrowedSpki) + { + [dict setObject:self->_escrowedSpki forKey:@"escrowed_spki"]; + } + if (self->_peerInfo) + { + [dict setObject:self->_peerInfo forKey:@"peer_info"]; + } + if (self->_bottleValidity) + { + [dict setObject:self->_bottleValidity forKey:@"bottle_validity"]; + } + if (self->_serial) + { + [dict setObject:self->_serial forKey:@"serial"]; + } + return dict; +} + +BOOL OTEscrowRecordMetadataReadFrom(__unsafe_unretained OTEscrowRecordMetadata *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* backupKeybagDigest */: + { + NSData *new_backupKeybagDigest = PBReaderReadData(reader); + self->_backupKeybagDigest = new_backupKeybagDigest; + } + break; + case 2 /* clientMetadata */: + { + OTEscrowRecordMetadataClientMetadata *new_clientMetadata = [[OTEscrowRecordMetadataClientMetadata alloc] init]; + self->_clientMetadata = new_clientMetadata; + PBDataReaderMark mark_clientMetadata; + BOOL markError = !PBReaderPlaceMark(reader, &mark_clientMetadata); + if (markError) + { + return NO; + } + BOOL inError = !OTEscrowRecordMetadataClientMetadataReadFrom(new_clientMetadata, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_clientMetadata); + } + break; + case 3 /* secureBackupUsesMultipleIcscs */: + { + self->_has.secureBackupUsesMultipleIcscs = YES; + self->_secureBackupUsesMultipleIcscs = PBReaderReadUint64(reader); + } + break; + case 4 /* bottleId */: + { + NSString *new_bottleId = PBReaderReadString(reader); + self->_bottleId = new_bottleId; + } + break; + case 5 /* secureBackupTimestamp */: + { + self->_has.secureBackupTimestamp = YES; + self->_secureBackupTimestamp = PBReaderReadUint64(reader); + } + break; + case 6 /* escrowedSpki */: + { + NSData *new_escrowedSpki = PBReaderReadData(reader); + self->_escrowedSpki = new_escrowedSpki; + } + break; + case 7 /* peerInfo */: + { + NSData *new_peerInfo = PBReaderReadData(reader); + self->_peerInfo = new_peerInfo; + } + break; + case 8 /* bottleValidity */: + { + NSString *new_bottleValidity = PBReaderReadString(reader); + self->_bottleValidity = new_bottleValidity; + } + break; + case 9 /* serial */: + { + NSString *new_serial = PBReaderReadString(reader); + self->_serial = new_serial; + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTEscrowRecordMetadataReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* backupKeybagDigest */ + { + if (self->_backupKeybagDigest) + { + PBDataWriterWriteDataField(writer, self->_backupKeybagDigest, 1); + } + } + /* clientMetadata */ + { + if (self->_clientMetadata != nil) + { + PBDataWriterWriteSubmessage(writer, self->_clientMetadata, 2); + } + } + /* secureBackupUsesMultipleIcscs */ + { + if (self->_has.secureBackupUsesMultipleIcscs) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupUsesMultipleIcscs, 3); + } + } + /* bottleId */ + { + if (self->_bottleId) + { + PBDataWriterWriteStringField(writer, self->_bottleId, 4); + } + } + /* secureBackupTimestamp */ + { + if (self->_has.secureBackupTimestamp) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupTimestamp, 5); + } + } + /* escrowedSpki */ + { + if (self->_escrowedSpki) + { + PBDataWriterWriteDataField(writer, self->_escrowedSpki, 6); + } + } + /* peerInfo */ + { + if (self->_peerInfo) + { + PBDataWriterWriteDataField(writer, self->_peerInfo, 7); + } + } + /* bottleValidity */ + { + if (self->_bottleValidity) + { + PBDataWriterWriteStringField(writer, self->_bottleValidity, 8); + } + } + /* serial */ + { + if (self->_serial) + { + PBDataWriterWriteStringField(writer, self->_serial, 9); + } + } +} + +- (void)copyTo:(OTEscrowRecordMetadata *)other +{ + if (_backupKeybagDigest) + { + other.backupKeybagDigest = _backupKeybagDigest; + } + if (_clientMetadata) + { + other.clientMetadata = _clientMetadata; + } + if (self->_has.secureBackupUsesMultipleIcscs) + { + other->_secureBackupUsesMultipleIcscs = _secureBackupUsesMultipleIcscs; + other->_has.secureBackupUsesMultipleIcscs = YES; + } + if (_bottleId) + { + other.bottleId = _bottleId; + } + if (self->_has.secureBackupTimestamp) + { + other->_secureBackupTimestamp = _secureBackupTimestamp; + other->_has.secureBackupTimestamp = YES; + } + if (_escrowedSpki) + { + other.escrowedSpki = _escrowedSpki; + } + if (_peerInfo) + { + other.peerInfo = _peerInfo; + } + if (_bottleValidity) + { + other.bottleValidity = _bottleValidity; + } + if (_serial) + { + other.serial = _serial; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTEscrowRecordMetadata *copy = [[[self class] allocWithZone:zone] init]; + copy->_backupKeybagDigest = [_backupKeybagDigest copyWithZone:zone]; + copy->_clientMetadata = [_clientMetadata copyWithZone:zone]; + if (self->_has.secureBackupUsesMultipleIcscs) + { + copy->_secureBackupUsesMultipleIcscs = _secureBackupUsesMultipleIcscs; + copy->_has.secureBackupUsesMultipleIcscs = YES; + } + copy->_bottleId = [_bottleId copyWithZone:zone]; + if (self->_has.secureBackupTimestamp) + { + copy->_secureBackupTimestamp = _secureBackupTimestamp; + copy->_has.secureBackupTimestamp = YES; + } + copy->_escrowedSpki = [_escrowedSpki copyWithZone:zone]; + copy->_peerInfo = [_peerInfo copyWithZone:zone]; + copy->_bottleValidity = [_bottleValidity copyWithZone:zone]; + copy->_serial = [_serial copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTEscrowRecordMetadata *other = (OTEscrowRecordMetadata *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_backupKeybagDigest && !other->_backupKeybagDigest) || [self->_backupKeybagDigest isEqual:other->_backupKeybagDigest]) + && + ((!self->_clientMetadata && !other->_clientMetadata) || [self->_clientMetadata isEqual:other->_clientMetadata]) + && + ((self->_has.secureBackupUsesMultipleIcscs && other->_has.secureBackupUsesMultipleIcscs && self->_secureBackupUsesMultipleIcscs == other->_secureBackupUsesMultipleIcscs) || (!self->_has.secureBackupUsesMultipleIcscs && !other->_has.secureBackupUsesMultipleIcscs)) + && + ((!self->_bottleId && !other->_bottleId) || [self->_bottleId isEqual:other->_bottleId]) + && + ((self->_has.secureBackupTimestamp && other->_has.secureBackupTimestamp && self->_secureBackupTimestamp == other->_secureBackupTimestamp) || (!self->_has.secureBackupTimestamp && !other->_has.secureBackupTimestamp)) + && + ((!self->_escrowedSpki && !other->_escrowedSpki) || [self->_escrowedSpki isEqual:other->_escrowedSpki]) + && + ((!self->_peerInfo && !other->_peerInfo) || [self->_peerInfo isEqual:other->_peerInfo]) + && + ((!self->_bottleValidity && !other->_bottleValidity) || [self->_bottleValidity isEqual:other->_bottleValidity]) + && + ((!self->_serial && !other->_serial) || [self->_serial isEqual:other->_serial]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_backupKeybagDigest hash] + ^ + [self->_clientMetadata hash] + ^ + (self->_has.secureBackupUsesMultipleIcscs ? PBHashInt((NSUInteger)self->_secureBackupUsesMultipleIcscs) : 0) + ^ + [self->_bottleId hash] + ^ + (self->_has.secureBackupTimestamp ? PBHashInt((NSUInteger)self->_secureBackupTimestamp) : 0) + ^ + [self->_escrowedSpki hash] + ^ + [self->_peerInfo hash] + ^ + [self->_bottleValidity hash] + ^ + [self->_serial hash] + ; +} + +- (void)mergeFrom:(OTEscrowRecordMetadata *)other +{ + if (other->_backupKeybagDigest) + { + [self setBackupKeybagDigest:other->_backupKeybagDigest]; + } + if (self->_clientMetadata && other->_clientMetadata) + { + [self->_clientMetadata mergeFrom:other->_clientMetadata]; + } + else if (!self->_clientMetadata && other->_clientMetadata) + { + [self setClientMetadata:other->_clientMetadata]; + } + if (other->_has.secureBackupUsesMultipleIcscs) + { + self->_secureBackupUsesMultipleIcscs = other->_secureBackupUsesMultipleIcscs; + self->_has.secureBackupUsesMultipleIcscs = YES; + } + if (other->_bottleId) + { + [self setBottleId:other->_bottleId]; + } + if (other->_has.secureBackupTimestamp) + { + self->_secureBackupTimestamp = other->_secureBackupTimestamp; + self->_has.secureBackupTimestamp = YES; + } + if (other->_escrowedSpki) + { + [self setEscrowedSpki:other->_escrowedSpki]; + } + if (other->_peerInfo) + { + [self setPeerInfo:other->_peerInfo]; + } + if (other->_bottleValidity) + { + [self setBottleValidity:other->_bottleValidity]; + } + if (other->_serial) + { + [self setSerial:other->_serial]; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h b/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h new file mode 100644 index 00000000..6b913b4b --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h @@ -0,0 +1,86 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import +#import + +#ifdef __cplusplus +#define OTESCROWRECORDMETADATACLIENTMETADATA_FUNCTION extern "C" +#else +#define OTESCROWRECORDMETADATACLIENTMETADATA_FUNCTION extern +#endif + +@interface OTEscrowRecordMetadataClientMetadata : PBCodable +{ + uint64_t _devicePlatform; + uint64_t _secureBackupMetadataTimestamp; + uint64_t _secureBackupNumericPassphraseLength; + uint64_t _secureBackupUsesComplexPassphrase; + uint64_t _secureBackupUsesNumericPassphrase; + NSString *_deviceColor; + NSString *_deviceEnclosureColor; + NSString *_deviceMid; + NSString *_deviceModel; + NSString *_deviceModelClass; + NSString *_deviceModelVersion; + NSString *_deviceName; + struct { + int devicePlatform:1; + int secureBackupMetadataTimestamp:1; + int secureBackupNumericPassphraseLength:1; + int secureBackupUsesComplexPassphrase:1; + int secureBackupUsesNumericPassphrase:1; + } _has; +} + + +@property (nonatomic) BOOL hasSecureBackupMetadataTimestamp; +@property (nonatomic) uint64_t secureBackupMetadataTimestamp; + +@property (nonatomic) BOOL hasSecureBackupNumericPassphraseLength; +@property (nonatomic) uint64_t secureBackupNumericPassphraseLength; + +@property (nonatomic) BOOL hasSecureBackupUsesComplexPassphrase; +@property (nonatomic) uint64_t secureBackupUsesComplexPassphrase; + +@property (nonatomic) BOOL hasSecureBackupUsesNumericPassphrase; +@property (nonatomic) uint64_t secureBackupUsesNumericPassphrase; + +@property (nonatomic, readonly) BOOL hasDeviceColor; +@property (nonatomic, retain) NSString *deviceColor; + +@property (nonatomic, readonly) BOOL hasDeviceEnclosureColor; +@property (nonatomic, retain) NSString *deviceEnclosureColor; + +@property (nonatomic, readonly) BOOL hasDeviceMid; +@property (nonatomic, retain) NSString *deviceMid; + +@property (nonatomic, readonly) BOOL hasDeviceModel; +@property (nonatomic, retain) NSString *deviceModel; + +@property (nonatomic, readonly) BOOL hasDeviceModelClass; +@property (nonatomic, retain) NSString *deviceModelClass; + +@property (nonatomic, readonly) BOOL hasDeviceModelVersion; +@property (nonatomic, retain) NSString *deviceModelVersion; + +@property (nonatomic, readonly) BOOL hasDeviceName; +@property (nonatomic, retain) NSString *deviceName; + +@property (nonatomic) BOOL hasDevicePlatform; +@property (nonatomic) uint64_t devicePlatform; + +// Performs a shallow copy into other +- (void)copyTo:(OTEscrowRecordMetadataClientMetadata *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTEscrowRecordMetadataClientMetadata *)other; + +OTESCROWRECORDMETADATACLIENTMETADATA_FUNCTION BOOL OTEscrowRecordMetadataClientMetadataReadFrom(__unsafe_unretained OTEscrowRecordMetadataClientMetadata *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.m b/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.m new file mode 100644 index 00000000..6b27339d --- /dev/null +++ b/keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.m @@ -0,0 +1,584 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTEscrowRecord.proto + +#import "OTEscrowRecordMetadataClientMetadata.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTEscrowRecordMetadataClientMetadata + +@synthesize secureBackupMetadataTimestamp = _secureBackupMetadataTimestamp; +- (void)setSecureBackupMetadataTimestamp:(uint64_t)v +{ + _has.secureBackupMetadataTimestamp = YES; + _secureBackupMetadataTimestamp = v; +} +- (void)setHasSecureBackupMetadataTimestamp:(BOOL)f +{ + _has.secureBackupMetadataTimestamp = f; +} +- (BOOL)hasSecureBackupMetadataTimestamp +{ + return _has.secureBackupMetadataTimestamp != 0; +} +@synthesize secureBackupNumericPassphraseLength = _secureBackupNumericPassphraseLength; +- (void)setSecureBackupNumericPassphraseLength:(uint64_t)v +{ + _has.secureBackupNumericPassphraseLength = YES; + _secureBackupNumericPassphraseLength = v; +} +- (void)setHasSecureBackupNumericPassphraseLength:(BOOL)f +{ + _has.secureBackupNumericPassphraseLength = f; +} +- (BOOL)hasSecureBackupNumericPassphraseLength +{ + return _has.secureBackupNumericPassphraseLength != 0; +} +@synthesize secureBackupUsesComplexPassphrase = _secureBackupUsesComplexPassphrase; +- (void)setSecureBackupUsesComplexPassphrase:(uint64_t)v +{ + _has.secureBackupUsesComplexPassphrase = YES; + _secureBackupUsesComplexPassphrase = v; +} +- (void)setHasSecureBackupUsesComplexPassphrase:(BOOL)f +{ + _has.secureBackupUsesComplexPassphrase = f; +} +- (BOOL)hasSecureBackupUsesComplexPassphrase +{ + return _has.secureBackupUsesComplexPassphrase != 0; +} +@synthesize secureBackupUsesNumericPassphrase = _secureBackupUsesNumericPassphrase; +- (void)setSecureBackupUsesNumericPassphrase:(uint64_t)v +{ + _has.secureBackupUsesNumericPassphrase = YES; + _secureBackupUsesNumericPassphrase = v; +} +- (void)setHasSecureBackupUsesNumericPassphrase:(BOOL)f +{ + _has.secureBackupUsesNumericPassphrase = f; +} +- (BOOL)hasSecureBackupUsesNumericPassphrase +{ + return _has.secureBackupUsesNumericPassphrase != 0; +} +- (BOOL)hasDeviceColor +{ + return _deviceColor != nil; +} +@synthesize deviceColor = _deviceColor; +- (BOOL)hasDeviceEnclosureColor +{ + return _deviceEnclosureColor != nil; +} +@synthesize deviceEnclosureColor = _deviceEnclosureColor; +- (BOOL)hasDeviceMid +{ + return _deviceMid != nil; +} +@synthesize deviceMid = _deviceMid; +- (BOOL)hasDeviceModel +{ + return _deviceModel != nil; +} +@synthesize deviceModel = _deviceModel; +- (BOOL)hasDeviceModelClass +{ + return _deviceModelClass != nil; +} +@synthesize deviceModelClass = _deviceModelClass; +- (BOOL)hasDeviceModelVersion +{ + return _deviceModelVersion != nil; +} +@synthesize deviceModelVersion = _deviceModelVersion; +- (BOOL)hasDeviceName +{ + return _deviceName != nil; +} +@synthesize deviceName = _deviceName; +@synthesize devicePlatform = _devicePlatform; +- (void)setDevicePlatform:(uint64_t)v +{ + _has.devicePlatform = YES; + _devicePlatform = v; +} +- (void)setHasDevicePlatform:(BOOL)f +{ + _has.devicePlatform = f; +} +- (BOOL)hasDevicePlatform +{ + return _has.devicePlatform != 0; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.secureBackupMetadataTimestamp) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupMetadataTimestamp] forKey:@"secure_backup_metadata_timestamp"]; + } + if (self->_has.secureBackupNumericPassphraseLength) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupNumericPassphraseLength] forKey:@"secure_backup_numeric_passphrase_length"]; + } + if (self->_has.secureBackupUsesComplexPassphrase) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupUsesComplexPassphrase] forKey:@"secure_backup_uses_complex_passphrase"]; + } + if (self->_has.secureBackupUsesNumericPassphrase) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_secureBackupUsesNumericPassphrase] forKey:@"secure_backup_uses_numeric_passphrase"]; + } + if (self->_deviceColor) + { + [dict setObject:self->_deviceColor forKey:@"device_color"]; + } + if (self->_deviceEnclosureColor) + { + [dict setObject:self->_deviceEnclosureColor forKey:@"device_enclosure_color"]; + } + if (self->_deviceMid) + { + [dict setObject:self->_deviceMid forKey:@"device_mid"]; + } + if (self->_deviceModel) + { + [dict setObject:self->_deviceModel forKey:@"device_model"]; + } + if (self->_deviceModelClass) + { + [dict setObject:self->_deviceModelClass forKey:@"device_model_class"]; + } + if (self->_deviceModelVersion) + { + [dict setObject:self->_deviceModelVersion forKey:@"device_model_version"]; + } + if (self->_deviceName) + { + [dict setObject:self->_deviceName forKey:@"device_name"]; + } + if (self->_has.devicePlatform) + { + [dict setObject:[NSNumber numberWithUnsignedLongLong:self->_devicePlatform] forKey:@"device_platform"]; + } + return dict; +} + +BOOL OTEscrowRecordMetadataClientMetadataReadFrom(__unsafe_unretained OTEscrowRecordMetadataClientMetadata *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* secureBackupMetadataTimestamp */: + { + self->_has.secureBackupMetadataTimestamp = YES; + self->_secureBackupMetadataTimestamp = PBReaderReadUint64(reader); + } + break; + case 2 /* secureBackupNumericPassphraseLength */: + { + self->_has.secureBackupNumericPassphraseLength = YES; + self->_secureBackupNumericPassphraseLength = PBReaderReadUint64(reader); + } + break; + case 3 /* secureBackupUsesComplexPassphrase */: + { + self->_has.secureBackupUsesComplexPassphrase = YES; + self->_secureBackupUsesComplexPassphrase = PBReaderReadUint64(reader); + } + break; + case 4 /* secureBackupUsesNumericPassphrase */: + { + self->_has.secureBackupUsesNumericPassphrase = YES; + self->_secureBackupUsesNumericPassphrase = PBReaderReadUint64(reader); + } + break; + case 5 /* deviceColor */: + { + NSString *new_deviceColor = PBReaderReadString(reader); + self->_deviceColor = new_deviceColor; + } + break; + case 6 /* deviceEnclosureColor */: + { + NSString *new_deviceEnclosureColor = PBReaderReadString(reader); + self->_deviceEnclosureColor = new_deviceEnclosureColor; + } + break; + case 7 /* deviceMid */: + { + NSString *new_deviceMid = PBReaderReadString(reader); + self->_deviceMid = new_deviceMid; + } + break; + case 8 /* deviceModel */: + { + NSString *new_deviceModel = PBReaderReadString(reader); + self->_deviceModel = new_deviceModel; + } + break; + case 9 /* deviceModelClass */: + { + NSString *new_deviceModelClass = PBReaderReadString(reader); + self->_deviceModelClass = new_deviceModelClass; + } + break; + case 10 /* deviceModelVersion */: + { + NSString *new_deviceModelVersion = PBReaderReadString(reader); + self->_deviceModelVersion = new_deviceModelVersion; + } + break; + case 11 /* deviceName */: + { + NSString *new_deviceName = PBReaderReadString(reader); + self->_deviceName = new_deviceName; + } + break; + case 12 /* devicePlatform */: + { + self->_has.devicePlatform = YES; + self->_devicePlatform = PBReaderReadUint64(reader); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTEscrowRecordMetadataClientMetadataReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* secureBackupMetadataTimestamp */ + { + if (self->_has.secureBackupMetadataTimestamp) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupMetadataTimestamp, 1); + } + } + /* secureBackupNumericPassphraseLength */ + { + if (self->_has.secureBackupNumericPassphraseLength) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupNumericPassphraseLength, 2); + } + } + /* secureBackupUsesComplexPassphrase */ + { + if (self->_has.secureBackupUsesComplexPassphrase) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupUsesComplexPassphrase, 3); + } + } + /* secureBackupUsesNumericPassphrase */ + { + if (self->_has.secureBackupUsesNumericPassphrase) + { + PBDataWriterWriteUint64Field(writer, self->_secureBackupUsesNumericPassphrase, 4); + } + } + /* deviceColor */ + { + if (self->_deviceColor) + { + PBDataWriterWriteStringField(writer, self->_deviceColor, 5); + } + } + /* deviceEnclosureColor */ + { + if (self->_deviceEnclosureColor) + { + PBDataWriterWriteStringField(writer, self->_deviceEnclosureColor, 6); + } + } + /* deviceMid */ + { + if (self->_deviceMid) + { + PBDataWriterWriteStringField(writer, self->_deviceMid, 7); + } + } + /* deviceModel */ + { + if (self->_deviceModel) + { + PBDataWriterWriteStringField(writer, self->_deviceModel, 8); + } + } + /* deviceModelClass */ + { + if (self->_deviceModelClass) + { + PBDataWriterWriteStringField(writer, self->_deviceModelClass, 9); + } + } + /* deviceModelVersion */ + { + if (self->_deviceModelVersion) + { + PBDataWriterWriteStringField(writer, self->_deviceModelVersion, 10); + } + } + /* deviceName */ + { + if (self->_deviceName) + { + PBDataWriterWriteStringField(writer, self->_deviceName, 11); + } + } + /* devicePlatform */ + { + if (self->_has.devicePlatform) + { + PBDataWriterWriteUint64Field(writer, self->_devicePlatform, 12); + } + } +} + +- (void)copyTo:(OTEscrowRecordMetadataClientMetadata *)other +{ + if (self->_has.secureBackupMetadataTimestamp) + { + other->_secureBackupMetadataTimestamp = _secureBackupMetadataTimestamp; + other->_has.secureBackupMetadataTimestamp = YES; + } + if (self->_has.secureBackupNumericPassphraseLength) + { + other->_secureBackupNumericPassphraseLength = _secureBackupNumericPassphraseLength; + other->_has.secureBackupNumericPassphraseLength = YES; + } + if (self->_has.secureBackupUsesComplexPassphrase) + { + other->_secureBackupUsesComplexPassphrase = _secureBackupUsesComplexPassphrase; + other->_has.secureBackupUsesComplexPassphrase = YES; + } + if (self->_has.secureBackupUsesNumericPassphrase) + { + other->_secureBackupUsesNumericPassphrase = _secureBackupUsesNumericPassphrase; + other->_has.secureBackupUsesNumericPassphrase = YES; + } + if (_deviceColor) + { + other.deviceColor = _deviceColor; + } + if (_deviceEnclosureColor) + { + other.deviceEnclosureColor = _deviceEnclosureColor; + } + if (_deviceMid) + { + other.deviceMid = _deviceMid; + } + if (_deviceModel) + { + other.deviceModel = _deviceModel; + } + if (_deviceModelClass) + { + other.deviceModelClass = _deviceModelClass; + } + if (_deviceModelVersion) + { + other.deviceModelVersion = _deviceModelVersion; + } + if (_deviceName) + { + other.deviceName = _deviceName; + } + if (self->_has.devicePlatform) + { + other->_devicePlatform = _devicePlatform; + other->_has.devicePlatform = YES; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTEscrowRecordMetadataClientMetadata *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.secureBackupMetadataTimestamp) + { + copy->_secureBackupMetadataTimestamp = _secureBackupMetadataTimestamp; + copy->_has.secureBackupMetadataTimestamp = YES; + } + if (self->_has.secureBackupNumericPassphraseLength) + { + copy->_secureBackupNumericPassphraseLength = _secureBackupNumericPassphraseLength; + copy->_has.secureBackupNumericPassphraseLength = YES; + } + if (self->_has.secureBackupUsesComplexPassphrase) + { + copy->_secureBackupUsesComplexPassphrase = _secureBackupUsesComplexPassphrase; + copy->_has.secureBackupUsesComplexPassphrase = YES; + } + if (self->_has.secureBackupUsesNumericPassphrase) + { + copy->_secureBackupUsesNumericPassphrase = _secureBackupUsesNumericPassphrase; + copy->_has.secureBackupUsesNumericPassphrase = YES; + } + copy->_deviceColor = [_deviceColor copyWithZone:zone]; + copy->_deviceEnclosureColor = [_deviceEnclosureColor copyWithZone:zone]; + copy->_deviceMid = [_deviceMid copyWithZone:zone]; + copy->_deviceModel = [_deviceModel copyWithZone:zone]; + copy->_deviceModelClass = [_deviceModelClass copyWithZone:zone]; + copy->_deviceModelVersion = [_deviceModelVersion copyWithZone:zone]; + copy->_deviceName = [_deviceName copyWithZone:zone]; + if (self->_has.devicePlatform) + { + copy->_devicePlatform = _devicePlatform; + copy->_has.devicePlatform = YES; + } + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTEscrowRecordMetadataClientMetadata *other = (OTEscrowRecordMetadataClientMetadata *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.secureBackupMetadataTimestamp && other->_has.secureBackupMetadataTimestamp && self->_secureBackupMetadataTimestamp == other->_secureBackupMetadataTimestamp) || (!self->_has.secureBackupMetadataTimestamp && !other->_has.secureBackupMetadataTimestamp)) + && + ((self->_has.secureBackupNumericPassphraseLength && other->_has.secureBackupNumericPassphraseLength && self->_secureBackupNumericPassphraseLength == other->_secureBackupNumericPassphraseLength) || (!self->_has.secureBackupNumericPassphraseLength && !other->_has.secureBackupNumericPassphraseLength)) + && + ((self->_has.secureBackupUsesComplexPassphrase && other->_has.secureBackupUsesComplexPassphrase && self->_secureBackupUsesComplexPassphrase == other->_secureBackupUsesComplexPassphrase) || (!self->_has.secureBackupUsesComplexPassphrase && !other->_has.secureBackupUsesComplexPassphrase)) + && + ((self->_has.secureBackupUsesNumericPassphrase && other->_has.secureBackupUsesNumericPassphrase && self->_secureBackupUsesNumericPassphrase == other->_secureBackupUsesNumericPassphrase) || (!self->_has.secureBackupUsesNumericPassphrase && !other->_has.secureBackupUsesNumericPassphrase)) + && + ((!self->_deviceColor && !other->_deviceColor) || [self->_deviceColor isEqual:other->_deviceColor]) + && + ((!self->_deviceEnclosureColor && !other->_deviceEnclosureColor) || [self->_deviceEnclosureColor isEqual:other->_deviceEnclosureColor]) + && + ((!self->_deviceMid && !other->_deviceMid) || [self->_deviceMid isEqual:other->_deviceMid]) + && + ((!self->_deviceModel && !other->_deviceModel) || [self->_deviceModel isEqual:other->_deviceModel]) + && + ((!self->_deviceModelClass && !other->_deviceModelClass) || [self->_deviceModelClass isEqual:other->_deviceModelClass]) + && + ((!self->_deviceModelVersion && !other->_deviceModelVersion) || [self->_deviceModelVersion isEqual:other->_deviceModelVersion]) + && + ((!self->_deviceName && !other->_deviceName) || [self->_deviceName isEqual:other->_deviceName]) + && + ((self->_has.devicePlatform && other->_has.devicePlatform && self->_devicePlatform == other->_devicePlatform) || (!self->_has.devicePlatform && !other->_has.devicePlatform)) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.secureBackupMetadataTimestamp ? PBHashInt((NSUInteger)self->_secureBackupMetadataTimestamp) : 0) + ^ + (self->_has.secureBackupNumericPassphraseLength ? PBHashInt((NSUInteger)self->_secureBackupNumericPassphraseLength) : 0) + ^ + (self->_has.secureBackupUsesComplexPassphrase ? PBHashInt((NSUInteger)self->_secureBackupUsesComplexPassphrase) : 0) + ^ + (self->_has.secureBackupUsesNumericPassphrase ? PBHashInt((NSUInteger)self->_secureBackupUsesNumericPassphrase) : 0) + ^ + [self->_deviceColor hash] + ^ + [self->_deviceEnclosureColor hash] + ^ + [self->_deviceMid hash] + ^ + [self->_deviceModel hash] + ^ + [self->_deviceModelClass hash] + ^ + [self->_deviceModelVersion hash] + ^ + [self->_deviceName hash] + ^ + (self->_has.devicePlatform ? PBHashInt((NSUInteger)self->_devicePlatform) : 0) + ; +} + +- (void)mergeFrom:(OTEscrowRecordMetadataClientMetadata *)other +{ + if (other->_has.secureBackupMetadataTimestamp) + { + self->_secureBackupMetadataTimestamp = other->_secureBackupMetadataTimestamp; + self->_has.secureBackupMetadataTimestamp = YES; + } + if (other->_has.secureBackupNumericPassphraseLength) + { + self->_secureBackupNumericPassphraseLength = other->_secureBackupNumericPassphraseLength; + self->_has.secureBackupNumericPassphraseLength = YES; + } + if (other->_has.secureBackupUsesComplexPassphrase) + { + self->_secureBackupUsesComplexPassphrase = other->_secureBackupUsesComplexPassphrase; + self->_has.secureBackupUsesComplexPassphrase = YES; + } + if (other->_has.secureBackupUsesNumericPassphrase) + { + self->_secureBackupUsesNumericPassphrase = other->_secureBackupUsesNumericPassphrase; + self->_has.secureBackupUsesNumericPassphrase = YES; + } + if (other->_deviceColor) + { + [self setDeviceColor:other->_deviceColor]; + } + if (other->_deviceEnclosureColor) + { + [self setDeviceEnclosureColor:other->_deviceEnclosureColor]; + } + if (other->_deviceMid) + { + [self setDeviceMid:other->_deviceMid]; + } + if (other->_deviceModel) + { + [self setDeviceModel:other->_deviceModel]; + } + if (other->_deviceModelClass) + { + [self setDeviceModelClass:other->_deviceModelClass]; + } + if (other->_deviceModelVersion) + { + [self setDeviceModelVersion:other->_deviceModelVersion]; + } + if (other->_deviceName) + { + [self setDeviceName:other->_deviceName]; + } + if (other->_has.devicePlatform) + { + self->_devicePlatform = other->_devicePlatform; + self->_has.devicePlatform = YES; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTGlobalEnums.h b/keychain/ot/proto/generated_source/OTGlobalEnums.h new file mode 100644 index 00000000..b491935d --- /dev/null +++ b/keychain/ot/proto/generated_source/OTGlobalEnums.h @@ -0,0 +1,43 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTPairingMessage.proto + +#include +#ifdef __OBJC__ +#include +#endif + +#ifndef NS_ENUM +#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum)) +#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type +#else +#define NS_ENUM(_type, _name) _type _name; enum +#endif +#endif // !defined(NS_ENUM) + +typedef NS_ENUM(int32_t, OTSupportType) { + OTSupportType_unknown = 0, + OTSupportType_supported = 1, + OTSupportType_not_supported = 2, +}; +#ifdef __OBJC__ +NS_INLINE NSString *OTSupportTypeAsString(OTSupportType value) +{ + switch (value) + { + case OTSupportType_unknown: return @"unknown"; + case OTSupportType_supported: return @"supported"; + case OTSupportType_not_supported: return @"not_supported"; + default: return [NSString stringWithFormat:@"(unknown: %i)", value]; + } +} +#endif /* __OBJC__ */ +#ifdef __OBJC__ +NS_INLINE OTSupportType StringAsOTSupportType(NSString *value) +{ + if ([value isEqualToString:@"unknown"]) return OTSupportType_unknown; + if ([value isEqualToString:@"supported"]) return OTSupportType_supported; + if ([value isEqualToString:@"not_supported"]) return OTSupportType_not_supported; + return OTSupportType_unknown; +} +#endif /* __OBJC__ */ diff --git a/keychain/ot/proto/generated_source/OTICDPRecordContext.h b/keychain/ot/proto/generated_source/OTICDPRecordContext.h new file mode 100644 index 00000000..08fac608 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTICDPRecordContext.h @@ -0,0 +1,42 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import +#import + +@class OTCDPRecoveryInformation; +@class OTEscrowAuthenticationInformation; + +#ifdef __cplusplus +#define OTICDPRECORDCONTEXT_FUNCTION extern "C" +#else +#define OTICDPRECORDCONTEXT_FUNCTION extern +#endif + +@interface OTICDPRecordContext : PBCodable +{ + OTEscrowAuthenticationInformation *_authInfo; + OTCDPRecoveryInformation *_cdpInfo; +} + + +@property (nonatomic, readonly) BOOL hasCdpInfo; +@property (nonatomic, retain) OTCDPRecoveryInformation *cdpInfo; + +@property (nonatomic, readonly) BOOL hasAuthInfo; +@property (nonatomic, retain) OTEscrowAuthenticationInformation *authInfo; + +// Performs a shallow copy into other +- (void)copyTo:(OTICDPRecordContext *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTICDPRecordContext *)other; + +OTICDPRECORDCONTEXT_FUNCTION BOOL OTICDPRecordContextReadFrom(__unsafe_unretained OTICDPRecordContext *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTICDPRecordContext.m b/keychain/ot/proto/generated_source/OTICDPRecordContext.m new file mode 100644 index 00000000..1d74b152 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTICDPRecordContext.m @@ -0,0 +1,194 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import "OTICDPRecordContext.h" +#import +#import +#import + +#import "OTCDPRecoveryInformation.h" +#import "OTEscrowAuthenticationInformation.h" + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTICDPRecordContext + +- (BOOL)hasCdpInfo +{ + return _cdpInfo != nil; +} +@synthesize cdpInfo = _cdpInfo; +- (BOOL)hasAuthInfo +{ + return _authInfo != nil; +} +@synthesize authInfo = _authInfo; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_cdpInfo) + { + [dict setObject:[_cdpInfo dictionaryRepresentation] forKey:@"cdpInfo"]; + } + if (self->_authInfo) + { + [dict setObject:[_authInfo dictionaryRepresentation] forKey:@"authInfo"]; + } + return dict; +} + +BOOL OTICDPRecordContextReadFrom(__unsafe_unretained OTICDPRecordContext *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* cdpInfo */: + { + OTCDPRecoveryInformation *new_cdpInfo = [[OTCDPRecoveryInformation alloc] init]; + self->_cdpInfo = new_cdpInfo; + PBDataReaderMark mark_cdpInfo; + BOOL markError = !PBReaderPlaceMark(reader, &mark_cdpInfo); + if (markError) + { + return NO; + } + BOOL inError = !OTCDPRecoveryInformationReadFrom(new_cdpInfo, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_cdpInfo); + } + break; + case 2 /* authInfo */: + { + OTEscrowAuthenticationInformation *new_authInfo = [[OTEscrowAuthenticationInformation alloc] init]; + self->_authInfo = new_authInfo; + PBDataReaderMark mark_authInfo; + BOOL markError = !PBReaderPlaceMark(reader, &mark_authInfo); + if (markError) + { + return NO; + } + BOOL inError = !OTEscrowAuthenticationInformationReadFrom(new_authInfo, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_authInfo); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTICDPRecordContextReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* cdpInfo */ + { + if (self->_cdpInfo != nil) + { + PBDataWriterWriteSubmessage(writer, self->_cdpInfo, 1); + } + } + /* authInfo */ + { + if (self->_authInfo != nil) + { + PBDataWriterWriteSubmessage(writer, self->_authInfo, 2); + } + } +} + +- (void)copyTo:(OTICDPRecordContext *)other +{ + if (_cdpInfo) + { + other.cdpInfo = _cdpInfo; + } + if (_authInfo) + { + other.authInfo = _authInfo; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTICDPRecordContext *copy = [[[self class] allocWithZone:zone] init]; + copy->_cdpInfo = [_cdpInfo copyWithZone:zone]; + copy->_authInfo = [_authInfo copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTICDPRecordContext *other = (OTICDPRecordContext *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_cdpInfo && !other->_cdpInfo) || [self->_cdpInfo isEqual:other->_cdpInfo]) + && + ((!self->_authInfo && !other->_authInfo) || [self->_authInfo isEqual:other->_authInfo]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_cdpInfo hash] + ^ + [self->_authInfo hash] + ; +} + +- (void)mergeFrom:(OTICDPRecordContext *)other +{ + if (self->_cdpInfo && other->_cdpInfo) + { + [self->_cdpInfo mergeFrom:other->_cdpInfo]; + } + else if (!self->_cdpInfo && other->_cdpInfo) + { + [self setCdpInfo:other->_cdpInfo]; + } + if (self->_authInfo && other->_authInfo) + { + [self->_authInfo mergeFrom:other->_authInfo]; + } + else if (!self->_authInfo && other->_authInfo) + { + [self setAuthInfo:other->_authInfo]; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.h b/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.h new file mode 100644 index 00000000..5576e3f8 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.h @@ -0,0 +1,42 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import +#import + +@class OTCDPRecoveryInformation; +@class OTEscrowAuthenticationInformation; + +#ifdef __cplusplus +#define OTICDPRECORDSILENTCONTEXT_FUNCTION extern "C" +#else +#define OTICDPRECORDSILENTCONTEXT_FUNCTION extern +#endif + +@interface OTICDPRecordSilentContext : PBCodable +{ + OTEscrowAuthenticationInformation *_authInfo; + OTCDPRecoveryInformation *_cdpInfo; +} + + +@property (nonatomic, readonly) BOOL hasCdpInfo; +@property (nonatomic, retain) OTCDPRecoveryInformation *cdpInfo; + +@property (nonatomic, readonly) BOOL hasAuthInfo; +@property (nonatomic, retain) OTEscrowAuthenticationInformation *authInfo; + +// Performs a shallow copy into other +- (void)copyTo:(OTICDPRecordSilentContext *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTICDPRecordSilentContext *)other; + +OTICDPRECORDSILENTCONTEXT_FUNCTION BOOL OTICDPRecordSilentContextReadFrom(__unsafe_unretained OTICDPRecordSilentContext *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.m b/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.m new file mode 100644 index 00000000..4d8e4f66 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTICDPRecordSilentContext.m @@ -0,0 +1,194 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTCDPRecoveryInformation.proto + +#import "OTICDPRecordSilentContext.h" +#import +#import +#import + +#import "OTCDPRecoveryInformation.h" +#import "OTEscrowAuthenticationInformation.h" + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTICDPRecordSilentContext + +- (BOOL)hasCdpInfo +{ + return _cdpInfo != nil; +} +@synthesize cdpInfo = _cdpInfo; +- (BOOL)hasAuthInfo +{ + return _authInfo != nil; +} +@synthesize authInfo = _authInfo; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_cdpInfo) + { + [dict setObject:[_cdpInfo dictionaryRepresentation] forKey:@"cdpInfo"]; + } + if (self->_authInfo) + { + [dict setObject:[_authInfo dictionaryRepresentation] forKey:@"authInfo"]; + } + return dict; +} + +BOOL OTICDPRecordSilentContextReadFrom(__unsafe_unretained OTICDPRecordSilentContext *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* cdpInfo */: + { + OTCDPRecoveryInformation *new_cdpInfo = [[OTCDPRecoveryInformation alloc] init]; + self->_cdpInfo = new_cdpInfo; + PBDataReaderMark mark_cdpInfo; + BOOL markError = !PBReaderPlaceMark(reader, &mark_cdpInfo); + if (markError) + { + return NO; + } + BOOL inError = !OTCDPRecoveryInformationReadFrom(new_cdpInfo, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_cdpInfo); + } + break; + case 2 /* authInfo */: + { + OTEscrowAuthenticationInformation *new_authInfo = [[OTEscrowAuthenticationInformation alloc] init]; + self->_authInfo = new_authInfo; + PBDataReaderMark mark_authInfo; + BOOL markError = !PBReaderPlaceMark(reader, &mark_authInfo); + if (markError) + { + return NO; + } + BOOL inError = !OTEscrowAuthenticationInformationReadFrom(new_authInfo, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_authInfo); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTICDPRecordSilentContextReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* cdpInfo */ + { + if (self->_cdpInfo != nil) + { + PBDataWriterWriteSubmessage(writer, self->_cdpInfo, 1); + } + } + /* authInfo */ + { + if (self->_authInfo != nil) + { + PBDataWriterWriteSubmessage(writer, self->_authInfo, 2); + } + } +} + +- (void)copyTo:(OTICDPRecordSilentContext *)other +{ + if (_cdpInfo) + { + other.cdpInfo = _cdpInfo; + } + if (_authInfo) + { + other.authInfo = _authInfo; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTICDPRecordSilentContext *copy = [[[self class] allocWithZone:zone] init]; + copy->_cdpInfo = [_cdpInfo copyWithZone:zone]; + copy->_authInfo = [_authInfo copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTICDPRecordSilentContext *other = (OTICDPRecordSilentContext *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_cdpInfo && !other->_cdpInfo) || [self->_cdpInfo isEqual:other->_cdpInfo]) + && + ((!self->_authInfo && !other->_authInfo) || [self->_authInfo isEqual:other->_authInfo]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_cdpInfo hash] + ^ + [self->_authInfo hash] + ; +} + +- (void)mergeFrom:(OTICDPRecordSilentContext *)other +{ + if (self->_cdpInfo && other->_cdpInfo) + { + [self->_cdpInfo mergeFrom:other->_cdpInfo]; + } + else if (!self->_cdpInfo && other->_cdpInfo) + { + [self setCdpInfo:other->_cdpInfo]; + } + if (self->_authInfo && other->_authInfo) + { + [self->_authInfo mergeFrom:other->_authInfo]; + } + else if (!self->_authInfo && other->_authInfo) + { + [self setAuthInfo:other->_authInfo]; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTPairingMessage.h b/keychain/ot/proto/generated_source/OTPairingMessage.h index e8c27edd..ba31f284 100644 --- a/keychain/ot/proto/generated_source/OTPairingMessage.h +++ b/keychain/ot/proto/generated_source/OTPairingMessage.h @@ -5,9 +5,11 @@ #import #import -@class OTSponsorToApplicantRound1M2; @class OTApplicantToSponsorRound2M1; +@class OTSponsorToApplicantRound1M2; @class OTSponsorToApplicantRound2M2; +@class OTSupportOctagonMessage; +@class OTSupportSOSMessage; #ifdef __cplusplus #define OTPAIRINGMESSAGE_FUNCTION extern "C" __attribute__((visibility("hidden"))) @@ -24,6 +26,8 @@ __attribute__((visibility("hidden"))) { OTSponsorToApplicantRound1M2 *_epoch; OTApplicantToSponsorRound2M1 *_prepare; + OTSupportOctagonMessage *_supportsOctagon; + OTSupportSOSMessage *_supportsSOS; OTSponsorToApplicantRound2M2 *_voucher; } @@ -37,6 +41,12 @@ __attribute__((visibility("hidden"))) @property (nonatomic, readonly) BOOL hasVoucher; @property (nonatomic, retain) OTSponsorToApplicantRound2M2 *voucher; +@property (nonatomic, readonly) BOOL hasSupportsOctagon; +@property (nonatomic, retain) OTSupportOctagonMessage *supportsOctagon; + +@property (nonatomic, readonly) BOOL hasSupportsSOS; +@property (nonatomic, retain) OTSupportSOSMessage *supportsSOS; + // Performs a shallow copy into other - (void)copyTo:(OTPairingMessage *)other; diff --git a/keychain/ot/proto/generated_source/OTPairingMessage.m b/keychain/ot/proto/generated_source/OTPairingMessage.m index a7c8f89b..76cefe59 100644 --- a/keychain/ot/proto/generated_source/OTPairingMessage.m +++ b/keychain/ot/proto/generated_source/OTPairingMessage.m @@ -10,6 +10,8 @@ #import "OTApplicantToSponsorRound2M1.h" #import "OTSponsorToApplicantRound1M2.h" #import "OTSponsorToApplicantRound2M2.h" +#import "OTSupportOctagonMessage.h" +#import "OTSupportSOSMessage.h" #if !__has_feature(objc_arc) # error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. @@ -32,6 +34,16 @@ return _voucher != nil; } @synthesize voucher = _voucher; +- (BOOL)hasSupportsOctagon +{ + return _supportsOctagon != nil; +} +@synthesize supportsOctagon = _supportsOctagon; +- (BOOL)hasSupportsSOS +{ + return _supportsSOS != nil; +} +@synthesize supportsSOS = _supportsSOS; - (NSString *)description { @@ -53,6 +65,14 @@ { [dict setObject:[_voucher dictionaryRepresentation] forKey:@"voucher"]; } + if (self->_supportsOctagon) + { + [dict setObject:[_supportsOctagon dictionaryRepresentation] forKey:@"supportsOctagon"]; + } + if (self->_supportsSOS) + { + [dict setObject:[_supportsSOS dictionaryRepresentation] forKey:@"supportsSOS"]; + } return dict; } @@ -126,6 +146,42 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa PBReaderRecallMark(reader, &mark_voucher); } break; + case 5 /* supportsOctagon */: + { + OTSupportOctagonMessage *new_supportsOctagon = [[OTSupportOctagonMessage alloc] init]; + self->_supportsOctagon = new_supportsOctagon; + PBDataReaderMark mark_supportsOctagon; + BOOL markError = !PBReaderPlaceMark(reader, &mark_supportsOctagon); + if (markError) + { + return NO; + } + BOOL inError = !OTSupportOctagonMessageReadFrom(new_supportsOctagon, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_supportsOctagon); + } + break; + case 6 /* supportsSOS */: + { + OTSupportSOSMessage *new_supportsSOS = [[OTSupportSOSMessage alloc] init]; + self->_supportsSOS = new_supportsSOS; + PBDataReaderMark mark_supportsSOS; + BOOL markError = !PBReaderPlaceMark(reader, &mark_supportsSOS); + if (markError) + { + return NO; + } + BOOL inError = !OTSupportSOSMessageReadFrom(new_supportsSOS, reader); + if (inError) + { + return NO; + } + PBReaderRecallMark(reader, &mark_supportsSOS); + } + break; default: if (!PBReaderSkipValueWithTag(reader, tag, aType)) return NO; @@ -162,6 +218,20 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa PBDataWriterWriteSubmessage(writer, self->_voucher, 3); } } + /* supportsOctagon */ + { + if (self->_supportsOctagon != nil) + { + PBDataWriterWriteSubmessage(writer, self->_supportsOctagon, 5); + } + } + /* supportsSOS */ + { + if (self->_supportsSOS != nil) + { + PBDataWriterWriteSubmessage(writer, self->_supportsSOS, 6); + } + } } - (void)copyTo:(OTPairingMessage *)other @@ -178,6 +248,14 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa { other.voucher = _voucher; } + if (_supportsOctagon) + { + other.supportsOctagon = _supportsOctagon; + } + if (_supportsSOS) + { + other.supportsSOS = _supportsSOS; + } } - (id)copyWithZone:(NSZone *)zone @@ -186,6 +264,8 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa copy->_epoch = [_epoch copyWithZone:zone]; copy->_prepare = [_prepare copyWithZone:zone]; copy->_voucher = [_voucher copyWithZone:zone]; + copy->_supportsOctagon = [_supportsOctagon copyWithZone:zone]; + copy->_supportsSOS = [_supportsSOS copyWithZone:zone]; return copy; } @@ -199,6 +279,10 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa ((!self->_prepare && !other->_prepare) || [self->_prepare isEqual:other->_prepare]) && ((!self->_voucher && !other->_voucher) || [self->_voucher isEqual:other->_voucher]) + && + ((!self->_supportsOctagon && !other->_supportsOctagon) || [self->_supportsOctagon isEqual:other->_supportsOctagon]) + && + ((!self->_supportsSOS && !other->_supportsSOS) || [self->_supportsSOS isEqual:other->_supportsSOS]) ; } @@ -211,6 +295,10 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa [self->_prepare hash] ^ [self->_voucher hash] + ^ + [self->_supportsOctagon hash] + ^ + [self->_supportsSOS hash] ; } @@ -240,6 +328,22 @@ BOOL OTPairingMessageReadFrom(__unsafe_unretained OTPairingMessage *self, __unsa { [self setVoucher:other->_voucher]; } + if (self->_supportsOctagon && other->_supportsOctagon) + { + [self->_supportsOctagon mergeFrom:other->_supportsOctagon]; + } + else if (!self->_supportsOctagon && other->_supportsOctagon) + { + [self setSupportsOctagon:other->_supportsOctagon]; + } + if (self->_supportsSOS && other->_supportsSOS) + { + [self->_supportsSOS mergeFrom:other->_supportsSOS]; + } + else if (!self->_supportsSOS && other->_supportsSOS) + { + [self setSupportsSOS:other->_supportsSOS]; + } } @end diff --git a/keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.m b/keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.m index 7a2aad45..43b70418 100644 --- a/keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.m +++ b/keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.m @@ -25,7 +25,7 @@ } - (BOOL)hasEpoch { - return _has.epoch; + return _has.epoch != 0; } - (NSString *)description diff --git a/keychain/ot/proto/generated_source/OTSupportOctagonMessage.h b/keychain/ot/proto/generated_source/OTSupportOctagonMessage.h new file mode 100644 index 00000000..bfe58f0d --- /dev/null +++ b/keychain/ot/proto/generated_source/OTSupportOctagonMessage.h @@ -0,0 +1,43 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTPairingMessage.proto + +#import +#import + +#import "OTGlobalEnums.h" + +#ifdef __cplusplus +#define OTSUPPORTOCTAGONMESSAGE_FUNCTION extern "C" __attribute__((visibility("hidden"))) +#else +#define OTSUPPORTOCTAGONMESSAGE_FUNCTION extern __attribute__((visibility("hidden"))) +#endif + +__attribute__((visibility("hidden"))) +@interface OTSupportOctagonMessage : PBCodable +{ + OTSupportType _supported; + struct { + int supported:1; + } _has; +} + + +@property (nonatomic) BOOL hasSupported; +@property (nonatomic) OTSupportType supported; +- (NSString *)supportedAsString:(OTSupportType)value; +- (OTSupportType)StringAsSupported:(NSString *)str; + +// Performs a shallow copy into other +- (void)copyTo:(OTSupportOctagonMessage *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTSupportOctagonMessage *)other; + +OTSUPPORTOCTAGONMESSAGE_FUNCTION BOOL OTSupportOctagonMessageReadFrom(__unsafe_unretained OTSupportOctagonMessage *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTSupportOctagonMessage.m b/keychain/ot/proto/generated_source/OTSupportOctagonMessage.m new file mode 100644 index 00000000..dceeaee4 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTSupportOctagonMessage.m @@ -0,0 +1,151 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTPairingMessage.proto + +#import "OTSupportOctagonMessage.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTSupportOctagonMessage + +@synthesize supported = _supported; +- (OTSupportType)supported +{ + return _has.supported ? _supported : OTSupportType_unknown; +} +- (void)setSupported:(OTSupportType)v +{ + _has.supported = YES; + _supported = v; +} +- (void)setHasSupported:(BOOL)f +{ + _has.supported = f; +} +- (BOOL)hasSupported +{ + return _has.supported != 0; +} +- (NSString *)supportedAsString:(OTSupportType)value +{ + return OTSupportTypeAsString(value); +} +- (OTSupportType)StringAsSupported:(NSString *)str +{ + return StringAsOTSupportType(str); +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.supported) + { + [dict setObject:OTSupportTypeAsString(self->_supported) forKey:@"supported"]; + } + return dict; +} + +BOOL OTSupportOctagonMessageReadFrom(__unsafe_unretained OTSupportOctagonMessage *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* supported */: + { + self->_has.supported = YES; + self->_supported = PBReaderReadInt32(reader); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTSupportOctagonMessageReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* supported */ + { + if (self->_has.supported) + { + PBDataWriterWriteInt32Field(writer, self->_supported, 1); + } + } +} + +- (void)copyTo:(OTSupportOctagonMessage *)other +{ + if (self->_has.supported) + { + other->_supported = _supported; + other->_has.supported = YES; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTSupportOctagonMessage *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.supported) + { + copy->_supported = _supported; + copy->_has.supported = YES; + } + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTSupportOctagonMessage *other = (OTSupportOctagonMessage *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.supported && other->_has.supported && self->_supported == other->_supported) || (!self->_has.supported && !other->_has.supported)) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.supported ? PBHashInt((NSUInteger)self->_supported) : 0) + ; +} + +- (void)mergeFrom:(OTSupportOctagonMessage *)other +{ + if (other->_has.supported) + { + self->_supported = other->_supported; + self->_has.supported = YES; + } +} + +@end + diff --git a/keychain/ot/proto/generated_source/OTSupportSOSMessage.h b/keychain/ot/proto/generated_source/OTSupportSOSMessage.h new file mode 100644 index 00000000..d9982886 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTSupportSOSMessage.h @@ -0,0 +1,43 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTPairingMessage.proto + +#import +#import + +#import "OTGlobalEnums.h" + +#ifdef __cplusplus +#define OTSUPPORTSOSMESSAGE_FUNCTION extern "C" __attribute__((visibility("hidden"))) +#else +#define OTSUPPORTSOSMESSAGE_FUNCTION extern __attribute__((visibility("hidden"))) +#endif + +__attribute__((visibility("hidden"))) +@interface OTSupportSOSMessage : PBCodable +{ + OTSupportType _supported; + struct { + int supported:1; + } _has; +} + + +@property (nonatomic) BOOL hasSupported; +@property (nonatomic) OTSupportType supported; +- (NSString *)supportedAsString:(OTSupportType)value; +- (OTSupportType)StringAsSupported:(NSString *)str; + +// Performs a shallow copy into other +- (void)copyTo:(OTSupportSOSMessage *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(OTSupportSOSMessage *)other; + +OTSUPPORTSOSMESSAGE_FUNCTION BOOL OTSupportSOSMessageReadFrom(__unsafe_unretained OTSupportSOSMessage *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/ot/proto/generated_source/OTSupportSOSMessage.m b/keychain/ot/proto/generated_source/OTSupportSOSMessage.m new file mode 100644 index 00000000..059472c6 --- /dev/null +++ b/keychain/ot/proto/generated_source/OTSupportSOSMessage.m @@ -0,0 +1,151 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from OTPairingMessage.proto + +#import "OTSupportSOSMessage.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation OTSupportSOSMessage + +@synthesize supported = _supported; +- (OTSupportType)supported +{ + return _has.supported ? _supported : OTSupportType_unknown; +} +- (void)setSupported:(OTSupportType)v +{ + _has.supported = YES; + _supported = v; +} +- (void)setHasSupported:(BOOL)f +{ + _has.supported = f; +} +- (BOOL)hasSupported +{ + return _has.supported != 0; +} +- (NSString *)supportedAsString:(OTSupportType)value +{ + return OTSupportTypeAsString(value); +} +- (OTSupportType)StringAsSupported:(NSString *)str +{ + return StringAsOTSupportType(str); +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.supported) + { + [dict setObject:OTSupportTypeAsString(self->_supported) forKey:@"supported"]; + } + return dict; +} + +BOOL OTSupportSOSMessageReadFrom(__unsafe_unretained OTSupportSOSMessage *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* supported */: + { + self->_has.supported = YES; + self->_supported = PBReaderReadInt32(reader); + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return OTSupportSOSMessageReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* supported */ + { + if (self->_has.supported) + { + PBDataWriterWriteInt32Field(writer, self->_supported, 1); + } + } +} + +- (void)copyTo:(OTSupportSOSMessage *)other +{ + if (self->_has.supported) + { + other->_supported = _supported; + other->_has.supported = YES; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + OTSupportSOSMessage *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.supported) + { + copy->_supported = _supported; + copy->_has.supported = YES; + } + return copy; +} + +- (BOOL)isEqual:(id)object +{ + OTSupportSOSMessage *other = (OTSupportSOSMessage *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.supported && other->_has.supported && self->_supported == other->_supported) || (!self->_has.supported && !other->_has.supported)) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.supported ? PBHashInt((NSUInteger)self->_supported) : 0) + ; +} + +- (void)mergeFrom:(OTSupportSOSMessage *)other +{ + if (other->_has.supported) + { + self->_supported = other->_supported; + self->_has.supported = YES; + } +} + +@end + diff --git a/keychain/ot/proto/source/OTSOSMessage.h b/keychain/ot/proto/source/OTSOSMessage.h deleted file mode 100644 index e515077e..00000000 --- a/keychain/ot/proto/source/OTSOSMessage.h +++ /dev/null @@ -1,48 +0,0 @@ -// This file was automatically generated by protocompiler -// DO NOT EDIT! -// Compiled from OTPairingMessage.proto - -#import -#import - -#ifdef __cplusplus -#define OTSOSMESSAGE_FUNCTION extern "C" __attribute__((visibility("hidden"))) -#else -#define OTSOSMESSAGE_FUNCTION extern __attribute__((visibility("hidden"))) -#endif - -__attribute__((visibility("hidden"))) -@interface OTSOSMessage : PBCodable -{ - NSData *_circleBlob; - NSData *_credential; - NSData *_initialSyncItems; - NSData *_peerInfo; -} - - -@property (nonatomic, readonly) BOOL hasCredential; -@property (nonatomic, retain) NSData *credential; - -@property (nonatomic, readonly) BOOL hasPeerInfo; -@property (nonatomic, retain) NSData *peerInfo; - -@property (nonatomic, readonly) BOOL hasCircleBlob; -@property (nonatomic, retain) NSData *circleBlob; - -@property (nonatomic, readonly) BOOL hasInitialSyncItems; -@property (nonatomic, retain) NSData *initialSyncItems; - -// Performs a shallow copy into other -- (void)copyTo:(OTSOSMessage *)other; - -// Performs a deep merge from other into self -// If set in other, singular values in self are replaced in self -// Singular composite values are recursively merged -// Repeated values from other are appended to repeated values in self -- (void)mergeFrom:(OTSOSMessage *)other; - -OTSOSMESSAGE_FUNCTION BOOL OTSOSMessageReadFrom(__unsafe_unretained OTSOSMessage *self, __unsafe_unretained PBDataReader *reader); - -@end - diff --git a/keychain/ot/tests/gen_test_plist.py b/keychain/ot/tests/gen_test_plist.py index 2b01e9a4..3ecb9ff4 100644 --- a/keychain/ot/tests/gen_test_plist.py +++ b/keychain/ot/tests/gen_test_plist.py @@ -43,7 +43,24 @@ for x in ['TrustedPeersTests', 'TrustedPeersHelperUnitTests']: test_dictionary['WorkingDirectory'] = '/AppleInternal/XCTests/com.apple.security/' test_command = Foundation.NSMutableArray.array() - test_command.append('BATS_XCTEST_CMD {}.xctest'.format(x)) + test_command.append('BATS_XCTEST_CMD') + test_command.append('{}.xctest'.format(x)) + test_dictionary['Command'] = test_command + + test_list.append(test_dictionary) + + +for x in ['OctagonTrustTests']: + + test_dictionary = Foundation.NSMutableDictionary.dictionary() + test_dictionary['TestName'] = x + test_dictionary['Timeout']= 1200 + test_dictionary['ShowSubtestResults']= True + test_dictionary['WorkingDirectory'] = '/AppleInternal/XCTests/com.apple.security/' + + test_command = Foundation.NSMutableArray.array() + test_command.append('BATS_XCTEST_CMD') + test_command.append('{}.xctest'.format(x)) test_dictionary['Command'] = test_command test_list.append(test_dictionary) @@ -58,7 +75,10 @@ for x in get_class_names(): test_dictionary['WorkingDirectory'] = '/AppleInternal/XCTests/com.apple.security/' test_command = Foundation.NSMutableArray.array() - test_command.append('BATS_XCTEST_CMD -XCTest {} OctagonTests.xctest'.format(x)) + test_command.append('BATS_XCTEST_CMD') + test_command.append('-XCTest') + test_command.append('{}'.format(x)) + test_command.append('OctagonTests.xctest') test_dictionary['Command'] = test_command test_list.append(test_dictionary) diff --git a/keychain/ot/tests/octagon/.swiftlint.yml b/keychain/ot/tests/octagon/.swiftlint.yml index 9ddd0d11..f8391d9b 100644 --- a/keychain/ot/tests/octagon/.swiftlint.yml +++ b/keychain/ot/tests/octagon/.swiftlint.yml @@ -1,3 +1,4 @@ disabled_rules: - force_cast - force_try + - implicitly_unwrapped_optional diff --git a/keychain/ot/tests/octagon/OctagonDataPersistenceTests.swift b/keychain/ot/tests/octagon/OctagonDataPersistenceTests.swift index 82e22519..5dd8c49c 100644 --- a/keychain/ot/tests/octagon/OctagonDataPersistenceTests.swift +++ b/keychain/ot/tests/octagon/OctagonDataPersistenceTests.swift @@ -3,7 +3,6 @@ import XCTest #if OCTAGON class OctagonAccountMetadataClassCPersistenceTests: CloudKitKeychainSyncingMockXCTest { - override static func setUp() { super.setUp() @@ -147,7 +146,7 @@ class OctagonAccountMetadataClassCPersistenceTests: CloudKitKeychainSyncingMockX do { let state2 = try OTAccountMetadataClassC.loadFromKeychain(forContainer: OTCKContainerName, contextID: OTDefaultContext) XCTAssertNotNil(state2) - XCTAssertEqual(state2.peerID, nil, "peerID should be nil") + XCTAssertNil(state2.peerID, "peerID should be nil") XCTAssertEqual(state2.icloudAccountState, OTAccountMetadataClassC_AccountState.UNKNOWN, "account state should be OTAccountMetadataClassC_AccountState_UNKNOWN") XCTAssertEqual(state2.trustState, OTAccountMetadataClassC_TrustState.UNKNOWN, "trust state should be OTAccountMetadataClassC_TrustState_UNKNOWN") } catch { diff --git a/keychain/ot/tests/octagon/OctagonPolicyTests.swift b/keychain/ot/tests/octagon/OctagonPolicyTests.swift new file mode 100644 index 00000000..4152e8cc --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonPolicyTests.swift @@ -0,0 +1,57 @@ +import Foundation + +class OctagonPolicyTests: XCTestCase { + func prevailingPolicy() throws -> TPPolicy { + let policyDocument = builtInPolicyDocuments().filter { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }.first + XCTAssertNotNil(policyDocument, "Should have a prevailing policy document") + + let policy = try policyDocument!.policy(withSecrets: [:], decrypter: Decrypter()) + return policy + } + + func testPrevailingPolicyHasModelsForAllViewRules() throws { + let policy = try self.prevailingPolicy() + + // There's a rule for 'NotSynced', but we explicitly don't want to bring up that view + let viewsWithRules = Set(policy.keyViewMapping.compactMap { $0.view }).subtracting(Set(["NotSynced"])) + XCTAssertEqual(Set(policy.categoriesByView.keys), + viewsWithRules, + "Every view should have a rule") + } + + func testPrevailingPolicyIntroducerGraphIsClosed() throws { + // Let's check that, for each model, introducing a new peer doesn't give them more introduction power + let policy = try self.prevailingPolicy() + + policy.introducersByCategory.forEach { category, introducers in + let allowedIntroducers = Set(introducers) + let allAccessible = Set(allowedIntroducers.compactMap { category in policy.introducersByCategory[category] }.joined()) + + XCTAssertEqual(allowedIntroducers, allAccessible, "A device class shouldn't be able to introduce a peer which can introduce a peer that the original device couldn't introduce") + } + } + + func testPrePolicyViews() throws { + let policy = try self.prevailingPolicy() + + XCTAssert(policy.keyViewMapping.count >= 7, "Should always have 7 basic views") + + let firstSevenRules = policy.keyViewMapping[..<7] + + let firstSevenViews = firstSevenRules.compactMap { $0.view } + XCTAssertEqual(Set(firstSevenViews), + Set(["ApplePay", "AutoUnlock", "Engram", "Health", "Home", "Manatee", "LimitedPeersAllowed"]), + "First seven rules should be for prepolicy views") + + // Now, ensure that the first seven rules match vwht only + firstSevenRules.forEach { viewRule in + XCTAssertNotNil(viewRule.view, "View rule should have a name") + XCTAssertNotNil(viewRule.matchingRule, "Rule should have a matching rule") + let rule = viewRule.matchingRule! + + XCTAssertNotNil(rule.match, "Rule should have a match subrule") + XCTAssertEqual(rule.match.fieldName, "vwht", "Rule should match field vwht") + XCTAssertEqual(rule.match.regex, "^\(viewRule.view!)$", "Regex should match field name") + } + } +} diff --git a/keychain/ot/tests/octagon/OctagonTestMocks.swift b/keychain/ot/tests/octagon/OctagonTestMocks.swift index ef94770e..874585e8 100644 --- a/keychain/ot/tests/octagon/OctagonTestMocks.swift +++ b/keychain/ot/tests/octagon/OctagonTestMocks.swift @@ -12,24 +12,24 @@ class OTMockSecureBackup: NSObject, OctagonEscrowRecovererPrococol { super.init() } - func recover(withInfo info: [AnyHashable: Any]!, - results: AutoreleasingUnsafeMutablePointer!) -> Error! { + func recover(withInfo info: [AnyHashable: Any]?, + results: AutoreleasingUnsafeMutablePointer?) -> Error? { if self.bottleID == nil && self.entropy == nil { - results.pointee = [ + results!.pointee = [ "bottleValid": "invalid", ] } else if self.bottleID == nil && self.entropy != nil { - results.pointee = [ + results!.pointee = [ "EscrowServiceEscrowData": ["BottledPeerEntropy": self.entropy], "bottleValid": "invalid", ] } else if self.bottleID != nil && self.entropy == nil { - results.pointee = [ + results!.pointee = [ "bottleID": self.bottleID!, "bottleValid": "invalid", ] } else { //entropy and bottleID must exist, so its a good bottle. - results.pointee = [ + results!.pointee = [ "bottleID": self.bottleID!, "bottleValid": "valid", "EscrowServiceEscrowData": ["BottledPeerEntropy": self.entropy], @@ -41,6 +41,17 @@ class OTMockSecureBackup: NSObject, OctagonEscrowRecovererPrococol { func disable(withInfo info: [AnyHashable: Any]!) -> Error? { return nil } + + @objc func getAccountInfo(withInfo info: [AnyHashable: Any]!, results: AutoreleasingUnsafeMutablePointer!) -> Error? { + let recordData = accountInfoWithInfoSample.data(using: .utf8)! + var propertyListFormat = PropertyListSerialization.PropertyListFormat.xml + do { + results.pointee = try PropertyListSerialization.propertyList(from: recordData, options: .mutableContainersAndLeaves, format: &propertyListFormat) as! [String: AnyObject] as NSDictionary + } catch { + print("Error reading plist: \(error), format: \(propertyListFormat)") + } + return nil + } } class OTMockFollowUpController: NSObject, OctagonFollowUpControllerProtocol { diff --git a/keychain/ot/tests/octagon/OctagonTests+Account.swift b/keychain/ot/tests/octagon/OctagonTests+Account.swift index fa1e3879..b19af22d 100644 --- a/keychain/ot/tests/octagon/OctagonTests+Account.swift +++ b/keychain/ot/tests/octagon/OctagonTests+Account.swift @@ -92,8 +92,8 @@ class OctagonAccountTests: OctagonTestsBase { self.wait(for: [quiescentExpectation], timeout: 10) - // CKKS should also be logged out, since Octagon believes there's no account - self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + // Since there's no acocunt, CKKS shouldn't even have any views loaded + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have 0 CKKS views loaded") } func testNoAccountLeadsToInitialize() throws { @@ -432,6 +432,19 @@ class OctagonAccountTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) } + func testDetermineCDPStateFromSOSError() throws { + // If SOS reports that it doesn't have the user key, a circle might exist and it might not + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCError) + self.mockSOSAdapter.circleStatusError = NSError(domain: kSOSErrorDomain as String, code: kSOSErrorPublicKeyAbsent, userInfo: nil) + + self.startCKAccountStatusMock() + + // Octagon should discover the right CDP state, and end up in untrusted + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .unknown, "CDP status should be 'unknown'") + } + func testSignOut() throws { self.startCKAccountStatusMock() @@ -496,7 +509,7 @@ class OctagonAccountTests: OctagonTestsBase { //check trust status let checkTrustExpectation = self.expectation(description: "checkTrustExpectation callback occurs") let configuration = OTOperationConfiguration() - self.cuttlefishContext.rpcTrustStatus(configuration) { _, _, _, _, _ in + self.cuttlefishContext.rpcTrustStatus(configuration) { _, _, _, _, _, _ in checkTrustExpectation.fulfill() } self.wait(for: [checkTrustExpectation], timeout: 10) @@ -562,7 +575,6 @@ class OctagonAccountTests: OctagonTestsBase { } self.wait(for: [joinWithBottleExpectation], timeout: 3) } - } #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+CKKS.swift b/keychain/ot/tests/octagon/OctagonTests+CKKS.swift index 4888f6e1..96b15016 100644 --- a/keychain/ot/tests/octagon/OctagonTests+CKKS.swift +++ b/keychain/ot/tests/octagon/OctagonTests+CKKS.swift @@ -1,6 +1,63 @@ #if OCTAGON class OctagonCKKSTests: OctagonTestsBase { + var previousKeychainAccessGroups: [String]! + + override func setUp() { + // These tests would like to examine the behavior of a CKKS user-controlled-view + if self.mockDeviceInfo == nil { + let actualDeviceAdapter = OTDeviceInformationActualAdapter() + self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: actualDeviceAdapter.modelID(), + deviceName: actualDeviceAdapter.deviceName(), + serialNumber: NSUUID().uuidString, + osVersion: actualDeviceAdapter.osVersion()) + } + + if self.mockDeviceInfo.mockModelID.contains("AppleTV") { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + ]) + } else { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + CKRecordZone.ID(zoneName: "Manatee"), + CKRecordZone.ID(zoneName: "Passwords"), + CKRecordZone.ID(zoneName: "SecureObjectSync"), + CKRecordZone.ID(zoneName: "Backstop"), + ]) + } + + super.setUp() + + XCTAssertTrue(self.cuttlefishContext.viewManager!.useCKKSViewsFromPolicy(), "CKKS should be configured to listen to policy-based views") + + // Allow ourselves to add safari items + self.previousKeychainAccessGroups = (SecAccessGroupsGetCurrent()?.takeUnretainedValue()) as? [String] + SecAccessGroupsSetCurrent((self.previousKeychainAccessGroups + ["com.apple.cfnetwork", "com.apple.sbd"]) as CFArray) + } + + override func tearDown() { + SecAccessGroupsSetCurrent(self.previousKeychainAccessGroups as CFArray) + super.tearDown() + } + + func testHandleSBDItemAddSort() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + #if os(tvOS) + // do not continue: TVs don't sync sos items. + #else + + self.expectCKModifyItemRecords(1, currentKeyPointerRecords: 1, zoneID: CKRecordZone.ID(zoneName: "SecureObjectSync")) + self.addGenericPassword("asdf", + account: "SBD-test", + accessGroup: "com.apple.sbd") + + self.verifyDatabaseMocks() + #endif // tvos test skip + } + func testHandleCKKSKeyHierarchyConflictOnEstablish() throws { self.startCKAccountStatusMock() @@ -64,6 +121,354 @@ class OctagonCKKSTests: OctagonTestsBase { self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) self.verifyDatabaseMocks() } + + func testUserControllableViewStatusAPI() throws { + self.startCKAccountStatusMock() + + let establishExpectation = self.expectation(description: "establish") + self.fakeCuttlefishServer.establishListener = { request in + XCTAssertTrue(request.peer.hasStableInfoAndSig, "updateTrust request should have a stableInfo info") + let newStableInfo = request.peer.stableInfoAndSig.stableInfo() + #if os(tvOS) || os(watchOS) + XCTAssertEqual(newStableInfo.syncUserControllableViews, .FOLLOWING, "User-controllable views should be 'following'") + #else + XCTAssertEqual(newStableInfo.syncUserControllableViews, .DISABLED, "User-controllable views should be disabled") + #endif + establishExpectation.fulfill() + return nil + } + + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + self.wait(for: [establishExpectation], timeout: 10) + self.fakeCuttlefishServer.establishListener = nil + + #if os(tvOS) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow") + + XCTAssertTrue(self.injectedManager?.policy?.syncUserControllableViewsAsBoolean() ?? false, "CKKS should be syncing user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + + // Watches won't ever disable the user views, so the API should fail + XCTAssertThrowsError(try clique.setUserControllableViewsSyncStatus(false), "Should be an error setting user-visible sync status") + XCTAssertThrowsError(try clique.setUserControllableViewsSyncStatus(true), "Should be an error setting user-visible sync status") + + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow peer's opinions of sync user views") + XCTAssertTrue(self.injectedManager?.policy?.syncUserControllableViewsAsBoolean() ?? false, "CKKS should be syncing user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + + #else + + #if !os(watchOS) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .DISABLED, "CKKS should be configured to not sync user views") + + // And disabling it again doesn't write to the server + self.assertModifyUserViewsWithNoPeerUpdate(clique: clique, intendedSyncStatus: false) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .DISABLED, "CKKS should be configured to not sync user views") + #else + // Watches, since some support this UI, and others don't, get special handling + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow") + XCTAssertTrue(self.injectedManager?.policy?.syncUserControllableViewsAsBoolean() ?? false, "CKKS should be syncing user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + + self.assertModifyUserViews(clique: clique, intendedSyncStatus: false) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .DISABLED, "CKKS should be configured to not sync user views") + #endif // watchOS + + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Manatee items should upload + self.expectCKModifyItemRecords(1, currentKeyPointerRecords: 1, zoneID: self.manateeZoneID) + self.addGenericPassword("asdf", account: "account-delete-me", viewHint: "Manatee") + self.verifyDatabaseMocks() + + // But Passwords items should not + self.addGenericPassword("asdf", + account: "account-apple.com", + access: kSecAttrAccessibleWhenUnlocked as String, + viewHint: nil, + accessGroup: "com.apple.cfnetwork", + expecting: errSecSuccess, + message: "Should be able to add a CFNetwork keychain item") + let passwordsView = self.injectedManager?.findView("Passwords") + XCTAssertNotNil(passwordsView, "Should have a passwords view") + passwordsView!.waitForOperations(of: CKKSOutgoingQueueOperation.self) + + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // And how about enabling it? That should upload the password + self.expectCKModifyItemRecords(1, currentKeyPointerRecords: 1, zoneID: self.passwordsZoneID) + self.assertModifyUserViews(clique: clique, intendedSyncStatus: true) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .ENABLED, "CKKS should be configured to sync user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + self.verifyDatabaseMocks() + + // And enabling it again doesn't write to the server + self.assertModifyUserViewsWithNoPeerUpdate(clique: clique, intendedSyncStatus: true) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .ENABLED, "CKKS should be configured to sync user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + + // And we can turn it off again + self.assertModifyUserViews(clique: clique, intendedSyncStatus: false) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .DISABLED, "CKKS should be configured to not sync user views") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + #endif // !os(tvOS) + } + + func testJoinFollowsUserViewStatus() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) + // For tvs, this is always on + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + + // Add a peer + let peer2Context = self.makeInitiatorContext(contextID: "peer2") + self.assertJoinViaEscrowRecovery(joiningContext: peer2Context, sponsor: self.cuttlefishContext) + + // The new peer should automatically have turned on user view syncing + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2Context), status: true) + + // TVs can't ever modify this value + let peer2Clique = self.cliqueFor(context: peer2Context) + XCTAssertThrowsError(try peer2Clique.setUserControllableViewsSyncStatus(false), "Should be an error setting user-visible sync status") + XCTAssertThrowsError(try peer2Clique.setUserControllableViewsSyncStatus(true), "Should be an error setting user-visible sync status") + self.assertFetchUserControllableViewsSyncStatus(clique: peer2Clique, status: true) + + #elseif os(watchOS) + // Watches are following by default. Turn the status off for the rest of the test + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow") + + self.assertModifyUserViews(clique: clique, intendedSyncStatus: false) + XCTAssertEqual(self.injectedManager?.policy?.syncUserControllableViews, .DISABLED, "CKKS should be configured to not sync user views") + + // Add a peer + let peer2Context = self.makeInitiatorContext(contextID: "peer2") + self.assertJoinViaEscrowRecovery(joiningContext: peer2Context, sponsor: self.cuttlefishContext) + + // A new watch peer will be FOLLOWING, so this API will return true + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2Context), status: true) + + #else // iOS, macOS + + // By default, the sync status is "off" + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Add a peer + let peer2Context = self.makeInitiatorContext(contextID: "peer2") + self.assertJoinViaEscrowRecovery(joiningContext: peer2Context, sponsor: self.cuttlefishContext) + + // The new peer should automatically have disabled syncing + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2Context), status: false) + + self.assertModifyUserViews(clique: self.cliqueFor(context: peer2Context), intendedSyncStatus: true) + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2Context), status: true) + #endif // iOS, macOS + + // And a third peer joins! + let peer3Context = self.makeInitiatorContext(contextID: "peer3", authKitAdapter: self.mockAuthKit3) + self.assertJoinViaEscrowRecovery(joiningContext: peer3Context, sponsor: peer2Context) + + #if os(tvOS) || os(watchOS) + // Watches and TVs won't ever turn this off (without extra UI), so a freshly joined peer will report this status as true + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer3Context), status: true) + #else + // Peer3, by default, should have disabled the user controllable views (following peer1) + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer3Context), status: false) + #endif + } + + func testUpgradePeerToHaveUserSyncableViewsOpinionViaAskingSOS() throws { + self.mockSOSAdapter.safariViewEnabled = true + + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) || os(watchOS) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + // Now, fake that the peer no longer has this opinion: + do { + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, + context: self.cuttlefishContext.contextID) + + let (_, newSyncingPolicy, updateError) = container.updateSync(test: self, + syncUserControllableViews: .UNKNOWN) + XCTAssertNil(updateError, "Should be no error performing update") + XCTAssertNotNil(newSyncingPolicy, "Should have a syncing policy") + XCTAssertEqual(newSyncingPolicy?.syncUserControllableViews, .UNKNOWN, "Should now have 'unknown' user controlled views setting") + + self.injectedManager?.setCurrentSyncingPolicy(newSyncingPolicy) + + try self.cuttlefishContext.accountMetadataStore.persistAccountChanges { metadata in + metadata.setTPSyncingPolicy(newSyncingPolicy) + return metadata + } + } + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Upon daemon restart, Octagon should notice and update its opinion + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + #if os(tvOS) || os(watchOS) + XCTAssertEqual(newStableInfo.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow peer's user views") + #else + XCTAssertEqual(newStableInfo.syncUserControllableViews, .ENABLED, "CKKS should be configured to sync user views (following SOS's lead)") + #endif + updateTrustExpectation.fulfill() + return nil + } + + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) + self.wait(for: [updateTrustExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should pause") + } + + func testUpgradePeerToHaveUserSyncableViewsOpinionViaPeersOpinion() throws { + self.mockSOSAdapter.sosEnabled = false + + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) || os(watchOS) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + // Now, fake that the peer no longer has this opinion: + do { + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, + context: self.cuttlefishContext.contextID) + + let (_, newSyncingPolicy, updateError) = container.updateSync(test: self, + syncUserControllableViews: .UNKNOWN) + XCTAssertNil(updateError, "Should be no error performing update") + XCTAssertNotNil(newSyncingPolicy, "Should have a syncing policy") + XCTAssertEqual(newSyncingPolicy?.syncUserControllableViews, .UNKNOWN, "Should now have 'unknown' user controlled views setting") + + self.injectedManager?.setCurrentSyncingPolicy(newSyncingPolicy) + + try self.cuttlefishContext.accountMetadataStore.persistAccountChanges { metadata in + metadata.setTPSyncingPolicy(newSyncingPolicy) + return metadata + } + } + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Upon daemon restart, Octagon should notice and update its opinion + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + #if os(tvOS) || os(watchOS) + XCTAssertEqual(newStableInfo.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow peer's user views") + #else + XCTAssertEqual(newStableInfo.syncUserControllableViews, .DISABLED, "CKKS should be configured to disable user views, since no peers have it actively enabled") + #endif + updateTrustExpectation.fulfill() + return nil + } + + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) + self.wait(for: [updateTrustExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should pause") + } + + func testUpgradePeerToHaveUserSyncableViewsOpinionWhileLocked() throws { + self.mockSOSAdapter.safariViewEnabled = true + + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) || os(watchOS) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + // Now, fake that the peer no longer has this opinion: + do { + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, + context: self.cuttlefishContext.contextID) + + let (_, newSyncingPolicy, updateError) = container.updateSync(test: self, + syncUserControllableViews: .UNKNOWN) + XCTAssertNil(updateError, "Should be no error performing update") + XCTAssertNotNil(newSyncingPolicy, "Should have a syncing policy") + XCTAssertEqual(newSyncingPolicy?.syncUserControllableViews, .UNKNOWN, "Should now have 'unknown' user controlled views setting") + + self.injectedManager?.setCurrentSyncingPolicy(newSyncingPolicy) + + try self.cuttlefishContext.accountMetadataStore.persistAccountChanges { metadata in + metadata.setTPSyncingPolicy(newSyncingPolicy) + return metadata + } + } + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + + // Upon daemon restart, Octagon should notice and update its opinion + + self.aksLockState = true + self.lockStateTracker.recheck() + + self.fakeCuttlefishServer.updateListener = { _ in + XCTFail("No update should happen while the device is locked") + return nil + } + + // We should get to 'wait for unlock' + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 100 * NSEC_PER_SEC) + + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + #if os(tvOS) || os(watchOS) + XCTAssertEqual(newStableInfo.syncUserControllableViews, .FOLLOWING, "CKKS should be configured to follow peer's user views") + #else + XCTAssertEqual(newStableInfo.syncUserControllableViews, .ENABLED, "CKKS should be configured to sync user views (following SOS's lead)") + #endif + updateTrustExpectation.fulfill() + return nil + } + + // and once we unlock, the update should go through + self.aksLockState = false + self.lockStateTracker.recheck() + + self.wait(for: [updateTrustExpectation], timeout: 10) + } + + func testAssistCKKSTLKUploadWhenMissingFromOctagon() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + // Another peer resets Octagon, but we miss the push + let reset = self.makeInitiatorContext(contextID: "reset") + self.assertResetAndBecomeTrusted(context: reset) + + // This should cause the original peer to notice that it's no longer trusted + self.silentZoneDeletesAllowed = true + self.resetAllCKKSViews() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 100 * NSEC_PER_SEC) + } } #endif // OCTAGON diff --git a/keychain/ot/tests/octagon/OctagonTests+CKKSConfiguration.swift b/keychain/ot/tests/octagon/OctagonTests+CKKSConfiguration.swift index 67e9a821..5cad6bd4 100644 --- a/keychain/ot/tests/octagon/OctagonTests+CKKSConfiguration.swift +++ b/keychain/ot/tests/octagon/OctagonTests+CKKSConfiguration.swift @@ -48,7 +48,6 @@ class OctagonCKKSConfigurationTestsPolicyDisabled: OctagonTestsBase { class OctagonCKKSConfigurationTestsPolicyEnabled: OctagonTestsBase { override func setUp() { - if self.mockDeviceInfo == nil { let actualDeviceAdapter = OTDeviceInformationActualAdapter() self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: actualDeviceAdapter.modelID(), @@ -69,18 +68,15 @@ class OctagonCKKSConfigurationTestsPolicyEnabled: OctagonTestsBase { CKRecordZone.ID(zoneName: "ApplePay"), CKRecordZone.ID(zoneName: "Applications"), CKRecordZone.ID(zoneName: "AutoUnlock"), - // Octagon: create final policy for CKKS4All - // CKRecordZone.ID(zoneName: "Backstop"), - // Cuttlefish: remove Safari prefix from view names - CKRecordZone.ID(zoneName: "SafariCreditCards"), + CKRecordZone.ID(zoneName: "Backstop"), + CKRecordZone.ID(zoneName: "CreditCards"), CKRecordZone.ID(zoneName: "DevicePairing"), CKRecordZone.ID(zoneName: "Engram"), CKRecordZone.ID(zoneName: "Health"), CKRecordZone.ID(zoneName: "Home"), CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), CKRecordZone.ID(zoneName: "Manatee"), - // Cuttlefish: remove Safari prefix from view names - CKRecordZone.ID(zoneName: "SafariPasswords"), + CKRecordZone.ID(zoneName: "Passwords"), CKRecordZone.ID(zoneName: "ProtectedCloudStorage"), CKRecordZone.ID(zoneName: "SecureObjectSync"), CKRecordZone.ID(zoneName: "WiFi"), @@ -100,25 +96,22 @@ class OctagonCKKSConfigurationTestsPolicyEnabled: OctagonTestsBase { #if !os(tvOS) let expected = Set([ - "ApplePay", - "Applications", - "AutoUnlock", - // Octagon: create final policy for CKKS4All - //"Backstop", - // Cuttlefish: remove Safari prefix from view names - "SafariCreditCards", - "DevicePairing", - "Engram", - "Health", - "Home", - "LimitedPeersAllowed", - "Manatee", - // Cuttlefish: remove Safari prefix from view names - "SafariPasswords", - "ProtectedCloudStorage", - "SecureObjectSync", - "WiFi", - ]) + "ApplePay", + "Applications", + "AutoUnlock", + "Backstop", + "CreditCards", + "DevicePairing", + "Engram", + "Health", + "Home", + "LimitedPeersAllowed", + "Manatee", + "Passwords", + "ProtectedCloudStorage", + "SecureObjectSync", + "WiFi", + ]) #else let expected = Set(["LimitedPeersAllowed", "Home", diff --git a/keychain/ot/tests/octagon/OctagonTests+CloudKitAccount.swift b/keychain/ot/tests/octagon/OctagonTests+CloudKitAccount.swift index fd35bd09..812520c6 100644 --- a/keychain/ot/tests/octagon/OctagonTests+CloudKitAccount.swift +++ b/keychain/ot/tests/octagon/OctagonTests+CloudKitAccount.swift @@ -42,8 +42,8 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) - // And CKKS should be in 'loggedout' - assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + // And CKKS shouldn't be spun up + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views before CK login") // Account sign in occurs let newAltDSID = UUID().uuidString @@ -188,7 +188,7 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForHSA2, within: 10 * NSEC_PER_SEC) self.assertNoAccount(context: self.cuttlefishContext) - self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views in an SA account") // On CK account sign-out, Octagon should stay in 'wait for hsa2': if there's no HSA2, we don't actually care about the CK account status self.accountStatus = .noAccount @@ -202,7 +202,7 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) self.assertNoAccount(context: self.cuttlefishContext) - self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views in an SA account") } func testSAtoHSA2PromotionWithoutCloudKit() throws { @@ -351,15 +351,16 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { let statusexpectation = self.expectation(description: "trust status returns") let configuration = OTOperationConfiguration() configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - self.cuttlefishContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _ in + self.cuttlefishContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _, error in XCTAssertEqual(.noCloudKitAccount, egoStatus, "cliqueStatus should be 'no cloudkit account'") + XCTAssertNil(error, "should have no error fetching status") statusexpectation.fulfill() } self.wait(for: [statusexpectation], timeout: 10) self.assertNoAccount(context: self.cuttlefishContext) - self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views") } func testStatusRPCsWithUnknownCloudKitAccount() throws { @@ -367,7 +368,7 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { let statusexpectation = self.expectation(description: "trust status returns") let configuration = OTOperationConfiguration() configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - self.cuttlefishContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _ in + self.cuttlefishContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _, _ in XCTAssertTrue([.absent].contains(egoStatus), "Self peer should be in the 'absent' state") statusexpectation.fulfill() } @@ -425,6 +426,63 @@ class OctagonCloudKitAccountTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: self.cuttlefishContext) self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) + + // Let Octagon know about the account status, so test teardown is fast + self.startCKAccountStatusMock() + } + + func testReceiveOctagonAPICallBeforeCKAccountNotification() throws { + // Device is signed out of everything + self.mockAuthKit.altDSID = nil + self.accountStatus = .noAccount + self.startCKAccountStatusMock() + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + // With no account, Octagon should go directly into 'NoAccount' + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views before CK login") + + // Account sign in occurs + let newAltDSID = UUID().uuidString + self.mockAuthKit.altDSID = newAltDSID + XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") + + // Octagon should go into 'wait for cloudkit account' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitingForCloudKitAccount, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) + + // RPCs should fail, since CK is not present + let fetchViableFailureExpectation = self.expectation(description: "fetchViableBottles callback occurs") + self.cuttlefishContext.rpcFetchAllViableBottles { _, _, error in + XCTAssertNotNil(error, "should be an error fetching viable bottles before CK is ready") + + if let nserror = error as NSError? { + XCTAssertEqual(nserror.domain, OctagonErrorDomain, "Error should be from correct domain") + XCTAssertEqual(nserror.code, OctagonError.OTErrorNotSignedIn.rawValue, "Error should indicate no account present") + } else { + XCTFail("Unable to convert error to nserror") + } + fetchViableFailureExpectation.fulfill() + } + self.wait(for: [fetchViableFailureExpectation], timeout: 10) + + // CK signs in, but we aren't yet notified about it + self.accountStatus = .available + + // RPCs should cause Octagon to recheck the CK account status and wake up + // In particular, fetching all viable bottles should succeed, instead of erroring with 'no CK account' + let fetchViableExpectation = self.expectation(description: "fetchViableBottles callback occurs") + self.cuttlefishContext.rpcFetchAllViableBottles { _, _, error in + XCTAssertNil(error, "should be no error fetching viable bottles") + fetchViableExpectation.fulfill() + } + self.wait(for: [fetchViableExpectation], timeout: 10) + + // With no SOS and no CDP, Octagon should wait for enablement + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) } } diff --git a/keychain/ot/tests/octagon/OctagonTests+CoreFollowUp.swift b/keychain/ot/tests/octagon/OctagonTests+CoreFollowUp.swift index b639f749..810b8e41 100644 --- a/keychain/ot/tests/octagon/OctagonTests+CoreFollowUp.swift +++ b/keychain/ot/tests/octagon/OctagonTests+CoreFollowUp.swift @@ -22,8 +22,9 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -85,8 +86,9 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -118,7 +120,7 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { // Since SOS isn't around to help, Octagon should post a CFU #if os(tvOS) - XCTAssertEqual(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), false, "Should not have posted a CFU on aTV (due to having no peers to join)") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should not have posted a CFU on aTV (due to having no peers to join)") #else XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should have posted an repair CFU, as SOS can't help") #endif @@ -150,8 +152,9 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -229,8 +232,9 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -323,12 +327,12 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { // Now, a mac appears! macs cannot fix apple TVs. let mac = self.manager.context(forContainerName: OTCKContainerName, - contextID: "asdf", - sosAdapter: self.mockSOSAdapter, - authKitAdapter: self.mockAuthKit2, - lockStateTracker: self.lockStateTracker, - accountStateTracker: self.accountStateTracker, - deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iMac7,1", deviceName: "test-mac", serialNumber: "456", osVersion: "macOS (fake version)")) + contextID: "asdf", + sosAdapter: self.mockSOSAdapter, + authKitAdapter: self.mockAuthKit2, + lockStateTracker: self.lockStateTracker, + accountStateTracker: self.accountStateTracker, + deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iMac7,1", deviceName: "test-mac", serialNumber: "456", osVersion: "macOS (fake version)")) mac.startOctagonStateMachine() let resetAndEstablishExpectation = self.expectation(description: "resetAndEstablishExpectation returns") @@ -429,7 +433,7 @@ class OctagonCoreFollowUpTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) #if os(tvOS) - XCTAssertEqual(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), false, "Should not have posted a CFU on aTV (due to having no peers to join)") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should not have posted a CFU on aTV (due to having no peers to join)") #else XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "should have posted an repair CFU, as SOS can't help") #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+DeviceList.swift b/keychain/ot/tests/octagon/OctagonTests+DeviceList.swift index 110b7e30..a0744ad9 100644 --- a/keychain/ot/tests/octagon/OctagonTests+DeviceList.swift +++ b/keychain/ot/tests/octagon/OctagonTests+DeviceList.swift @@ -80,7 +80,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // Then peer2 drops off the device list. Peer 1 should distrust peer2. let updateTrustExpectation = self.expectation(description: "updateTrust") @@ -102,7 +102,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .excludes, target: peer2ID)), - "peer 1 should distrust peer 2 after update") + "peer 1 should distrust peer 2 after update") } func testNumberOfPeersInModel() throws { @@ -148,7 +148,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // Then peer2 drops off the device list. Peer 1 should distrust peer2. let updateTrustExpectation = self.expectation(description: "updateTrust") @@ -194,7 +194,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") self.assertMIDList(context: self.cuttlefishContext, allowed: self.mockAuthKit.currentDeviceList(), disallowed: Set(), @@ -231,7 +231,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") } func testRemoveSelfWhenRemovedFromOnlySelfList() throws { @@ -351,7 +351,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // We receive a 'remove' push for peer2's ID, but for the wrong DSID. The peer should do nothing useful. self.fakeCuttlefishServer.updateListener = { request in @@ -365,7 +365,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") self.assertMIDList(context: self.cuttlefishContext, allowed: self.mockAuthKit.currentDeviceList(), @@ -390,7 +390,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // We receive a 'add' push for a new ID, but for the wrong DSID. The peer should do nothing useful. self.fakeCuttlefishServer.updateListener = { request in @@ -405,7 +405,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // newMachineID should be on no lists self.assertMIDList(context: self.cuttlefishContext, @@ -457,7 +457,7 @@ class OctagonDeviceListTests: OctagonTestsBase { // machinemo.modified = Date(timeIntervalSinceNow: -60 * 60 * TimeInterval(72)) XCTAssertEqual(machinemo.status, Int64(TPMachineIDStatus.unknown.rawValue), "peer2's MID entry should be 'unknown'") - } + } XCTAssertTrue(foundPeer2, "Should have found an entry for peer2") try! container.moc.save() @@ -490,7 +490,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") // Then peer2 arrives on the device list. Peer 1 should update its dynamic info to no longer have a disposition for peer2. let updateTrustExpectation = self.expectation(description: "updateTrust") @@ -575,7 +575,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.mockAuthKit.otherDevices.removeAll() self.mockAuthKit.isDemoAccount = true self.mockAuthKit2.isDemoAccount = true - + XCTAssertEqual(self.mockAuthKit.currentDeviceList(), Set([self.mockAuthKit.currentMachineID]), "AuthKit should have exactly one device on the list") XCTAssertFalse(self.mockAuthKit.currentDeviceList().contains(self.mockAuthKit2.currentMachineID), "AuthKit should not already have device 2 on the list") @@ -591,7 +591,7 @@ class OctagonDeviceListTests: OctagonTestsBase { self.verifyDatabaseMocks() XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") self.assertMIDList(context: self.cuttlefishContext, allowed: self.mockAuthKit.currentDeviceList(), disallowed: Set(), @@ -628,9 +628,102 @@ class OctagonDeviceListTests: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), - "peer 1 should trust peer 2 after update") + "peer 1 should trust peer 2 after update") } + static func makeAuthKitError(code: Int) -> NSError { + let authkitError = CKPrettyError(domain: AKAppleIDAuthenticationErrorDomain, + code: code, + userInfo: nil) + + return authkitError + } + + func testRemovePeerWhenRemovedFromDeviceListAndAuthkitThrowsError() throws { + self.startCKAccountStatusMock() + + XCTAssert(self.mockAuthKit.currentDeviceList().contains(self.mockAuthKit2.currentMachineID), "AuthKit should already have device 2 on the list") + + let peer2ContextID = "joiner" + let peer1ID = self.assertResetAndBecomeTrustedInDefaultContext() + + let joiningContext = self.makeInitiatorContext(contextID: peer2ContextID, authKitAdapter: self.mockAuthKit2) + let peer2ID = self.assertJoinViaEscrowRecovery(joiningContext: joiningContext, sponsor: self.cuttlefishContext) + + // Now, tell peer1 about the change. It will trust the peer and upload some TLK shares + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), + "peer 1 should trust peer 2 after update") + + // Then peer2 drops off the device list. Peer 1 should distrust peer2. + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + XCTAssertTrue(request.hasDynamicInfoAndSig, "updateTrust request should have a dynamic info") + let newDynamicInfo = TPPeerDynamicInfo(data: request.dynamicInfoAndSig.peerDynamicInfo, + sig: request.dynamicInfoAndSig.sig) + XCTAssertNotNil(newDynamicInfo, "should be able to make a dynamic info from protobuf") + + XCTAssertTrue(!(newDynamicInfo?.includedPeerIDs.contains(peer2ID) ?? true), "peer1 should no longer trust peer2") + updateTrustExpectation.fulfill() + return nil + } + + self.mockAuthKit.removeAndSendNotification(machineID: try! self.mockAuthKit2.machineID()) + + self.wait(for: [updateTrustExpectation], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .excludes, target: peer2ID)), + "peer 1 should distrust peer 2 after update") + + self.assertEnters(context: joiningContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + //peer2 attempts to update trusted device list but hits an authkit error + //try bottle restore again + joiningContext.startOctagonStateMachine() + + let sponsorPeerID = try self.cuttlefishContext.accountMetadataStore.loadOrCreateAccountMetadata().peerID + XCTAssertNotNil(sponsorPeerID, "sponsorPeerID should not be nil") + let entropy = try self.loadSecret(label: sponsorPeerID!) + XCTAssertNotNil(entropy, "entropy should not be nil") + + let altDSID = try joiningContext.authKitAdapter.primaryiCloudAccountAltDSID() + XCTAssertNotNil(altDSID, "Should have an altDSID") + + let bottles = self.fakeCuttlefishServer.state.bottles.filter { $0.peerID == sponsorPeerID } + XCTAssertEqual(bottles.count, 1, "Should have a single bottle for the approving peer") + let bottle = bottles[0] + + let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") + joiningContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: altDSID) { error in + XCTAssertNil(error, "error should be nil") + joinWithBottleExpectation.fulfill() + } + + self.assertEnters(context: joiningContext, state: OctagonStateInitiatorUpdateDeviceList, within: 10 * NSEC_PER_SEC) + + let authKitError = OctagonDeviceListTests.makeAuthKitError(code: -7026) + self.mockAuthKit2.machineIDFetchErrors = [authKitError] + let updateTrustExpectationPeer2 = self.expectation(description: "updateTrustPeer2") + self.fakeCuttlefishServer.fetchChangesListener = { request in + self.mockAuthKit2.machineIDFetchErrors = [] + updateTrustExpectationPeer2.fulfill() + self.fakeCuttlefishServer.fetchChangesListener = nil + return nil + } + self.wait(for: [updateTrustExpectationPeer2], timeout: 10) + + self.wait(for: [joinWithBottleExpectation], timeout: 10) + + self.assertConsidersSelfTrusted(context: joiningContext) + + self.assertEnters(context: joiningContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + } } #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+ErrorHandling.swift b/keychain/ot/tests/octagon/OctagonTests+ErrorHandling.swift index da28130f..a909284c 100644 --- a/keychain/ot/tests/octagon/OctagonTests+ErrorHandling.swift +++ b/keychain/ot/tests/octagon/OctagonTests+ErrorHandling.swift @@ -1,17 +1,15 @@ #if OCTAGON class OctagonErrorHandlingTests: OctagonTestsBase { - func testEstablishFailedError() throws { self.startCKAccountStatusMock() let establishExpectation = self.expectation(description: "establishExpectation") - self.fakeCuttlefishServer.establishListener = { [unowned self] request in + self.fakeCuttlefishServer.establishListener = { [unowned self] request in self.fakeCuttlefishServer.establishListener = nil - self.fakeCuttlefishServer.establish(request) { - response, error in + self.fakeCuttlefishServer.establish(request) { response, error in XCTAssertNil(error, "should be no error from establish") XCTAssertNotNil(response, "should get a response from establish") // drop the response on the floor @@ -31,7 +29,7 @@ class OctagonErrorHandlingTests: OctagonTestsBase { let establishExpectation = self.expectation(description: "establishExpectation") - self.fakeCuttlefishServer.establishListener = { [unowned self] request in + self.fakeCuttlefishServer.establishListener = { [unowned self] request in self.fakeCuttlefishServer.establishListener = nil establishExpectation.fulfill() @@ -51,7 +49,7 @@ class OctagonErrorHandlingTests: OctagonTestsBase { var t0 = Date.distantPast - self.fakeCuttlefishServer.establishListener = { [unowned self] request in + self.fakeCuttlefishServer.establishListener = { [unowned self] request in self.fakeCuttlefishServer.establishListener = nil establishExpectation.fulfill() @@ -188,8 +186,8 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) self.mockAuthKit.machineIDFetchErrors.append(CKPrettyError(domain: CKErrorDomain, - code: CKError.networkUnavailable.rawValue, - userInfo: [CKErrorRetryAfterKey: 2])) + code: CKError.networkUnavailable.rawValue, + userInfo: [CKErrorRetryAfterKey: 2])) self.sendContainerChange(context: self.cuttlefishContext) @@ -224,8 +222,8 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.lockStateTracker.recheck() self.mockAuthKit.machineIDFetchErrors.append(CKPrettyError(domain: CKErrorDomain, - code: CKError.networkUnavailable.rawValue, - userInfo: [CKErrorRetryAfterKey: 2])) + code: CKError.networkUnavailable.rawValue, + userInfo: [CKErrorRetryAfterKey: 2])) self.sendContainerChange(context: self.cuttlefishContext) @@ -401,7 +399,7 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) // Peer 2 arrives (with a voucher), but is not on the trusted device list let firstPeerID = clique.cliqueMemberIdentifier @@ -473,11 +471,16 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) // And on unlock, it should handle the update + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.aksLockState = false self.lockStateTracker.recheck() self.wait(for: [updateTrustExpectation], timeout: 30) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() } func testCKKSResetRecoverFromCKKSConflict() throws { @@ -492,10 +495,10 @@ class OctagonErrorHandlingTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) do { - let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) - XCTAssertNotNil(clique, "Clique should not be nil") + let clique = OTClique(contextData: self.otcliqueContext) + try clique.establish() } catch { - XCTFail("Shouldn't have errored making new friends: \(error)") + XCTFail("Shouldn't have errored establishing Octagon: \(error)") } // Now, we should be in 'ready', and CKKS should be stuck @@ -537,6 +540,78 @@ class OctagonErrorHandlingTests: OctagonTestsBase { XCTAssertEqual(tlkUUID, (self.keys![zoneID] as? ZoneKeys)?.tlk?.uuid, "TLK should match conflicted version") } } + + func testHandlePeerMissingOnSetUserControllableViews() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + // Another device updates the world, but we don't get the push + let reset = self.makeInitiatorContext(contextID: "reset") + self.assertResetAndBecomeTrusted(context: reset) + + // Now, the original peer sets their view status + #if os(tvOS) + throw XCTSkip("TVs don't set user-controllable views") + #else + + let clique = self.cliqueFor(context: self.cuttlefishContext) + + do { + try clique.setUserControllableViewsSyncStatus(true) + XCTFail("Should be an error setting user-visible sync status") + } catch { + } + + // Octagon should notice that it's been kicked out. + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + #endif // os(tvOS) + } + + func testHandlePeerMissingOnTrustUpdate() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + // Another device joins + let joiner = self.makeInitiatorContext(contextID: "joiner") + self.assertJoinViaEscrowRecovery(joiningContext: joiner, sponsor: self.cuttlefishContext) + + // Now, directly after the default context fetches, another device resets Octagon. + // To simulate this, we reset things in the updateTrust listener. + let reset = self.makeInitiatorContext(contextID: "reset") + + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + reset.startOctagonStateMachine() + + do { + try reset.setCDPEnabled() + self.assertEnters(context: reset, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let arguments = OTConfigurationContext() + arguments.altDSID = try reset.authKitAdapter.primaryiCloudAccountAltDSID() + arguments.context = reset.contextID + arguments.otControl = self.otControl + + let clique = try OTClique.newFriends(withContextData: arguments, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + } + self.assertEnters(context: reset, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + updateTrustExpectation.fulfill() + return FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .updateTrustPeerNotFound) + } + + // Notify Octagon of the join + self.sendContainerChange(context: self.cuttlefishContext) + + self.wait(for: [updateTrustExpectation], timeout: 10) + + // Octagon should notice that it's been kicked out. + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + } } #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift b/keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift new file mode 100644 index 00000000..5f9a4f50 --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonTests+EscrowRecords.swift @@ -0,0 +1,788 @@ +#if OCTAGON + +@objcMembers +class OctagonEscrowRecordTests: OctagonTestsBase { + + func testFetchEscrowRecord() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let entropy = try self.loadSecret(label: clique.cliqueMemberIdentifier!) + XCTAssertNotNil(entropy, "entropy should not be nil") + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords: [OTEscrowRecord] = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 1, "should be 1 escrow record") + let reduced = escrowRecords.compactMap { $0.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + } + + func testViableBottleCachingAfterJoin() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let entropy = try self.loadSecret(label: clique.cliqueMemberIdentifier!) + XCTAssertNotNil(entropy, "entropy should not be nil") + + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in + XCTAssertNil(error, "error should be nil") + joinWithBottleExpectation.fulfill() + } + + self.wait(for: [joinWithBottleExpectation], timeout: 100) + + let dumpCallback = self.expectation(description: "dumpCallback callback occurs") + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + dumpCallback.fulfill() + } + self.wait(for: [dumpCallback], timeout: 10) + + self.verifyDatabaseMocks() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + + //now call fetchviablebottles, we should get the uncached version + let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + fetchUnCachedViableBottlesExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 1) + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + + //now call fetchviablebottles, we should get the cached version + let fetchViableBottlesExpectation = self.expectation(description: "fetch Cached ViableBottles") + fetchViableBottlesExpectation.isInverted = true + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + fetchViableBottlesExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow record") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesExpectation], timeout: 1) + } + + func testCachedEscrowRecordFetch() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let entropy = try self.loadSecret(label: clique.cliqueMemberIdentifier!) + XCTAssertNotNil(entropy, "entropy should not be nil") + + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in + XCTAssertNil(error, "error should be nil") + joinWithBottleExpectation.fulfill() + } + + self.wait(for: [joinWithBottleExpectation], timeout: 100) + + let dumpCallback = self.expectation(description: "dumpCallback callback occurs") + self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + dumpCallback.fulfill() + } + self.wait(for: [dumpCallback], timeout: 10) + + self.verifyDatabaseMocks() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + + //now call fetchviablebottles, we should get the uncached version + let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + fetchUnCachedViableBottlesExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 1) + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + //now call fetchviablebottles, we should get the cached version + let fetchViableBottlesExpectation = self.expectation(description: "fetch Cached ViableBottles") + fetchViableBottlesExpectation.isInverted = true + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + fetchViableBottlesExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesExpectation], timeout: 1) + + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: initiatorContextID) + container.escrowCacheTimeout = 1 + + //sleep to invalidate the cache + sleep(1) + + //now call fetchviablebottles, we should get the uncached version + let uncachedViableBottlesFetchExpectation = self.expectation(description: "fetch Uncached ViableBottles") + let fetchBottlesFromCuttlefishFetchExpectation = self.expectation(description: "fetch bottles from cuttlefish expectation") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + fetchBottlesFromCuttlefishFetchExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + uncachedViableBottlesFetchExpectation.fulfill() + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchBottlesFromCuttlefishFetchExpectation], timeout: 10) + self.wait(for: [uncachedViableBottlesFetchExpectation], timeout: 10) + } + + func testForcedEscrowRecordFetch() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + bottlerotcliqueContext.overrideEscrowCache = false + + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let entropy = try self.loadSecret(label: clique.cliqueMemberIdentifier!) + XCTAssertNotNil(entropy, "entropy should not be nil") + + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: bottlerContext) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") + self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in + XCTAssertNil(error, "error should be nil") + joinWithBottleExpectation.fulfill() + } + + self.wait(for: [joinWithBottleExpectation], timeout: 100) + + self.verifyDatabaseMocks() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + + //now call fetchviablebottles, we should get records from cuttlefish + let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + fetchUnCachedViableBottlesExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 1) + + //set the override to force an escrow record fetch + bottlerotcliqueContext.overrideEscrowCache = true + + //now call fetchviablebottles, we should get records from cuttlefish + let fetchViableBottlesExpectation = self.expectation(description: "fetch forced ViableBottles") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + fetchViableBottlesExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 2, "should be 2 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesExpectation], timeout: 10) + } + + func testSignInWithEscrowPrecachingEnabled() throws { + self.startCKAccountStatusMock() + + let contextName = OTDefaultContext + let containerName = OTCKContainerName + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + // Tell SOS that it is absent, so we don't enable CDP on bringup + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + //expect fetch escrow record fetch + let fetchViableBottlesExpectation = self.expectation(description: "fetch Cached ViableBottles") + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + fetchViableBottlesExpectation.fulfill() + return nil + } + + // Device is signed out + self.mockAuthKit.altDSID = nil + self.mockAuthKit.hsa2 = false + + // With no account, Octagon should go directly into 'NoAccount' + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + let newAltDSID = UUID().uuidString + self.mockAuthKit.altDSID = newAltDSID + self.mockAuthKit.hsa2 = true + XCTAssertNoThrow(try self.cuttlefishContext.accountAvailable(newAltDSID), "Sign-in shouldn't error") + + let signInExpectation = self.expectation(description: "signing in expectation") + + self.manager.sign(in: newAltDSID, container: containerName, context: contextName) { error in + XCTAssertNil(error, "error should not be nil") + signInExpectation.fulfill() + } + + self.wait(for: [signInExpectation], timeout: 10) + self.wait(for: [fetchViableBottlesExpectation], timeout: 10) + } + + func testLegacyEscrowRecordFetch() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + OctagonSetPlatformSupportsSOS(true) + + self.startCKAccountStatusMock() + + let initiatorContextID = "joiner" + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = OTDefaultContext + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + self.mockAuthKit.hsa2 = true + bottlerotcliqueContext.otControl = self.otControl + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") + + // SOS TLK shares will be uploaded after the establish + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + self.verifyDatabaseMocks() + + let joinerContext = self.makeInitiatorContext(contextID: initiatorContextID) + self.assertJoinViaEscrowRecovery(joiningContext: joinerContext, sponsor: self.cuttlefishContext) + + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: OTDefaultContext) + + //now call fetchviablebottles, we should get the uncached version + let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") + + self.fakeCuttlefishServer.injectLegacyEscrowRecords = true + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + fetchUnCachedViableBottlesExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + + XCTAssertEqual(escrowRecords.count, 3, "should be 3 escrow records") + let recordsWithBottles = escrowRecords.filter { $0!.escrowInformationMetadata.bottleId != "" } + XCTAssertEqual(recordsWithBottles.count, 2, "should be 2 escrow records with a bottleID") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 1) + + //now call fetchviablebottles, we should get the cached version + let fetchViableBottlesExpectation = self.expectation(description: "fetch Cached ViableBottles") + fetchViableBottlesExpectation.isInverted = true + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + let legacy = container.containerMO.legacyEscrowRecords as! Set + let partial = container.containerMO.partiallyViableEscrowRecords as! Set + let full = container.containerMO.fullyViableEscrowRecords as! Set + + XCTAssertEqual(legacy.count, 1, "legacy escrowRecords should contain 1 record") + XCTAssertEqual(partial.count, 1, "partially viable escrowRecords should contain 1 record") + XCTAssertEqual(full.count, 1, "fully viable escrowRecords should contain 1 record") + + fetchViableBottlesExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + + XCTAssertEqual(escrowRecords.count, 3, "should be 3 escrow record") + let recordsWithBottles = escrowRecords.filter { $0!.escrowInformationMetadata.bottleId != "" } + XCTAssertEqual(recordsWithBottles.count, 2, "should be 2 escrow records with a bottleID") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesExpectation], timeout: 1) + + //check cache is empty after escrow fetch timeout expires + container.escrowCacheTimeout = 1 + sleep(1) + + //now call fetchviablebottles, we should get the uncached version, check there's 0 cached records + let fetchViableBottlesAfterExpiredTimeoutExpectation = self.expectation(description: "fetch Cached ViableBottles expectaiton after timeout") + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") + XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") + XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") + + fetchViableBottlesAfterExpiredTimeoutExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 3, "should be 3 escrow record") + let recordsWithBottles = escrowRecords.filter { $0!.escrowInformationMetadata.bottleId != "" } + XCTAssertEqual(recordsWithBottles.count, 2, "should be 2 escrow records with a bottleID") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesAfterExpiredTimeoutExpectation], timeout: 10) + } + + func testEmptyEscrowRecords() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + self.fakeCuttlefishServer.includeEscrowRecords = false + self.fakeCuttlefishServer.injectLegacyEscrowRecords = false + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: initiatorContextID) + + let fetchViableBottlesAfterExpiredTimeoutExpectation = self.expectation(description: "fetch Cached ViableBottles expectaiton after timeout") + + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + container.moc.performAndWait { + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") + XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") + XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") + } + fetchViableBottlesAfterExpiredTimeoutExpectation.fulfill() + return nil + } + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + XCTAssertEqual(escrowRecordDatas.count, 0, "should be 0 escrow records") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesAfterExpiredTimeoutExpectation], timeout: 10) + container.moc.performAndWait { + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") + XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") + XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") + } + } + + func testRemoveEscrowCache() throws { + OctagonSetOptimizationEnabled(true) + OctagonSetEscrowRecordFetchEnabled(true) + + let initiatorContextID = "initiator-context-id" + let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) + + bottlerContext.startOctagonStateMachine() + let ckacctinfo = CKAccountInfo() + ckacctinfo.accountStatus = .available + ckacctinfo.hasValidCredentials = true + ckacctinfo.accountPartition = .production + + bottlerContext.cloudkitAccountStateChange(nil, to: ckacctinfo) + XCTAssertNoThrow(try bottlerContext.setCDPEnabled()) + self.assertEnters(context: bottlerContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + let bottlerotcliqueContext = OTConfigurationContext() + bottlerotcliqueContext.context = initiatorContextID + bottlerotcliqueContext.dsid = "1234" + bottlerotcliqueContext.altDSID = self.mockAuthKit.altDSID! + bottlerotcliqueContext.otControl = self.otControl + do { + clique = try OTClique.newFriends(withContextData: bottlerotcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: bottlerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: bottlerContext) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords: [OTEscrowRecord] = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 1, "should be 1 escrow record") + let reduced = escrowRecords.compactMap { $0.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + + let removeExpectation = self.expectation(description: "remove expectation") + self.manager.invalidateEscrowCache(OTCKContainerName, contextID: initiatorContextID) { error in + XCTAssertNil(error, "error should not be nil") + removeExpectation.fulfill() + } + self.wait(for: [removeExpectation], timeout: 10) + + let container = try self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: initiatorContextID) + + let fetchViableBottlesAfterCacheRemovalExpectation = self.expectation(description: "fetchViableBottles expectation after cache removal") + self.fakeCuttlefishServer.fetchViableBottlesListener = { request in + self.fakeCuttlefishServer.fetchViableBottlesListener = nil + XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set, [], "legacy escrowRecords should be empty") + XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set, [], "partially viable escrowRecords should be empty") + XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set, [], "fully viable escrowRecords should be empty") + + fetchViableBottlesAfterCacheRemovalExpectation.fulfill() + return nil + } + + do { + let escrowRecordDatas = try OTClique.fetchEscrowRecordsInternal(bottlerotcliqueContext) + let escrowRecords = escrowRecordDatas.map { OTEscrowRecord(data: $0) } + XCTAssertNotNil(escrowRecords, "escrowRecords should not be nil") + XCTAssertEqual(escrowRecords.count, 1, "should be 1 escrow records") + let reduced = escrowRecords.compactMap { $0!.escrowInformationMetadata.bottleId } + XCTAssert(reduced.contains(bottle.bottleID), "The bottle we're about to restore should be viable") + } catch { + XCTFail("Shouldn't have errored fetching escrow records: \(error)") + throw error + } + self.wait(for: [fetchViableBottlesAfterCacheRemovalExpectation], timeout: 10) + + } +} + +#endif diff --git a/keychain/ot/tests/octagon/OctagonTests+EscrowRecovery.swift b/keychain/ot/tests/octagon/OctagonTests+EscrowRecovery.swift index d79263f8..37698b05 100644 --- a/keychain/ot/tests/octagon/OctagonTests+EscrowRecovery.swift +++ b/keychain/ot/tests/octagon/OctagonTests+EscrowRecovery.swift @@ -51,12 +51,6 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { self.startCKAccountStatusMock() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - // Try to enforce that that CKKS doesn't know about the key hierarchy until Octagon asks it - self.holdCloudKitFetches() - - // Note: CKKS will want to upload a TLKShare for its self - self.assertAllCKKSViewsUpload(tlkShares: 1) - // Before you call joinWithBottle, you need to call fetchViableBottles. let fetchViableExpectation = self.expectation(description: "fetchViableBottles callback occurs") self.cuttlefishContext.rpcFetchAllViableBottles { viable, _, error in @@ -72,9 +66,6 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { joinWithBottleExpectation.fulfill() } - sleep(1) - self.releaseCloudKitFetchHold() - self.wait(for: [joinWithBottleExpectation], timeout: 100) let dumpCallback = self.expectation(description: "dumpCallback callback occurs") @@ -93,7 +84,8 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { self.verifyDatabaseMocks() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) } func testBottleRestoreEntersOctagonReady() throws { @@ -254,8 +246,8 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { let differentRestoreExpectation = self.expectation(description: "different restore returns") differentDevice.startOctagonStateMachine() differentDevice.join(withBottle: bottle.bottleID, - entropy: entropy!, - bottleSalt: self.otcliqueContext.altDSID!) { error in + entropy: entropy!, + bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") differentRestoreExpectation.fulfill() } @@ -280,8 +272,8 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { restoreContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in - XCTAssertNil(error, "error should be nil") - restoreExpectation.fulfill() + XCTAssertNil(error, "error should be nil") + restoreExpectation.fulfill() } self.wait(for: [restoreExpectation], timeout: 10) @@ -468,7 +460,8 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { // We will upload a new TLK for the new peer self.assertAllCKKSViewsUpload(tlkShares: 1) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() self.sendContainerChangeWaitForFetch(context: initiatorContext) bottleIDs = try OTClique.findOptimalBottleIDs(withContextData: self.otcliqueContext) @@ -608,7 +601,6 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { fetchEscrowContentsException.fulfill() } self.wait(for: [fetchEscrowContentsException], timeout: 10) - } catch { XCTFail("failed to reset clique: \(error)") } @@ -901,12 +893,12 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { machineID: "c-machine-id", otherDevices: [self.mockAuthKit.currentMachineID, deviceBmockAuthKit.currentMachineID]) let restoreContext = self.manager.context(forContainerName: OTCKContainerName, - contextID: "restoreContext", - sosAdapter: OTSOSMissingAdapter(), - authKitAdapter: restoremockAuthKit, - lockStateTracker: self.lockStateTracker, - accountStateTracker: self.accountStateTracker, - deviceInformationAdapter: self.makeInitiatorDeviceInfoAdapter()) + contextID: "restoreContext", + sosAdapter: OTSOSMissingAdapter(), + authKitAdapter: restoremockAuthKit, + lockStateTracker: self.lockStateTracker, + accountStateTracker: self.accountStateTracker, + deviceInformationAdapter: self.makeInitiatorDeviceInfoAdapter()) restoreContext.startOctagonStateMachine() let newOTCliqueContext = OTConfigurationContext() @@ -969,6 +961,7 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { } func testCachedBottleFetch() throws { + OctagonSetOptimizationEnabled(false) let initiatorContextID = "initiator-context-id" let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) @@ -1009,15 +1002,12 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { let bottle = self.fakeCuttlefishServer.state.bottles[0] - self.cuttlefishContext.startOctagonStateMachine() - self.startCKAccountStatusMock() - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - // Try to enforce that that CKKS doesn't know about the key hierarchy until Octagon asks it self.holdCloudKitFetches() - // Note: CKKS will want to upload a TLKShare for its self - self.assertAllCKKSViewsUpload(tlkShares: 1) + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in @@ -1046,7 +1036,7 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { self.verifyDatabaseMocks() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) //now call fetchviablebottles, we should get the uncached version let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") @@ -1061,6 +1051,10 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { self.cuttlefishContext.rpcFetchAllViableBottles { viable, _, error in XCTAssertNil(error, "should be no error fetching viable bottles") XCTAssert(viable?.contains(bottle.bottleID) ?? false, "The bottle we're about to restore should be viable") + XCTAssertEqual(viable?.count, 2, "There should be 2 bottles") + XCTAssertNotEqual(viable?[0], "", "Bottle should not be empty") + XCTAssertNotEqual(viable?[1], "", "Bottle should not be empty") + FetchAllViableBottles.fulfill() } self.wait(for: [FetchAllViableBottles], timeout: 10) @@ -1095,6 +1089,7 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { } func testViableBottleCachingAfterJoin() throws { + OctagonSetOptimizationEnabled(false) let initiatorContextID = "initiator-context-id" let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID) @@ -1140,21 +1135,12 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - // Try to enforce that that CKKS doesn't know about the key hierarchy until Octagon asks it - self.holdCloudKitFetches() - - // Note: CKKS will want to upload a TLKShare for its self - self.assertAllCKKSViewsUpload(tlkShares: 1) - let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") joinWithBottleExpectation.fulfill() } - sleep(1) - self.releaseCloudKitFetchHold() - self.wait(for: [joinWithBottleExpectation], timeout: 100) let dumpCallback = self.expectation(description: "dumpCallback callback occurs") @@ -1173,7 +1159,8 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { self.verifyDatabaseMocks() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) //now call fetchviablebottles, we should get the uncached version let fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") @@ -1266,21 +1253,12 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { self.startCKAccountStatusMock() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - // Try to enforce that that CKKS doesn't know about the key hierarchy until Octagon asks it - self.holdCloudKitFetches() - - // Note: CKKS will want to upload a TLKShare for its self - self.assertAllCKKSViewsUpload(tlkShares: 1) - let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs") self.cuttlefishContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: self.otcliqueContext.altDSID!) { error in XCTAssertNil(error, "error should be nil") joinWithBottleExpectation.fulfill() } - sleep(1) - self.releaseCloudKitFetchHold() - self.wait(for: [joinWithBottleExpectation], timeout: 100) var egoPeerID: String? @@ -1302,7 +1280,8 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { self.verifyDatabaseMocks() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) let bottles: [Bottle] = self.fakeCuttlefishServer.state.bottles var bottleToExclude: String? @@ -1333,8 +1312,9 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { self.wait(for: [FetchAllViableBottles], timeout: 10) self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 10) - //now call fetchviablebottles, we should get the uncached version - fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch UnCached ViableBottles") + //now call fetchviablebottles, we should get the cached version + fetchUnCachedViableBottlesExpectation = self.expectation(description: "fetch cached ViableBottles") + fetchUnCachedViableBottlesExpectation.isInverted = true self.fakeCuttlefishServer.fetchViableBottlesListener = { request in self.fakeCuttlefishServer.fetchViableBottlesListener = nil @@ -1352,11 +1332,11 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { FetchAllViableBottles.fulfill() } self.wait(for: [FetchAllViableBottles], timeout: 10) - self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 10) + self.wait(for: [fetchUnCachedViableBottlesExpectation], timeout: 1) } func testRecoverTLKSharesSendByPeers() throws { - // First, set up the world: two peers, one of which has sent TLKs tto itself and the other + // First, set up the world: two peers, one of which has sent TLKs to itself and the other let noSelfSharesContext = self.makeInitiatorContext(contextID: "noShares", authKitAdapter: self.mockAuthKit2) let allSharesContext = self.makeInitiatorContext(contextID: "allShares", authKitAdapter: self.mockAuthKit3) @@ -1368,7 +1348,7 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { self.assertEnters(context: noSelfSharesContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: noSelfSharesPeerID, opinion: .trusts, target: allSharesPeerID)), - "noShares should trust allShares") + "noShares should trust allShares") XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: noSelfSharesPeerID, opinion: .trusts, target: noSelfSharesPeerID)), "No shares should trust itself") @@ -1376,17 +1356,123 @@ class OctagonEscrowRecoveryTests: OctagonTestsBase { try self.putSelfTLKSharesInCloudKit(context: allSharesContext) try self.putAllTLKSharesInCloudKit(to: noSelfSharesContext, from: allSharesContext) - try self.ckksZones.forEach { zone in - XCTAssertFalse(try self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: noSelfSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should not have self shares for noSelfShares") - XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: allSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should have a share for noSelfShares from allShares") + self.ckksZones.forEach { zone in + XCTAssertFalse(self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: noSelfSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should not have self shares for noSelfShares") + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: allSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should have a share for noSelfShares from allShares") } // Now, recover from noSelfShares - self.assertAllCKKSViewsUpload(tlkShares: 1) self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: noSelfSharesContext) // And CKKS should enter ready! self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testRecoverTLKSharesSentByPeersAfterCKKSFetchTimeout() throws { + // First, set up the world: two peers, one of which has sent TLKs to itself and the other + let noSelfSharesContext = self.makeInitiatorContext(contextID: "noShares", authKitAdapter: self.mockAuthKit2) + let allSharesContext = self.makeInitiatorContext(contextID: "allShares", authKitAdapter: self.mockAuthKit3) + + self.startCKAccountStatusMock() + let noSelfSharesPeerID = self.assertResetAndBecomeTrusted(context: noSelfSharesContext) + let allSharesPeerID = self.assertJoinViaEscrowRecovery(joiningContext: allSharesContext, sponsor: noSelfSharesContext) + + self.sendContainerChangeWaitForFetch(context: noSelfSharesContext) + self.assertEnters(context: noSelfSharesContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: noSelfSharesPeerID, opinion: .trusts, target: allSharesPeerID)), + "noShares should trust allShares") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: noSelfSharesPeerID, opinion: .trusts, target: noSelfSharesPeerID)), + "No shares should trust itself") + + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: allSharesContext) + try self.putAllTLKSharesInCloudKit(to: noSelfSharesContext, from: allSharesContext) + + self.ckksZones.forEach { zone in + XCTAssertFalse(self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: noSelfSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should not have self shares for noSelfShares") + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: allSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should have a share for noSelfShares from allShares") + } + + // Simulate CKKS fetches taking forever. In practice, this is caused by many round-trip fetches to CK happening over minutes. + self.holdCloudKitFetches() + + self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: noSelfSharesContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateFetch, within: 10 * NSEC_PER_SEC) + + // now, let CKKS fetch and become ready + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.releaseCloudKitFetchHold() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testJoinWithBottleCreatedBeforeSignin() throws { + // A remote device creates the keys before CKKS starts up at all + self.putFakeKeyHierarchiesInCloudKit() + + self.startCKAccountStatusMock() + + let remote = self.makeInitiatorContext(contextID: "remote") + let remotePeerID = self.assertResetAndBecomeTrusted(context: remote) + + // Note that depending on when CKKS starts up, it may or may not have received this in its initial fetch. But, Octagon should force a fetch during signin anyway! + try self.putSelfTLKSharesInCloudKit(context: remote) + + let entropy = try self.loadSecret(label: remotePeerID) + XCTAssertNotNil(entropy, "entropy should not be nil") + + self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: remote) + + self.verifyDatabaseMocks() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testJoinWithBottleCreatedAfterInitialFetch() throws { + // Our local machine signs into CloudKit, and becomes untrusted + + self.startCKAccountStatusMock() + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC) + + // Now, another device comes along and performs an establish + let remote = self.makeInitiatorContext(contextID: "remote") + let remotePeerID = self.assertResetAndBecomeTrusted(context: remote) + + let entropy = try self.loadSecret(label: remotePeerID) + XCTAssertNotNil(entropy, "entropy should not be nil") + + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: remote) + + let bottle = self.fakeCuttlefishServer.state.bottles[0] + + // And now our local machine is told to restore from the newly-joined peer + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + self.otcliqueContext.sbd = OTMockSecureBackup(bottleID: bottle.bottleID, entropy: entropy) + + let newClique: OTClique + do { + newClique = try OTClique.performEscrowRecovery(withContextData: self.otcliqueContext, escrowArguments: [:]) + XCTAssertNotNil(newClique, "newClique should not be nil") + } catch { + XCTFail("Shouldn't have errored recovering: \(error)") + throw error + } + + self.verifyDatabaseMocks() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) } } diff --git a/keychain/ot/tests/octagon/OctagonTests+EscrowTestVectors.swift b/keychain/ot/tests/octagon/OctagonTests+EscrowTestVectors.swift new file mode 100644 index 00000000..ee1b70a9 --- /dev/null +++ b/keychain/ot/tests/octagon/OctagonTests+EscrowTestVectors.swift @@ -0,0 +1,1872 @@ +#if OCTAGON + + let accountInfoWithInfoSample = """ + + + + + SecureBackupAccountIsHighSecurity + + SecureBackupAlliCDPRecords + + + SecureBackupEscrowDate + 2020-01-31T03:07:40Z + SecureBackupRemainingAttempts + 10 + encodedMetadata + YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ== + label + com.apple.icdp.record + metadata + + BackupKeybagDigest + + yFGtyxY2ZzDt0j/26GkNSmrgVnY= + + ClientMetadata + + SecureBackupMetadataTimestamp + 2020-01-31 03:07:40 + SecureBackupNumericPassphraseLength + 6 + SecureBackupUsesComplexPassphrase + + SecureBackupUsesNumericPassphrase + + device_color + 1 + device_enclosure_color + 1 + device_mid + yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X + device_model + iPhone 8 Plus + device_model_class + iPhone + device_model_version + iPhone10,5 + device_name + iPhone + device_platform + 1 + + SecureBackupUsesMultipleiCSCs + + bottleID + DD5E3F9F-3702-4789-8ACF-2D28BC86A94C + build + 18A214 + com.apple.securebackup.timestamp + 2020-01-31 03:07:40 + escrowedSPKI + + MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC + Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b + 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj + Ug+fyh0c0xABOXt2Kdup7IYTGrzn + + peerInfo + + MIIErjGCBGEwFAwPQ29uZmxpY3RWZXJzaW9uAgEDMCsM + D0FwcGxpY2F0aW9uRGF0ZQQYGBYyMDIwMDEzMDIyNDEy + Ni4yODAwNTdaMFUMEFB1YmxpY1NpZ25pbmdLZXkEQQTl + vn18gJwjGum8v3Chn9Yh5HM/VRLGuq6HAV4KyxlUm+w8 + uF80+32tY3/l9nKOmU61691beekwSWcfF+mDTGPrMFgM + D0FwcGxpY2F0aW9uVXNpZwRFMEMCIGOIXWe83FnflHu+ + yShdjivfTaPDFHvX+RYNgMy74iSnAh9OHeQzmDchZOi0 + 81lbhw/9rjEe8wEmozXX126RUOe/MHAMDURldmljZUdl + c3RhbHQxXzATDAlNb2RlbE5hbWUMBmlQaG9uZTATDAlP + U1ZlcnNpb24MBjE4QTIxNDAWDAxDb21wdXRlck5hbWUM + BmlQaG9uZTAbDBZNZXNzYWdlUHJvdG9jb2xWZXJzaW9u + AgEAMHwMF09jdGFnb25QdWJsaWNTaWduaW5nS2V5BGEE + oLohYY3GpRSv20AT67jLJ1s2dKr+1bT8JoY23QkCeJgj + GNb+vutEQhLFjLPsENtNE7+NA7wgac0QAXLDO9H/LbpN + UP8DF1Q0NpFX4JiFZqG876jS8HEgR6VOOJzhJzUZMH8M + Gk9jdGFnb25QdWJsaWNFbmNyeXB0aW9uS2V5BGEEDRnS + sPQ/mTEl5dmMEYnQYhcm9hiPzBnQ0ghQzb70auYoPbCR + xjCoG7MCpbb+4JGM4L74OdbJZJbTtHeZ0JtCbqo93ZyI + fULWz131HsOyxowTSSI9yDiPAyXZz6nRnnvnMIIB+AwQ + VjJEaWN0aW9uYXJ5RGF0YQSCAeIxggHeMBAMDEVzY3Jv + d1JlY29yZAUAMBwMDFNlcmlhbE51bWJlcgwMQzM5VjIw + OUFKOUw1MC0MCUJhY2t1cEtleQQgZlnxFs5NJO9YlR/4 + SDWH+e9rD/+Jf7lWWjMoTW9+n68wYAwMTWFjaGluZUlE + S2V5DFB5V25JOHZkTmc2RVdheWVXL0ZQNGNEWlJzZTNM + TW44UHhnL3gvc1B6WkpJUzVjczNSS280L3N0T1c0Nm5R + OThpTmxwU0hyblIwa2ZzYlIzWDCCARkMBVZpZXdz0YIB + DgwHQXBwbGVUVgwHSG9tZUtpdAwHUENTLUZERQwJUENT + LU5vdGVzDApQQ1MtQmFja3VwDApQQ1MtRXNjcm93DApQ + Q1MtUGhvdG9zDAtCYWNrdXBCYWdWMAwLUENTLVNoYXJp + bmcMDE5hbm9SZWdpc3RyeQwMUENTLUNsb3VkS2l0DAxQ + Q1MtRmVsZHNwYXIMDFBDUy1NYWlsZHJvcAwMUENTLWlN + ZXNzYWdlDA1QQ1MtTWFzdGVyS2V5DA5XYXRjaE1pZ3Jh + dGlvbgwOaUNsb3VkSWRlbnRpdHkMD1BDUy1pQ2xvdWRE + cml2ZQwQQWNjZXNzb3J5UGFpcmluZwwQQ29udGludWl0 + eVVubG9jawRHMEUCIES5okyKP4YMZqDjIGRMoLE83SYh + zjEyOvGPA0BoF6ViAiEAh6/dd57K+JBWmGXd4v4qGELp + vAeSjqcRUfdLtQj4DxI= + + serial + C39V209AJ9L5 + + osVersion + 18A214 + peerInfoSerialNumber + C39V209AJ9L5 + recordID + sNs6voV0N35D/T91SuGmJnGO29 + recordStatus + valid + silentAttemptAllowed + + + + SecureBackupContainsiCloudIdentity + + SecureBackupEnabled + + SecureBackupEscrowTrustStatus + 0 + SecureBackupRecoveryRequiresVerificationToken + + SecureBackupStingrayMetadata + + BackupKeybagDigest + + LTrJHVHFZ5vQO59wUih1MEgg1qI= + + ClientMetadata + + SecureBackupClientVersion + iPhone OS;18A214 + SecureBackupKeyRegistry + + AccessibilityVOPronunciation2 + + PublicIdentities + + + YYH5MIH2AgE0AgEBBCDeXT460rcv + jIDp8aJE+uDw1JKyosrd5OaCN/Ke + QJy+kqBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZTBjBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRIMEYCIQDOAegi + 450wm5Yk2Qtu7sSf4/jGWzCWU0a4 + FPRQSCgCUwIhANpyPSOc/yiCIIfd + YULrKwcZ0dm710etKYFNitrv8VRx + + + + AccessibilityVOPronunciation3 + + PublicIdentities + + + YYGSMIGPAgE1AgEBBCAmObm/AMsh + CPishw7Zj5VqF7pxEz7WPYFQoTdN + WC6PkqFlMGMEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEgwRgIhAKUc + sWDKPbwQt2TLHm2bzDWTVg2rOYrb + o+4sGs0sT5alAiEAv3x1jY/E/xXN + Jbex7oy7x0dLq4FGmNJFHWLQrDQd + GRw= + + + + AccountData + + PublicIdentities + + + YYGRMIGOAgEmAgEBBCApjqgrPqZL + BVUo4ShL7VlQX14zLBzgjiiVP6ke + WE57G6FkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgaaOc + o1aiL8bKLKXv4WmWg6kRwTFQjdZM + S+GRIJmxe1oCIQDAdSxG+N8iojUF + dRAMlGqgzMZMVxKZDiviyf7O0YOR + 9Q== + + + + Activities + + PublicIdentities + + + YYGRMIGOAgEOAgEBBCDXTpaU32V/ + ljxo71s2tcojaFlrzWTu93dunzeY + 6K5TK6FkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhAMxT + 7l56PjtGjLM/rK1TLAeJmg5QkgIt + Mo77FSHyMHH/AiBjR6GOatFE+CtQ + uaz7uL+JNEoF0R0+1MykoHRSHqPI + pQ== + + + + BTAnnouncement + + PublicIdentities + + + YYGQMIGNAgETAgEBBCD0zBfXeZOJ + FS8oXM/hL8rH9HaMyKBeHoOKMdfw + MtAo9qFjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgb/2S + ceDq75L07mzvNa3IgnlUh8hvlAAs + TJPyGtgFJNwCIGNWkSlYNNQEGUQZ + R9GHVgIWMD8ccRKjz17kMtdoJSkI + + + + BTPairing + + PublicIdentities + + + YYGRMIGOAgESAgEBBCBsRs9WTIBy + 92mIMVd6URteSUxiAwRpHEKiT1ky + 0MZPOqFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgQDg5 + 9S8sDoDS4OkFJKCCOIo/0gkLy7ol + bA0ebbRqbOcCIQCONcU18leu/dVG + clWNgN4FPWIHMX3Xs6QD4h+hpJFs + 9g== + + + + Backup + + PublicIdentities + + + YYGRMIGOAgEIAgEBBCBezDIWdM56 + G/KBXahejdDg+W06PIZORqx808HB + k+J2dqFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhAPF5 + A/HcSV4gftgp/JNJt3YncN6UaO7W + fN2uLJpFVbtMAiBdbyb1R/79q4An + Mv+DFCsR274j/nc4TBJl52libm+i + 9g== + + + + BluetoothCloudPairing2 + + PublicIdentities + + + YYH5MIH2AgEyAgEBBCClfvDzGvfD + bRAjpecc9+7M+if4wO/tdWQ8vOb1 + 1L1+pKBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZTBjBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRIMEYCIQD+DnMw + WzcKXCpNN7vODSoCFnuMeHrQV3Hd + E7W6PtJ7WwIhAPNmAa/o0hGaVoZQ + QMDMDy6x4aILZSev+q+H1SzxFU9P + + + + BulkMail + + PublicIdentities + + + YYGRMIGOAgERAgEBBCCI3XoOP4Ko + su3w8M+ECPTMCnjbM3nLmjK/6WlJ + OUoIgaFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhAIgz + I2bYHyqRHAQpYq3liI6jtn8ZT1ve + /Pz6euQP4NAuAiBB2dIbtiuwSxgV + IkqI699bhauRROHjO9r48FrjrTJl + cA== + + + + CloudKit + + PublicIdentities + + + YYGSMIGPAgEEAgEBBCDX4Lqi2liR + QKhXA2QYm0l7edIQPhVLwuk/TWLl + yAT9PaFlMGMEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEgwRgIhAL2u + oy74rk2RNImZA2BlpEt1lbYXDjQD + LVWFl48ZiGflAiEArkFMxuEWlWOH + BtNjjZ44fmxKxWsZi8+NGAHfBCd+ + IAU= + + + + CloudKitApple + + PublicIdentities + + + YYGRMIGOAgEXAgEBBCAjsVTQ0pZm + rzPCJAdrUjU8RDTgE57XNKIyvXPY + 0HkVhqFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgfrBi + TRmWf4KPF+HN26p3jCAjdIeTIySY + CHoXSYnuDxMCIQDPm8w+aF9D5f8n + ZdPGAJgZGf7IfYYej7uksgAfWpiv + 6Q== + + + + Continuity + + PublicIdentities + + + YYGRMIGOAgEVAgEBBCAACkc0AMRb + cY8hsM3mTlgYJovohPSj6QIjo2tB + hGJGoaFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgHKPo + mEfyG4Y5oqrUXC3ILH97fFYNLXT/ + vxnypm4m3NACIQDO3uZEcTXfDXT7 + 7iJlctPPnWtskWaGZdxaKSEdQ1Ga + BQ== + + + + CoreSuggestionsPseudoEvents2 + + PublicIdentities + + + YYH3MIH0AgEzAgEBBCCvNPJB1xx7 + x/4UOr+5IH/0UzVKX+QpvmqX7ODO + leMkrKBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCIGfKKUNL + wZhpIi9OIrEtkrsB7rzpdPRx/nc+ + pd53aepmAiArIUBx0EAPslG1TrYH + SLNo0XCtF4C0ihTQfaJPBAiyqA== + + + + Gaming + + PublicIdentities + + + YYGQMIGNAgEPAgEBBCDJbjy/eQN5 + 71Uz8wPWukKE0SZY/QvIlA4GfkVy + 102fBqFjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgSrBW + Rcxox1/CdtChoDYXmabj8Y4vZYBS + LOgHMdIwKQoCIEkq6KImjlvmlWBk + ewyK0jUwqSyhtuJuJtXux0TUKIpa + + + + KeyboardServices + + PublicIdentities + + + YYGSMIGPAgENAgEBBCAZ2Mqr74uD + cAkMedabKkMBE1YVv3r9BY+ZQxiz + tbxuOaFlMGMEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEgwRgIhAJSI + 7dsRXpoxNc7bFCtPFSDwUrWlwNbN + oa+j9VpBg/nqAiEAuj1iKHKO5ixZ + 92iBCwS6tta9CNYL8DZMMoJYhrkg + LSA= + + + + Maildrop + + PublicIdentities + + + YYGQMIGNAgEHAgEBBCChFkKqgrWz + OfMgBCCorBsVT8hy+zmWs15UbouB + PzHsGKFjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgJUhO + SBsTLydtk7Xu0V2PP7A+Q3VoDsDr + JTGWbd8z01wCIE03dzox48zVifu5 + Uo5LPTqD5n1HxwNX21flE1bs+W8Y + + + + MapsSync + + PublicIdentities + + + YYGQMIGNAgEoAgEBBCADagtpAora + 2dL8YgDGudGGs9SNDfTdlEkAmFcE + DYVR76FjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgYIZn + OdcURVO0mg3mLmB3McpFItiTlpsv + 0fhSNluJZHYCIEX2PE8he+N4PSLE + q4HDjL2NVwGPX7mfXhQR/mrdrD+l + + + + MasterKey + + PublicIdentities + + + YYHDMIHAAgEBAgEBBCDBd3m4WFN5 + LsrHxCmPrmepRrZHDyx66Xo8SFTT + 8u9bpqAwMC4wLAIBAQQnMCWgEAwO + TWFjIE9TIFg7MTdENDehERgPMjAx + ODA5MjgxOTQ1MjVaoWQwYgQUAaKG + m18QogpAmwTW7wAhpcqfemgCAQEE + RzBFAiB9fOTaJMlRDK+FkotvzkJu + jB1quh9OBx3CqmLNpiry1wIhAOJ4 + wV3ckIwdzk/YNkGZLoSP9GhxsoY3 + 0yQKPqkZzQEQ + + + + Messages2 + + PublicIdentities + + + YYH3MIH0AgEpAgEBBCC/q5CztxOc + zrhN7w5PxTq2sWqTTdIRGht/2++h + NuGp36BlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCIECcCDJY + COrM8qBndA7BeEQh8i70wcFIk34v + 0hyC1VEcAiAdpGuOYOq8iCydXCrZ + kUOOCLK97fcO89AxaaDQ49r2KA== + + + + News + + PublicIdentities + + + YYGSMIGPAgELAgEBBCA3ZmHh5Ky4 + vX3DShRnlUuRPEIL1k/g4tvJJbkF + 5IfVWaFlMGMEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEgwRgIhAMeT + 2qHhhVTbb/0mF5IMLllOCL4wljRT + TVKzc2tDhdVKAiEAgJVLdcM90d+3 + j16ZxlF195knpfHs/9dor1wEIixd + EjY= + + + + Notes + + PublicIdentities + + + YYGRMIGOAgEJAgEBBCCKIp/yJqTm + 4Iuf/SWj8j1YQa6azRmpCY/bKq/g + iO6aZqFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhAOF5 + JxJkSDXw6hNSF9eJkwt5cKRsMMV3 + JuDJK/fBGW1lAiABjZZ1U+XzytGp + 5i1A6YgE7VVpR9btI6/QQi2iZbFA + Ag== + + + + Photos + + PublicIdentities + + + YYGQMIGNAgEDAgEBBCCcav3S7T1z + VLM9B88tyXLT6Y5GjRD2jCzDdlKs + YdfhsaFjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgPwDW + JNcSN2+zAN47Hg0UcbnzPRbHJBR3 + JrDpBOEn7pYCICtNOoLuVEwfqX7j + A2fX7soQVUfT4j/y34C5CPrIbKxL + + + + Rawhide + + PublicIdentities + + + YYH4MIH1AgE2AgEBBCAO/9RLJMcH + o3qhFeFb3qanoK8t49rSDrm9ilPv + AeiKJ6BlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZDBiBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRHMEUCIEqa4Rq2 + iCw3ULDe3577bLpHuUyRvUDtEKE0 + rS7H4IIGAiEA4yG/enWyQuz+TacB + Vbe3U0cZ8mNarFnCWvjagNZ/BU4= + + + + Rawhide3 + + PublicIdentities + + + YYH4MIH1AgE4AgEBBCDfi1Ny5x/R + aYdLHWW+xFbNw90R5XCc5isHN6ud + qaGyKqBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZDBiBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRHMEUCIQClF2jC + dx76r4x23i8sBLm6syiQYYhvPmC2 + bEvnxPkxagIgUg/wLELGQMoReD12 + SiiQglIgKNtzSuCgRfdUjAYB7fY= + + + + Safari + + PublicIdentities + + + YYGRMIGOAgEWAgEBBCBqKP7jb+TP + nhhTpvziH9LG4aDa6i1IDLJmtFBl + 7u7AXKFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgYT1t + a5nB5G1GRccSzXyo84mvxb3xTeqS + V0HNw3zP9uUCIQDnoAU+3LtXDkVK + 4n51tfLXr3XZIVEwPGImBB/p2qGx + QQ== + + + + Sharing + + PublicIdentities + + + YYGRMIGOAgEMAgEBBCCeimmOmppn + EufS9uArUm8PTZ8AQfV1cAszCMD8 + uJoN9qFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgIyyv + XdIJY2RRQcBHo7Uf8qzZwq3GYHqK + yCbh3voiR2gCIQD/cgaeToE5Z7be + wD6evPVSPSXwBc7OH0FJFy+1iqCc + Og== + + + + TTYCallHistory + + PublicIdentities + + + YYGRMIGOAgEUAgEBBCCNrMVagA0+ + ttQkY4NGtYqj49b4PHHV7YFaAHyV + d9vodqFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIgAUD9 + nE+lBkcEnXyL0pcE/LE4diyBd/Ub + osjHyB5j22wCIQCUcJfgxHVChg8A + e6FjMuYjf7cVoyNf0YmuUEWkmwvo + Ig== + + + + com.apple.health.sync2 + + PublicIdentities + + + YYH3MIH0AgEsAgEBBCBC9NWuZFgs + rkDeXFDLnakWgoI4L/cXyz+m43lC + 2JWUJKBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCIGo37UsM + Xb7GaLeBwYfg302TWGv0xbM6XDuo + xi/RX09VAiBOSD4os5NX+GTYqLdR + erCTQ5dEVScIWaR6n45SATDuRg== + + + + com.apple.icloud-appleid.privacy + + PublicIdentities + + + YYGRMIGOAgE/AgEBBCDyKeoxY5kg + 0jXZokvw9XIZk/dXsLybRdeGyOhC + RXTz/6FkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhANGl + TEY7KpACQHm7qcSuuS/j63P5/AHu + M/CFNtpxHPs2AiBB4iFuMmexGzcA + dxjD8AweXzf3BuT2eAMPveTum/As + YQ== + + + + com.apple.knowledgestore2 + + PublicIdentities + + + YYH3MIH0AgEvAgEBBCBbIpT6tptz + 5puJ0XdYbcQiOBT9JDtH4o1W9en3 + P4hJPqBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCIBEFJhmK + SW5huLbY39W2AuOZ7sMzOwTka/Bl + aOYDw/qNAiBNsupg44L53rbTy0+J + ItQBOKQPFMyS4ggM+38xEh1o/w== + + + + com.apple.news.private.secure2 + + PublicIdentities + + + YYH3MIH0AgExAgEBBCBjOqSZoGDw + ScKt5ncrZEkl/5e43V/wCItiOI3f + fCu3XaBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCIBbcBuay + kWaCE1IFXL/4nmckm8tSDLnSLUje + T2YtgVB6AiA7S+NREY9sOh3WrB5p + VpmZfhd3Blv6JbeHkBsMjWDCUg== + + + + com.apple.routined2 + + PublicIdentities + + + YYH4MIH1AgErAgEBBCCO6YXL9f4P + kkoFCTOYTejP548/+n2QYLyev/v9 + 60tVSKBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZDBiBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRHMEUCIG1WEsAe + upMhR1v7+1RxWB5AosnbhgnLueM0 + FT4xIYFgAiEAokT0B7qa+pQMJgVi + Jy48mJOwTbFTVcN9Csz1cbxD6+w= + + + + com.apple.siri.knowledge2 + + PublicIdentities + + + YYH5MIH2AgEuAgEBBCCM34oVJt4n + 8zzP2NzHDaKADwE6BqMEvWbXPXnG + LiJfzaBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZTBjBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRIMEYCIQD+HNJz + cwUhn+8nGbYmaXsYgjUN5IGBuhwG + kkws3W66pAIhAIHSbuQ7n6p/Rkjs + KOeVOq25ZcL+3hibiJJZIvNEqtSU + + + + com.apple.siri.profile2 + + PublicIdentities + + + YYH3MIH0AgEtAgEBBCCOKC4GWP07 + MXtnJuAXpyVkRwrXBhFMf1fEv1EN + L2HFGKBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhYzBhBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRGMEQCID6kHeWN + nKA2CRiHtOssTg7KKMONOf5K8wnO + spBk+d9vAiBKRpXkBbHzObbc9Sz6 + 3WEfAi+2Z6iOZ+vVDVirAbFr/A== + + + + com.apple.textinput.KeyboardServices.Secure2 + + PublicIdentities + + + YYH4MIH1AgEqAgEBBCDtVL0VIeP3 + V7gD9jkiaWu4xwxe215t3PammS0L + No2WIaBlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZDBiBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRHMEUCIQCLfuV/ + Hulb54Wrc8pNt1ibM8IFuN6XvkDj + ijiryyxGVgIgHfaVTZE/F2b02h4X + aAPBi1YIDvMAoycxd9ylXQI1cr0= + + + + com.apple.wallet.paymentservices2 + + PublicIdentities + + + YYH4MIH1AgEwAgEBBCDMr1rH/wSx + KnXhhMuq2kmQAsbuu8aQ7CUjAaP7 + ltmt56BlMGMwCgIBAwQFMAMCAQAw + JwIBBgQiBCAownsDFvISVYfCbbD/ + 50T51ZSZzt04daIl5fdJpmI89jAs + AgEBBCcwJaAQDA5NYWMgT1MgWDsx + N0Q0N6ERGA8yMDE4MDkyODE5NDUz + MFqhZDBiBBQBooabXxCiCkCbBNbv + ACGlyp96aAIBAQRHMEUCIQC2O2y2 + BdX70rfntL/TRaSfQ2hi2HDlJRcD + Y4Ac7dTNDAIgMCCNLTjH3w3yanom + cdUpUYpUXk0xg7rmWv776V2/ph0= + + + + iAD + + PublicIdentities + + + YYGQMIGNAgEQAgEBBCDcezl6FqtG + yHkX174CEG8VSAOi4P3lIlFNO4qJ + fVX0saFjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgQvuS + zR9rw1O2ySTcaQADxxJd1GuffZ2c + xK1kGvS45cUCICC++3nOux4yl6TG + ku4P9QDla3NQp/7hH+lKmOIpvcOk + + + + iCloudDrive + + PublicIdentities + + + YYGRMIGOAgECAgEBBCAXOlNsMQNV + JQUY+dqcGt39XUTbDVT2ksgEBMVv + yOjkPaFkMGIEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEcwRQIhAIL+ + 1l8MsRW3rN9wMeM7tSinakp/c2/D + p2kO8Z8OZBxSAiAL15IC/CrJgkQL + yS4rarGeTmMFKGz34i/jQ1AQHzQy + 0Q== + + + + iMessage + + PublicIdentities + + + YYGQMIGNAgEKAgEBBCDK+TvjMZ0j + zhAklsGuo1nbUpfAsRutInhCa0uX + k/HLA6FjMGEEFAGihptfEKIKQJsE + 1u8AIaXKn3poAgEBBEYwRAIgaDaM + i4SMzCnvHsQyB4k94BaG6y34FbB3 + LDlMT2pa7EYCIHJGgdwlbbRfFyYz + j08ohfXpCRbck5akTbDkOxRYIdyB + + + + + SecureBackupStableMetadata + + EscrowKey + wVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3k= + LooseLeaves + + AccessibilityVOPronunciation3 + + + ZIIBnTCCAZkEUwEA7coGYUYS65YH + nBubKFI66JIshlD/zcZadtS7UPht + /gQw4Na60gEDpn3LLWAPmNzSU5aF + q2i5FdGApmZz2ZjxJhKs34OzsSz2 + kh2Dpg1xkYYABIH6KTIPWejPTEmB + IMu/M8MHedxNSBN92aCUaaFKlFpI + Efr4ERxhq2+7aqBDUod+agFjj6Bz + Ei4NBHu/j4LZsb4fcOMwq2G594K7 + cevsVg5hsWb800lTOnIWzgnPfk// + T7CYB3S5UnPQnLtORz7gQZzWlqlo + HJSGltcXdt9nF5hOsawKZttCDaL6 + 0j00MtfeD0WO+aLl2BmD8syaCwNF + RCG8zplq3ot9Anh6xzoeTGzljjuY + mPQPAKVFkUNyBI81ZK04m9wxPUh1 + 64CPXdv2hsm+zGqNrTX1sny7hlcA + VbMXspR54l7EpBlHw0hO9D+2wtrf + I4cwtfSpKFG9oAQgJjm5vwDLIQj4 + rIcO2Y+Vahe6cRM+1j2BUKE3TVgu + j5ICAQIEIMFSm9doDsBBLY2n03Nk + YLw/jjbTcxbWf7/ZhJH9Q3d5 + + + AccountData + + + ZIIBnDCCAZgEUwEAIkREyheGTEpx + 90YhB0zt3gW7v4Jjgs2YF9K8fDOd + GFYwGDCkB4bB6j9FZr1ZEg57UMjq + djwsUAthex7ePflo01Wn4PzatH1r + LOwjHLfTO+12BIH5P5Bm3AyaWPJq + W138OzxseZfkxmZayjGK2tHsbrRi + gth3AkOUvysatYcgmAzVFfBUITc2 + F2eUOMlX05Lq98JWGJUN1wx6LKYK + CAmISy7GfaDDSWd35YlSRXrYHl2m + kDjGpUkUT4RB2REVsBH6OuOXM1NG + 3sFrV3Mx7LZt7qWt8j8fbpwT9S36 + l77TyJIMPu/xkywGxLSUP5UDjiby + e/Z8T1SEpqyikOx+r7/YY3iZczIi + KcDVJCkzxQbEGEka4a9r8h35SgM5 + uy8bzjO/heXIh9OhxcKv2bYqQbln + bMjtL0vLqp2ihT9blHf7JZRrW/86 + Yo0hO1V3e310BCApjqgrPqZLBVUo + 4ShL7VlQX14zLBzgjiiVP6keWE57 + GwIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Activities + + + ZIIBnDCCAZgEUwEAit6fWo+OJu+u + 0AmgeLcyLkhTi2UnNSi+KCrMPwq7 + cLkwDDfCp19sx91iRV66MjOXnyac + 2K3Z4Ne0Yu1pTA80NvfKboJngDgI + sGXGdipH0RiWBIH5IVxHisC8FLLk + JrToYv9zZNkscu5xh1v9/RC43IEQ + +1VIYwvzCkUGCfRNg/rf7mHIT4o0 + nQppvEb75QbPXoHzB2TembqJYBID + ltYQBrVSwII0rwDipCH+LrPNJkRc + QoyRuVsH2baT2e6Jz3L630zc4vzm + Dxt2tPEWfluCjjQPkgX96A2mF0lF + F8lHIQyVTQOxs7KwgrreCk92/XVP + qS/31SlphaMV87/ZCnKtMpVb0F3u + GFM21274mvl+83giEOUgMqzDhMqO + SJ6MXIgW2/lYpBz+UKpLZVHNnYzA + FIO9soDHThSGR/wCjOFVo2PhYruS + 9zwtMg+iJuy+BCDXTpaU32V/ljxo + 71s2tcojaFlrzWTu93dunzeY6K5T + KwIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + BTAnnouncement + + + ZIIBmzCCAZcEUwEAt971wW2seGN1 + VyUtU9Uo26f45e+nwJSlPDuZnJ7k + 8YwwrOft/abFvpL9EQi55rdaFcWZ + MA9Nm1kqyDno1lScw7YDhPXFOFmu + RLiUcfJcVu+lBIH40fYFa6SwWaS1 + A4fpAmULHHJpuG2kya+ESnHHZFw6 + G6ok39oj0ji/GRTW5WsWhjMxn7YM + ziN7ZUuImxTbNFQyvTEymOVBaxxR + 6MD7Bg+yie/glTHQdFUFlxnOimIz + C6AsPCbWm8Z7BDTEr6i7t4f1tjDu + eAT7Jj7Uxe9W2eQzx/+J9JbjBPSB + 4OxHRfqpRc7DeMMGTZy/fAQKND6V + AMYPdhnUARGxAkzkUf8gAmJD3nc/ + v9NGnU6TLtxRjEytKSQhUy9A6zyX + YMxK7nyv56dTPMGnxg8uIOdNIixA + DIhy5WeV/vUsn3sabMHP7tyXcnMt + BxyawjgsL14EIPTMF9d5k4kVLyhc + z+Evysf0dozIoF4eg4ox1/Ay0Cj2 + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + BTPairing + + + ZIIBnDCCAZgEUwEAQ3obteunNorD + 2SpZOpGB+88OlqQgI4mYVzIeqYzr + MqcwjpgS+EMayACEgCy30mwZkXV+ + y1mxtVo8Jz5sAHprj3wiiyHrur2q + uQnLjJJ4s88dBIH58t/+KhpQs7BR + mUgocoztX8bNopGuc08Uq5hHiBeZ + L5Q72jHu8wRIC/SSuz2o+THUyF8J + duh8fnOanFdTTVvm4sZVONCKCHF1 + O2XAy5kOeYRY43/omrS0rFyELiSY + 1ABalykBCBQYH/5WCzGAQnh3h6s7 + lVuYvTpsFlz+wzWxXnhAH0HVST9A + f8COEpidxATAZ7OTpBAYD9SXvBmT + axSsB6sPdhQ83WLGFz4D+W4raymg + uSRIQXUUjw0PSP2LPIaWagww/4hE + ZGp74PILQOeiOzBjeeNbzTdr5r2n + IFCcQr1jmYh2Eb2fhB+HjU2Wn9EX + 5yd6VOzXfqAOBCBsRs9WTIBy92mI + MVd6URteSUxiAwRpHEKiT1ky0MZP + OgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Backup + + + ZIIBnDCCAZgEUwEA3A/n4WhznwF/ + LvLzAhTFBE7oIxKivBNqU7OSE6FT + GWUw5pLbLd3Uq72xUPHw4nDGp7mY + m/aNK4J9BKbsgmKDLNVwls7anxkS + JkA706XCsbdgBIH5It/fR9OHWKzu + 8iHEaf7YYhQSabWoNfJRpZS1EkNV + e9DojJDJfg8ExcQQsPu6JSLFhQ+a + cvPEWsoKzW0PIsVb5oiiqU4WWeAG + US5LbxAENGeAEOJqbna0D7iWXHkm + EGtRKl+raWSZAsXAGpSKGy9efsst + DbNGOcN4ievp8DnSkFwSoQ+EvkUA + Mb1MoiCCCB0NCfn+MK8LIg0g+MhB + Hp3lf8HC8Aie+gcj5hzVesMeG6lj + OOeBVE8BS6fUet5IWoSNhhRyDoyE + 0V5kja4Mr8hY5XnB3G0770VoDwYY + mPQj0jgrG+jS4AQsSDW4PknNxLgK + Hk/7StJ7vJx6BCBezDIWdM56G/KB + XahejdDg+W06PIZORqx808HBk+J2 + dgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + BulkMail + + + ZIIBnDCCAZgEUwEA8MWcOAuFRzvg + Ybrd2u3dBi/D1UFZ9oqNL2EdTjM7 + 314wOTSbbAqyhIYWd5wkNwbwh4QQ + ZN5ZKEcv+VpIOLTc5gg9dF9GAtq7 + iWQnctLlI/RZBIH54/fs/QwzrSJh + en5U1iskhIsWbBzdK+QtdekgVFYI + P34Q28Qang7eN0hZo+ndyiBcqHJ3 + kL5mfk6ZIpvcUHFpXgC0wwxTgDDm + T0yHAEOevwgf2Qng2jobFp5PwpHi + wmqCI4RltMVMwnnv4vh8yM8WZihe + sZEXMBiqS3gmWRk43dBTCKAzHhKP + lR82vZHOTiJDbj3Ewpnu2MjfjMFL + C9wi+Dcuk8K2a6YRq4N5voLQ5Aiv + KO/rW/Te7P4wrObgCEtTWZZETQmE + QjMa7uGqA8rD3yoWXX+TcVIj1Bhg + psCJUT6kyYEvv8Y5q9oCYMMLy+6o + 2trU56gfq1xMBCCI3XoOP4Kosu3w + 8M+ECPTMCnjbM3nLmjK/6WlJOUoI + gQIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + CloudKit + + + ZIIBnTCCAZkEUwEA7mcfkI9joA5Y + RiHMKVPYdCl0EZbdHHSkd+XbtD7M + z1swmsOp0wrFLe6Vs8Fl/eLiARGA + oFbEyqKuOqGBvVJcANDyON1SpccP + YyE+m9Fv1N84BIH68b9LFxZu11g2 + wdpwAoLfHGAIpixj/l/ExdN1SejD + h42zj68oMRJipC5Pzuy7Rsfo8hBq + DgSCZQ0ASzcyZvd/r1eUVlkPdtfW + 3e1G8CiLvEJjalHXMK/q+ZkT5ix5 + RrImOK4L8KpwVcLyYf6RxPhvLtQI + FuyDWZ/zcGeOQfXbEU0N3DEcM86j + T5VpOVvbejiFABDV2auJtxAzcbPo + imkyfQH6B0hb7J4MoUBqojYp3/Wb + Xgd+xsZueOYaioaD5F47gGJJt68v + V79KNCrerlvSaoAAFZMT3aj1EfjW + zc2Q+XU2ugjdA7yNrxDXAtzteqcT + bqVa7k48t+smmgQg1+C6otpYkUCo + VwNkGJtJe3nSED4VS8LpP01i5cgE + /T0CAQIEIMFSm9doDsBBLY2n03Nk + YLw/jjbTcxbWf7/ZhJH9Q3d5 + + + CloudKitApple + + + ZIIBnDCCAZgEUwEA2gOwrczljkPA + WHgRADJ6o8gdgLyxKKfRWNqWUnri + s14w5TsyO/m09rQMYaqozK92iNdi + KgZVS4ewntjnRL0MINfQuxE83RV7 + rGrDO3oEuJ6cBIH5V8A65gqIk5kQ + 7ZgU+4YDOpi8zZcfMSPbssw5fPy2 + RcH112RboQAPpDRWqfRA+v6ozvIU + BLFt3yHfhZLpd13PbxxjaSKjxd/x + LhdMWk39WAcIlIQFTyurBS3C0Nsf + pH2oVVjoOaLI/iv1cIITjgHgjUcQ + oX161WZTUcp4C7GD6eExWGNfc9lh + 7jEXNoutRL7W2eBMIJbca0cNaoen + zh8Ee4t/CNeBuWe2Ex2ka+KZBRGP + Ruw4o5T2W/iCOu3dY+izFhzp1BLZ + 0AbBDpmEII7+8evOrXHqYX7rEt9F + te5bDvZoO1hmO6sIuuONuiK9ad43 + zWXdZMqNOZk6BCAjsVTQ0pZmrzPC + JAdrUjU8RDTgE57XNKIyvXPY0HkV + hgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Continuity + + + ZIIBnDCCAZgEUwEAEJ5swAeKdGml + KBxozSTpsTC97zVft9/MWvYmFdVB + askw0WgUkVHiegWuHKE5xphAVwc9 + 8fEHr8WdxDfrbg0k8X/oUBAhjK09 + QFBdKAAT6sAuBIH5MiYviQHOuAnJ + mFIVlH6qMoiv+JHzgkXl4futwcwV + oI/t8Y8VE81qeXgP6N6y9iF/VpRV + GhVqaD7jNqXjVFycgWrwOXHYF5V6 + HgxGIGe7/lIIytjAy0Ubrn4IZGn1 + hKGmFM39r4hoFFn4UYL11wXTl3xC + BxG+Nt66tnD2tZSMvlVOkBi1Z/uW + xFsm7veDYzCveRI38yOKmdmG4zkn + fw+AQF8tYcWOKYe39TKhwgNEYe5/ + WI9/3CxWUqxd9H0g9wb6OOlUjnJE + Jf/3uoYFLUpAlYLyDP8JlDqDad1T + xL9wdUmt+DeiHHTC72wHCt0Q1Tnv + HJhBBhiUR6x7BCAACkc0AMRbcY8h + sM3mTlgYJovohPSj6QIjo2tBhGJG + oQIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Escrow + + + ZIIBnTCCAZkEUwEAq92z+A2mGWee + OAh6/oSmx+1nNN8OVrv0OZFF9ACP + 0L0w3Tq7x0BsXOKji8FqrajsM0b/ + 9vvFNDPKpeD0iM6qgjnOjXhTEVU3 + 5BNEd9eXuNpWBIH6NWYRYQLnDg/R + X2JWnmomZjRrOIr058bkXVsn7nbE + CP5XP8UiniHnk1DchxDMlkkmckV9 + 612PnxNyegWg29s0i1hf9s+NLrhk + 3KQEQ585xa6Ghc14F2oN8M6T1xMp + K86u3bO7NeSVJXbst2LqeGFYf6no + p176vubd+jrNAvMVemeCADoYLyDY + LgNmAPrVfQC/THUMQVMC954K12m6 + 0I4xoenEvFOR6Vlg4wyuR9eJCcUh + b4+iqBQO62xtbxakcQETMx4GBL/y + y69NTEfA+hGKD0uTqiU1PTGmOtUr + KTfH6X9y0aju9o0B5jAUMJ6rkOHu + nLQr6jYvW+L59gQgwVKb12gOwEEt + jafTc2RgvD+ONtNzFtZ/v9mEkf1D + d3kCAQIEIMFSm9doDsBBLY2n03Nk + YLw/jjbTcxbWf7/ZhJH9Q3d5 + + + FDE + + + ZIIBnDCCAZgEUwEAMAsrg/pUgwcX + RauUPBcyWRKaaIrhSthNfvQSO2pB + HKkw8daKeW6oP3npBiMnXgGZAohM + k5VD2zlLd/jHgN5vL4WwoR0ohT2c + ZjYHzUG81P1oBIH5TR0h3tRdlap8 + wORCCEhoRaZOXozPoQLc6UQb06yb + KSG54WqWIeiYDDYBNSJ3Pqn7pTIx + bhyxg569iDwnBWlHZcOmlbTQPePx + 2r+Qysu/a8Pf+S9IYBkz6BCBoS8i + K7d7ZonfO6P6ObuXHQXIUeDqeCqF + CwYIVslDBViyywv8v30zmKB+Gs5C + IlwrkDUeXGjimKsynu5FghhOKNc1 + hrmfn+XLV8Ht+eS8SkcjmuZ4NAiy + 4YZpyKGVX8VEC7WtwnVQv7Dj7+AB + Q+dZYZZDIMkRYLff8sP4vizqDK8/ + wXOKv06sBpSG1avueWr0O5jXxLdH + tqQjjFU/fXPPBCAkfz8NsHhEsMkD + wr+lLP6dfwEGvs83Be0DwG+OwI3G + UgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Gaming + + + ZIIBmzCCAZcEUwEAL9qPoxGTOloQ + mg+k5v9L9DK1FVDLI94ISo0SIl2g + IWswe/PThv4UwYAvYy151JYnVXRG + pIglXCh3wMmRn/HeBt0pwoeVc8Qp + tw60Ds997cnEBIH4Pi3mibPRMb11 + 8nGz+D4A5bzm/9+SZyW8lXsr9vb9 + CppQEXP3xp+2IosFV3J8YgZhFkNk + foB9fcjjSuk4NE++NnoGXG3FqT88 + UrvDvpykFttHs7odv+n1yMn1HYlO + KD0lCrp0LAzsRrDfm8rQHt8XxACR + mBmUGuR/hreDWw+kLaeWfi7YJ+UO + lCmOJWo02jUyusVoasNyYh09oCJP + 8P+jnJKaLbI7uJsty5kLMpVFHqP9 + RMYB5GQT0n18q0fUEO6XREgBSn0S + Og412K7XjJaZeqE0DqkF87Hi3JLg + 1zRjAGS2B9nAes/fntuQco/eyCPx + LHAsqDaHsecEIMluPL95A3nvVTPz + A9a6QoTRJlj9C8iUDgZ+RXLXTZ8G + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + KeyboardServices + + + ZIIBnTCCAZkEUwEA/tGjVinL3pjD + EQPaRVbA1KOHUUWoLy2O4ImMlSZP + Qxowjy3uVmizCnwAr4HCq8tQezOX + 6Rmr7UYEf4CXVQ30BCuKrTC4iIwt + mvqWuk68Fh2MBIH63FQzTbLYTz8H + meAieQeF7vk39HOcW1gJIu4nFk8n + x1sc+sA56IWcFZYDHzJsauykjz4s + ezTE/45Crpl3qiCgnAgdQ29fQnDZ + sQVOGChZI+H83dN0lobteC4Nsxkx + EOWS+csPvEYREAcZWAz8C2cl2MEA + crhKqAQ+0QxiorH5Coif+M9+nnTR + AAPsmw1MOqA7JNecRfwV69W8SjAD + 8fJcx46hH9aehHd0eVgxUZz9qoXq + VbjOEFL2Zx1aYvqc2wGyWEUIDmdC + Sof3DYZ/U8ePGQteXjTduaetIfTD + N8+4gE9/APPDiVNzwKaZQYOGshk+ + DZw7wedOQwn0wgQgGdjKq++Lg3AJ + DHnWmypDARNWFb96/QWPmUMYs7W8 + bjkCAQIEIMFSm9doDsBBLY2n03Nk + YLw/jjbTcxbWf7/ZhJH9Q3d5 + + + Maildrop + + + ZIIBmzCCAZcEUwEAq3Qy6v5D1m+q + f++g6YHn64jfWkV8Relexixw2tY8 + GdgwJ6cmMqCgtvNO8S+o9/s2Q7x1 + iY7Z+D2l2YS6bo5QMtr2XxZtL648 + vKlQXw9m+TeDBIH41LFxD1yx7/x4 + qYqVSUgiWJJQVHgj5ld63Fxrf7SH + 8JMqluC/D232rw3aGNrIbJ9De7ZZ + B90/2BQEvt31H574yy6AA69fr6EI + gZQDw8aYXye7H0ZEnUIvb0vJqhxJ + okO8+qLryVYZp2b9VGmAtRCtSJJm + o9SQqBzYVDyeS5Fwe/7qTnYT/6f7 + 0frJBen0IMB2F6B9Ymh2EfB5mgIt + YvQsi/iedZ0SoShEhELv/dkMFQfE + sBL4fWGgZdXWSIvaQDw/r/t1p5Qx + CgFazEZ3P2Nma3CONYe4DdmdzvrC + 9pU/sngdKk8W+yKB8XivorNvSA2v + ItMNxcrBPQ4EIKEWQqqCtbM58yAE + IKisGxVPyHL7OZazXlRui4E/MewY + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + MapsSync + + + ZIIBmzCCAZcEUwEApFg3dOexxalj + 8nUrzt4S8lvykjPlpatoQaZV5jXH + utow2+O3Yevp/vk2zN3BZA8Z57Rr + irw/eSC66GQAIdaXTkQrQT/4pB6O + iKxPo0t6Zy0tBIH4khoiH57Ia4E8 + v4OSvsWDJhdW+VG62anIBrNq/VjN + YQGe0tNceaXA1xDmmCtATLQzjiZT + cHCGXn5whPdXaNBnpWJZr5S2v6zF + Hbja5DQKAoJN9tX6SiHsnkjFKblN + 4FzcCXZwtcatnvzn7quAhczRe9MH + aS6Fjx3sll9v/fhoVv59f8+NBoQx + ZKsEJVbJ3JiR2K5Gd5ddwMhckZjL + 2ukh2zheY7nH71M/0h+5tlvQD2JG + AfGjjsIco0wMFkZRcB7TcnklYVrk + +pn/Qvz8GAWmrThOJpwoNmYSgaSm + +R2M4cL0KLSvuqyHjDHk0dDjXgoV + U6FcHhuItnoEIANqC2kCitrZ0vxi + AMa50Yaz1I0N9N2USQCYVwQNhVHv + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + MasterKey + + + ZIIB0DCCAcwEUwEAl0pbM+TN/wyy + dy8KAtqB2Ra739lKTulOuUSwbnNh + 360w+LwPDymGHkz8b9qb8G8CQysT + yrmi+cXbp9WY8PpWpxSfrzK78mGE + j5aLPVEHXU0sBIIBLK9R/FnK18rb + q6AgmjGZid6JlPzBvvGN6C73embB + eMYoALRyxQ/DZOk44jzcP31LYfSO + Co+Q3MEKiITdA2wp8csupYRh/U1b + iFgsin+KeGi7WchB3GXvsE2Xiyvq + p78e4V20nVihsGjHfAGgJ3qe7JjJ + Bxfs8+SojxfWRGlCrjjnFa+yY0Vz + XgqELEKP+Y2YvpPoSxq5NYWTbIkF + 29mlPT8sbI0jW2odY1cNzuPKCQEp + nK9o8adqOSIe6Rq+wtUVRaAuN04N + CQZD8oVfjxTdPGq2EXlbUx+5po4K + /yCJzA4wBONR6nxzc8AsF0rycSop + 1ZaYMONrMjQjtR1/JvVZnNnZWBSD + vBz/74gdRPui0jG2ddKrubI1pZ7T + oELHtdw5WdGRb+LVkDncchopcAQg + wXd5uFhTeS7Kx8Qpj65nqUa2Rw8s + eul6PEhU0/LvW6YCAQIEIMFSm9do + DsBBLY2n03NkYLw/jjbTcxbWf7/Z + hJH9Q3d5 + + + News + + + ZIIBnTCCAZkEUwEAbLiwWK0ZW+qd + E7VQF/Vgc6Ca06iAa0KjlCHxqzfa + QWAwTUxr9mwi+sFXnZtJZS1lxjmf + 7Dkz/lfogz+o2A0eUMtT2veBw676 + 0wjRg1OUVEATBIH6uUM8GHhyqc1v + eSwAwr1M2jpDpw2T1KGfjKYIlD3l + AKC0SEt21m8KWdZbK9wIpK5XKblp + mqZ74iezeRWyUm4wYE0DaZQd0uNp + De63OU636GybAXMvJ3NbNbBhoXsS + 7Vrjp4luJq3/Hc1Z1v8Bs5/VU0ca + KAlH/MxLNJnAFu3wKzOSqpqvM0Al + XsrZd9HaBOKTz6cVpb46eM7GkXNy + YfoFripk2XfYIgB4ZTRMJstAbw9i + AxcSfN6UE0VaVYk+kcfcC41km/kt + 5yQXPEteuDhTZF36Ls09fmwRjry2 + 7O3gzYtC/N2bcXKEvqMQJHw6972O + NBjNkxyvkdyIKgQgN2Zh4eSsuL19 + w0oUZ5VLkTxCC9ZP4OLbySW5BeSH + 1VkCAQIEIMFSm9doDsBBLY2n03Nk + YLw/jjbTcxbWf7/ZhJH9Q3d5 + + + Notes + + + ZIIBnDCCAZgEUwEA5QBs7cwCbsgx + b6+/WPrQqmz8PyGvRm1M9by43vPo + XpEwIvaozyKcDGBuIUOKXPoZHm8q + MLwCqjz3la7fD2E8zysNgHx8R94d + Zs6RTFm00Kd8BIH5+z6ZZmeFMqKu + 14NIZXFS4lpZ5wVa0dBMzkU34qNb + dfzIGnOrtJdvTdBjlt7RBpwjdnxU + Om9+v/7OqzfPvu7Jfs7knMiDYNdd + 4VV1RYSvXngW413oMoWQrgt7Di6D + 4yEXwB6iCTjo4eRzhwRKqGVXL+MB + bzxKbQlQ5T5GmQO26dHeOW2bomPa + RP7an00X2C82dZIO4ri0HO++9yhA + Optmyos5C36lj4TASVuyHJddwmoj + RySv1ma4DezRxcCZzY3MF3ZjUIIK + pIX5NzNCkFbCFYLz/YJ8vSmNm2TZ + C4FhwSEPI3M9BwqSdVXzVTO7I0CN + U12UPyTaW6exBCCKIp/yJqTm4Iuf + /SWj8j1YQa6azRmpCY/bKq/giO6a + ZgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Photos + + + ZIIBmzCCAZcEUwEA5N7lj1BTLUER + P51xbaN4uvwmaMYtYNZfXtNEqvOX + SL0wsbOiat59vkct3mt211TBke09 + P8RBWD5Sqzrdfhutqg88shqDVvNP + iYFzHfAv6syDBIH4o/HHz51zYY9J + hNwCHW8G//opH42HzklRulXLOFy2 + 3QwDRUfiJIae2P6Y8sTYbHU8NbuK + BSEos5i0siIdqDD7lXi2/Y68uu6S + k2jNnRZS2sfO9qOFGOwZv6JGDh2i + 3YBAptDnESr7hlvAZ8HZyrl8SYi1 + IN6R0DHalhTF0kx+K+i78u7yqipB + H6oUeYc6GuAFYkkYt1E2os6b2M1+ + H9h47Skl21hvah+UAnMXpRHuDhFR + dNXy6LtQPmKlKOStp6AwS3JQfTEv + 1kEdUv27R2MpQib7pQwXEn2L0MFQ + R4QFj1TPG7hPkHPI25hotdFod0dV + 0v0LK6S2Af0EIJxq/dLtPXNUsz0H + zy3JctPpjkaNEPaMLMN2Uqxh1+Gx + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + Safari + + + ZIIBnDCCAZgEUwEAbbqSrvyPe8zp + 5T3WiZy6a2oIop8rT9+jxu7K8kt/ + UTcwK6jGuKAWyE3vKuzyYFZsD6W1 + 7aCq0ZGfCAxU7LOg+Ss+T5AP7LsX + RsLuG4qs8c2QBIH5DVOG01pG8RvW + FZxMYkq4xHTH+XPP6Mki0ppRbiqv + vXk/R3i3CWr7sdRcgHLrWEuu20b7 + MOujrqRatx3x9LeCydhiLgmr9G9x + Rm8AmRlcYipgD49Dsvd4BF4NkNWS + jtc4A645IyZBdH+GJ2JWQOtubT8p + GWEES2waAuuUm47FftMgdH33HfjG + ypG7d6f4rnoU5NgrauIrz8uA9ezT + TJeJYj4dI4AJ72LA8FnlZNPJ+p2w + c5CWTuLKHKjcA+DSJirdYJGFusTj + JiBmPBzEfHWTU+dEcehSCMxJnsK0 + sKYUy8Gx86NMB5T7qK8dzgvbep7B + 4iivY5KjPirOBCBqKP7jb+TPnhhT + pvziH9LG4aDa6i1IDLJmtFBl7u7A + XAIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + Sharing + + + ZIIBnDCCAZgEUwEAH/kF2CGnaMF7 + EeY5ls9Fd5WSvugys6kQdLxXU9+u + 0xgw9ZoHh1n6tl/l8TjVn68IfqcK + UtbkGEgcwgPj7oykBnDlUJxEBdW/ + LtWleF8Xp2Y1BIH5zaaktjtHOx4k + bXWPLNKOdF/zLfiGnI35fpzSZzLD + 7F1eanbVaIAxWcNNO/83Q7qirjcO + Oy8mU3dNQmE6+x7owH1Bpxk97IJX + cqL62Qm8tbeQG+K2w5iq+X7CZYzx + wKlo3pw5dgzuBSPv7llYcsjlzlie + 3zYDHFHDpXhtJM/pgCGcZ0xxJDi0 + wO/eSc8eW+6ea7S9F83aTiK4lDiN + l9DnDcowEpXR9mBzvWRyaf8yXO/R + 2wwZbF9X47eYfeB7r2AZmyhnoQdt + doet0A27Cp6jpuvBFvLiLqR2dDhR + OnY/2LsluiY6qTcsmtcoOliHNjXk + VXQWRizDA2ZOBCCeimmOmppnEufS + 9uArUm8PTZ8AQfV1cAszCMD8uJoN + 9gIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + TTYCallHistory + + + ZIIBnDCCAZgEUwEAxUH7GAzWiPzn + ziecAwy1WBgXS+jYd3WPN2bYMol7 + ZGgwOPm2ifOo7M9szW9cjl/dI3JM + 419ce2yWog/TbFJ2cAWKpfB3WsDE + 0cyPrUBYHIJ6BIH5ImIZ9NBEdMrP + e1zKlrFLEnwOxncJCen7RrQd3/bt + WSG42saJI10Zk8lQSW09YGJ7xh8Y + NQp2IOWKBytmxdvR9jAudn/8z4w7 + NXWqhfqYpjrzVmG5nz9XTxt75DBz + bozqsYvKVQWfmq/C7FXRPP9we27S + KXjNNnMgk2u6ircum+tWn9OftEEA + s0EXGcI30YqoTKcgLsfyGGlTsG5C + 9P9CffzpOtrzY+nprBxZSmIScK4i + FTx6N8w+j9S3lQeqTLthvBH6DTc6 + 0pCCF4OnxgWpP9POm9IltCgo9WJv + llIGI5T1WT7C7SgMpxscLu84aCrD + EUdxjL8SpNBMBCCNrMVagA0+ttQk + Y4NGtYqj49b4PHHV7YFaAHyVd9vo + dgIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + com.apple.icloud-appleid.privacy + + + ZIIBnDCCAZgEUwEApcI++fPiMp2F + 7719sTxSJqaM6ee9DlujcuWuzM6t + JVow1MYYRnnH8QbtORp2/ddi/I/o + OoPNQ7y8LVOGFVyJoARvHXAuJbiy + oT/PNy3FzHjbBIH5rEU6m8vdSuPs + 0ygcTuIPvXnGDYdkGzx4c39oflgm + aFgUsuW++rH1HOa6cCgJ/lstbJUX + RWhgoOMro9kMmgI89wzcd5DSBiG9 + UhQt9ZDVvWz262k5O01os9poHy5Q + WHECo4HqcfykUXLt/pQUo0QcQ9b4 + xGRis/X7vzpprRcK8M983alsaJH6 + Zeh87J6DDPajPfxHN/HPzB3D+Gkl + TSbzm+WRA0d3Iea3wh5edoJl9HSq + Xgxx4UFnpQyz+Y9Yl467o7Yn42/C + +2IvNFRQM98STxWssxamHdoHl5p1 + rUIUxseaHYCmdhvMUAslosNalc/p + wDmXbrlFVqktBCDyKeoxY5kg0jXZ + okvw9XIZk/dXsLybRdeGyOhCRXTz + /wIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + iAD + + + ZIIBmzCCAZcEUwEAT1yMt7X/tEb5 + DGCA2BPD9zgwPca1ZgTNiFadCztP + NZEwQzlt/Wmok9wBFnZtBF1eSoDw + W+hkyWSHqMLWbw7nhDCGFsK5mhxX + SD2syn2d4JYBBIH43drE0fkWOe+h + /k/tlsA0K+MVK4mjDGX+Rob97aDe + +AK5hR4Td8TOTPdilMfO4o5DpToD + Q7wzVF+tYqesLviZcTLlbtK+8+OI + bxx7OprVdxp8L1UQcRRDe5MrzEpn + yUGad/VmIvqBWJXVH+IaqLXTLhsV + T1XwYvaM3Q2gk3h3EYA6zjTLUKl/ + GagiADSmJUnL/sz6dI81fXhstcWw + ELvvxM1VqpBIZPQJ3E9XPNTX96bg + 6tdsH1xyzezqijanhcOqIYcR8fbu + PocuN220LJOZ89k0gQTYWswU9V77 + qw8TCiBu6KBL82omINf51oA3cXoS + MjQCQBnUl+QEINx7OXoWq0bIeRfX + vgIQbxVIA6Lg/eUiUU07iol9VfSx + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + iCloudDrive + + + ZIIBnDCCAZgEUwEAhTriZPlk5ba8 + weQP8abhLwtXIMRdFUPlVDwmgqCY + 2U8w/ZpeoOaJ5wp+7NNBOQgGi88J + CQfor7ChKRLSy0rdlAZDLKEHZifl + NJMpqaRLDNMFBIH5Zo4hPORCAtqi + KM6BZmXDM4ZnyqLNREjAw8SAyQKq + viDGU5f55CavjkHluBLUzvddxRPu + e+IFc6+Yes+Rs6R0Xj9xZpprfAFk + 1vusLNajPhT+a4+ChnEtrp5c8keB + z7xte8YgPINm9HyTERH4X/QrwHXE + 0un5d2iU5tE1Q9a+V9FctlUHl4De + EKk1cO6+UdckPo5l/1ozpxscvNpt + wgfla36ivuZQ8Nawz7Bc9s9EiFRv + Pa3EaHN1pJOMzJ3eWCqkFy+XheEa + F6riryW/Ybl/prjzre3i0EKTzzXO + bnZ6OceTfOzMmPHKmCj56rjqharV + hoo2e8zhwV0lBCAXOlNsMQNVJQUY + +dqcGt39XUTbDVT2ksgEBMVvyOjk + PQIBAgQgwVKb12gOwEEtjafTc2Rg + vD+ONtNzFtZ/v9mEkf1Dd3k= + + + iMessage + + + ZIIBmzCCAZcEUwEAEZKDmq9tWraG + 4Q3otQnxhDK/rs9+l6EeptQ0JF/j + PCgw4ua1T1g9j/IC4OOk9PEUUQix + 4R5VYCTstE9HtdVC7AhhOIbFUp+K + 8ms36ITjerXQBIH4egZIG+JkLXf2 + n9WCQHv2Ue/cw6SbxEmKtrNtYfqs + 85x9rhhZLaEag55ko7hq/5nvRyAN + 0MMH1DxU7TipecTWz4we5FRHWn00 + 2PM4TqMDci7/0+Z6+UAQwXzF8SyA + X12W2UZns78mKKCLCWMBfsj2Dvu1 + sab7LIn4eZHiMq25bk+w5s2kI/X7 + 2ee6eeNGqhPS2Qx5a7uHSkuQ/+OY + TUG8v/3Azsb0Gzn0gplS7peFXNAm + /FyzYhMeWQWbPlWc8HdDshzppCbq + XkBbXq5Szlbh/68pTMHAXYLWqWsU + LEkgtNgu/zAm405LDqU/pXb1MzIk + bJAbsvGpie8EIMr5O+MxnSPOECSW + wa6jWdtSl8CxG60ieEJrS5eT8csD + AgECBCDBUpvXaA7AQS2Np9NzZGC8 + P44203MW1n+/2YSR/UN3eQ== + + + + + SecureBackupiCloudDataProtection + + kPCSMetadataEscrowedKeys + + ZIIayjCCGsYEUwEAPy4812ENrmwVk6t0W6sfIrlO6AiE + gmqgnxn3sL0HIeEwRUGvxCIWt3mQR09OyX60jN44aMzY + PANLmNbWzcM1aHDJm6yLdO6haQEjAvmG8/8NBIIaRp3E + xXChfOzkEz30rxfRi4Dzk+uU3c2qN/qmO9jcdYHB18ja + gteFAASSTK5JofeMqNMqbnd81l2wXbhC2gdok/dawR85 + kVCYOO8Bf0y8pTaZUrjX2b4UYR9fDf79kNP0oyvncn43 + u9kYdnh0q9PDKf1E0VYFt74P2ZTRQxDgd5pSglYe82md + FZhv0vgmjF+kykzlfFbftYughM6Wg8pvzMP+5luRj31e + vzrc0cTSzUWSCQMLmipkWg6RL7+ee0cuRSdSzQxYBvzd + 61uc5GYfw6Z20B7qlVAdcSDgyl49hrSIb7JZcpOHSVIV + dcQiOD8+00avphT2gH1IEm1ckMtTqObftwgrXiysQs4z + y42OtdWBclOATpn2h41lBiKUPRfLhiZRHDi2ewly6d9v + 2oHA4nzo2ydxK7IrmkQpG0HGuJwQL0aBK0eyu9tapo0G + BG2gprNitthlMleO3NlGOcID+2Zc2TFiLe0R3Qtj3Wk/ + Pvg1G1wchPi0uIgDBs+3GY1+EY7OBSTlRiQQXG7doQ68 + YyFfI9XDEJq2T5dfeSvQ/Ii+ERWDRge1uZ0p60oox6Bu + e8tZzo+yOOQD0uSqPtlcjjsbkGHykR3J0gBQLxxnuKF1 + 7odIY9oeScrJfsnVmnsE//XtllmcLgLhZj1jThqqcEJ/ + jg6Zk+q3vtk5L4t9c0HzNrDZYC8KnUPZ3xQVF5wYgBqy + UL7fIOtLfCzKmdWM1EZaKbpv2frwgs/updXRMFCT1do1 + 7FgznRruGobBbfW5Hzg9MAhnmOlqnHKgrDTLlsLyOUOY + PK2w1DkIWz6eG7lKN8JGwFgGjK60w9/3wMsmZzsX2aOe + sMtnjpxtJgx00ab7rEWp+HH8dpPq00butcsriePkpTQ7 + M65m6r1du+05vxscAxCazxCKigWK3B8+VBcJOuQSQ5w8 + uTbBoD5SexSvzun7MeCbLuI5p5B4WITXOhekn23sMwMs + St5+6iSANjtnNOY4DUikYTjkJ+Cc6kWR3h9MIlmh+Ros + DSRf+QyArypm/EAY5Xw9sHrGsQ+4lrbuEjvxKH5b5kI8 + QsrI5ktdxDSZn1WicbiMK+U1H46KJSaAeY9RwcudGoVn + pD2XvoD329/TgdgoQ6zrQ0cuXl/M5sCLzcmFBLJbJD0g + 5O+vMhhc4pF3Udy5Xxuuji8/xpa5Gkae2rwQL28P/ZCP + RZyazSOx0aK9TCDfBBkgwYzYYmcSXWk0bYYrs2Zracut + 3NnUN8efIJb8SnjRd6kCLWvMgSyRdU7vbTMfjpa66Mii + TF1avDiNJ6WRmHw6HgzOXE7MiKk5d2WEPC6h33Z/jGVp + iuFqMSajXetwUbc97nffiTxraaHnxAi8U+EL0X6uxyRd + xKu//fAfbpwy4W9MZzOEd9fkqomSQb1A6fDftsVhHP+m + 7rk+WIGYn6DKHSLqQMGnXdKG1VQxqbQZkXra2Z6Z47ok + XxavfUA8Vy7qiT3HDWDVAq5IKFnAO7pltkpYQ8KBRCrF + 0JWDPuXua23jyqNW9zUjGwGw3+hZ2dpGSuYIRGcnp8he + uJe85jkJ3YGeYXQSRPNHHZqiflA7PcVtHTaG0Oy6QDDK + 57sp7n6UOsON4S2xBmNkMJ3kXBlR227y21HrE/fnWtBA + B9Tsmrd4ydXisIW4qxKZzMkNoBQlE+68Y8zwZXaqRHQ3 + zIap916Zmdn5nAlWWDZWwA7VA6W02IAvjxQO7Q5V8wZ3 + lQ77cZJRA9udptfV/oWu8sI6U/w9Ju+DVAHmbn+Y0834 + TpGalDwKcWgrwdgL0UCd/VHRoLK+5fcPKz9Q1KXbpFWk + glZ9priGzXfc3M6rlM95tpgoabmjruGVnPIHYnAKl80S + v/1/gVOQf7cHsK5oKg2c9euXKSeouJMbDPd0DvtZrmGU + tiWZiXjvmuKajIhLO9AAtubYWMBjQkimw1/oo7xH9qys + Pr4nvv3S8gA3mbwstnePqO4h3iiZJLnkYrudRKNWq3w8 + qNPY63Vd6IVCR9bjySSOhwcXmvwEGe4Vtz/linzjEsgr + 75hMYT3xJDXiXk01azsXbHWAyz5aF+oQaz6G6PySQGUZ + GeN26qCNL4VWeFt7sGa36MnH5tJSczLO9yXMX3kbiqJh + j5ipDCgd0duhsfqnURiU7SmB4fYRuvfw5wDnHLfbuU6x + qwaW0IKYsBBtgvn+i1AvxhE5bwaMqyn2RdAgxMiRB8Af + X6LRBk0aOBcGahwmbLLxtLeGMD5jvbT4kkfA6u24Af3q + PXCKO07aP4YUyXMtrti89wnkzqaMACiul8PVfXeWuvGK + hBVJPf3zcD14fdDk/oeTZRlHyf5PD0D5cMbU1lVv+1Ld + vm7f+zoMXMv18If2pWpK8Nc6pqG5OuDa8mcdvR3iY6z0 + HpTQdVMUnH31Y6pncR6JYOc6DPXF7mvaizUvK5Jgl3Jx + BoZauBw5f1ZS4gC6TD1omkJETgmb2qKy8O14qDSpFBlm + gyCkXLacP8mK4xbM2KU4Tz9dm+jcuGH9GYWLERzkGir2 + ksbeDLR8zjOUwFAvJuHYC835rL7TeNI6Ieb5xqz2Z0OJ + 40hiaarxpXolNon00JvOLjo3GPvTE0d/pA+SRiXm1Ez0 + AtaBkbYywgbQYWbFZvQr88EATOnzaUrBHIYfjCAxT5RV + OHVzlhH35D2hhXD3fpbRpXGegXVG91de7bb5EZg5aHAG + 2qTfcOA/rYez4O8U/xh4RLIFL9ew9fulhfm1sUhKgPRt + e/BurazU6fAzlzNPZ3soA/sN6C0xwhR6InxUHr8WtrJx + 8ak+s+ISmQav7gwo9Nc4JF345HSUGgKZefJcKko5pOrs + cym8NDDEFhJDISItu5r8SV71heSho9lTXC15r980BxC+ + TNTlXSKp6ua8cZj3Mvn5/Zi32+I+eLqeAkbHiROZm0mX + vkgSeplFBp7K2WfeSY2N72AWcV2b9TdZ3KQ2MYTv3qJz + u57WMkwvMGfGRukfsGJwBxeFpJnVCJnDQ5wyPSXxkbIN + eAOhCKLnkqpZjKuivVz6TSNJ8TOhgjK38KhKQW4pRY9H + NwGR6VSNe2vxJQoOdslgVekl91Al+RlU5AVykyKLEycu + 60g+rjesTmDPP/Tr/b2tIqRmAJbcxM05baUFdkNAXi0j + 9uzjZtis2QQfqjLOIdSQUXWAQ3mafw3r3vNjofgOyVyS + cuSv10SKSxqqsZreix4ae6KX9kGsI0al/lyPA6qQuQpe + WG7HkjAmQc+AGemGMqruJd/xbRyp28guxkiVsI52ljHM + K9iu0jUKGQnH72Hr/InEAVxjk1s3/wrOjOsYha4mhOSt + Lvu3qH5NCqRDBOd69hzpKRu9QVU8MdbvYqbsz/WJI6yG + 8mTh5VFEhjkVb/QhXTWSrhoXsaqv8oQBk4Xde9v2lWzQ + j9QvwXKeulngVsf8dEqV8xJD6SLH+NoSLxAebk1qEItc + feZTzvEt57wWMOX+8zalFSDLkqEuTWd8ViQ9ZlSo5WV3 + AFbcKDcWvoyCF347IVA7y+FzWmTLbfSjSmtKIu/bX1d1 + WnlDZqL5oAPRcMh+Njp9Zh4uvnOBPnwoxnVvOpDrbhrx + fmF6tXzSjz2/y66mpNT2upQZBRATIKy9rn8fdC0WUSTS + yi2Br0JYKrw4ajm7QkoGIniQeZ+bbtqQyfu2lgMKUyeU + mHhj7vH441xYcj6bn6Umy5iY+oHb+JkrcWQmNKHA5dTg + OB35cC0/i9hB+jkOWAMGx4MJZ5Si9jCe9myhWZzuk+km + FsAueeg/HjYjNBEfYuMUMrpRIJpzgPQ7AolfUE9EieeV + 1CPzRZbl1EteDdD1RYd7wWo2qWwhbYMopGGTZtgpBZwl + dIxkSnRFwuaeqSq5h6FFriDbtvZAsl+smRVPgWQl3O6M + UQQfRS2Mqe4lfi1wi7znhGEGZnQr2zeoKfudbU4xrq7C + 6KcfCineZ66pRSqTF1ERpo5olierMsn7Q6sGvezb3umO + aGi5KmysL4CStBM/rMfk4UAJP8/JHOe8hj5BzJ0Vj2p0 + QH/icLnwxQXPlt3An6EoLVyfea2n+Xz5zBsPsFem3aE+ + MOyNuBT+Wi99iISUGjYCeoK0IPMxDowQlgO8bdL5frG8 + v3rGEidUYEkSX3kv/3dqg/m2+L/rHzaKZo09HQSLGaCF + BngxviUGzC7IRNdSwNGWiz5dvvALrkMDheqNb5Zs9KHV + nmzs4xyKNHh2rwziYD+qP0gtcvja7Q7rp/30JLUoh7lE + HSlox8LZvrhcKsX5Fj2tJ5y1gEAWOThhRsw7eVVS034G + Uue76HsHzNA+Sszh3v5tawcqVuXXkVCJPabPRjoEVTxz + 3Ngzp13qm1uQcdshmCBhSWZ0spKSjIVmSgJbKj+GRKBu + XV4+e2zFGMEfnnyJXWt91gErH/+22LQmROrWReucNmf2 + HWS0RGaL9OUehhrriV1Tt1Y5YD8A23DtErU+9NWCHcyF + 1KnL3CoYyNWKTPnptrqD8N7RaS28JOtDT9bi7hn/nTgz + alO6SUzBIa9TKSugQd9F/AHQfiMTSyEbz+RrWNWHlfQj + S5Kjuo0GG2kypc7jRDSVeHnZ6xAWvl/gpl+PU3RyALDo + oPJ97ETYH5hMpOJa7/AnlduBwQyd+Ix7Dg4+Z+rKQscN + Sxc/Gfb29OBIi1LUU+g3WqiMK34T1zF0QqzynMMVt/rz + eeB/R1ea9yO3FIQCvyNVTBOMbOwt32kSKraiRa1JZ183 + 0PYAOKoLy7eEC9h9n7JLXV2V/F/1O7/lU6RzB46SZUiR + 9Ye8wKfTlA3EZcc5LdWgZFG34kLEMr5Z6P5gOPcYuwae + QiMcBVYAb3Cce1uDsgLhSPJXHJfhQG5mEaKFfomNe++X + +fK8uYplGPjB0hxmJPIh4lFAqNhJhI6tozTyd/+KmJHH + sSniBG+LEcuR621TQVUf56mx6cCE5Pzxaee4faEPsC9X + YK6NonfXuOpEFkbH9mPsIUprwOE/s2MOBCg6yTgiQ6Ok + u+FNltMGm1mWkFqsgvkAUYTCvB2zYfV1qVxjf+VgyJ11 + oUHrbMJ+jZwKISKSnvTLAiq013mA5BJ4vDsDU4S5O9Uv + GRHmejmbYbfmGVIw50TwTnFJHIpyrwpkjZOqsJ1p/k/e + rUwwZ2OGxZ85qPTRTDEwCnJGSxKI7BbEfi7wbNT4OBKW + zlTmtr+uCWpRw6joQ76vyYWHtj0BrmMK2TYKsl6zZZFP + ARBCFGrO8hjpAkQ3k9oZ5p8KU7dWXspPwAgOESWllmOE + 4kUtuTWFuUtt77vo6Jy1Him/d8jQiNdVBcw+7gnTGBXz + zrljq65uBO2pzUBkdG5nkBXwK/161E5MXQb6bkXxPyJq + heGzvkVtIfTS/zAeswBO+WNXyGqONOfa7qaGl+IPnVaJ + PalQXuuka+IxsEMIwkw/In03x+Jb6Hud7p9qAaCxd9IH + rrNq73BkTw2GQAm7VTwm5nzE61WWwuh0XaKhquse0znP + xyBijVUAkyBvht7NaXA04wj8HX1sTDnSwH1RFDyQIMei + V2uVrqKFtyVfQLxNbn6YfXjbA8iwethkLGJGS5rXq/ay + pk8fs2rvYYywL48s+gcMgxDbfWu8rux8F9ymO/DM5sNJ + buCCcc+kYL4VMNAtM22CAZM0/OrAL8ItUXUsn0MvVAs1 + skDQuyZBPlPTmJ5Ta7DPXoHJikeMclNki6TjmROFuCM6 + 5rMa3pOTrb+UKh0ozqK8lrmYQVRJ8ZBfr48DkdgHDd8d + Kyb1ymSmGWd9dnS2eV62J+nd2nKIfZ0j1JiMY7cgESMe + v1kD3SXRdCLlen80L0sdLRjcFbzg7M2Pq6IV5W54tgt4 + LKgYettPhlMNoPeEvUProp+AkbWDfeptakwxgmYrRrhw + 9nhlbX9paKSZ9JQ/2skUknBPc2zc04qCL4ghXwcG8X4/ + a0DzaUBLiW35rp6WwqnmlndkwUeJ6VSiH113JjK3oyRg + dDQgHhdecffQysaWn0+03ccx8eVe3FMAknX8KYI6Q/iM + Uum+KsGcUH/Cza4qbSEZKERvc59jeN6rY1/J7U/JCown + jyKelYJ4ai0i2lMenpmzM9xkXw8amhubeCiAEDpklntX + 0nWuVYjSy2hzqo6N3KC4Py+0sY0tAqp23EYnatxCwYTr + aQUZ5CHW3SzsP4PjOLEhoixBuX3b/HjG8C59KN18cIcR + HdQU4IYMmkZV3DfxpEWxAwM3M+1sAA+ZHzYQB8I/OppV + 2YiZaHcDxDUO5aj98w3Qr1BbE3l89Z+tMWBIe/QigCA8 + JIOf032BQ+RM5Q5rzprOzyKCfCJIcwsSMv3cQpuiWPG8 + 79TmWzkd4Ayv9lKWbHY2eoTqieRc5B49fdtMAo94OFlV + zC6EY+823s6pkI0LiOuc5PRxRnhexSixsCrbsU7e/0DX + BX9vK4E2ShGs3EJFEbvshbuDQSFitds4HsotmIBvZH7T + UFqbKfVUyuQfdKd53mzZ9RwIVVOleMtjwfdSFGut15pU + J/RqcSAtYaObnc44EbeelmA5HzMfuji6GO+sN90UVD9J + +Wk6BPIefRf+JOof89byJuYS2IQ7cFckPa2Yjd8roWgb + uqNP5h8mVZf+SzMNwcHWIAHBxMZ7ymqLq4RcjriNzGUY + wv4hJsnsMGFJz7HPg3jxiNKe5RLsaF3volW1ROVyAs8f + OoAdAJasXh5SGbhW5jppCkNhrjJrfWsHI2tX8vbMVO3H + hr00mrx1Gaz7jcE88H2kQruDuqv0VdFIfeCIEzI9FoAh + 0xtj7IKBYhazOtIGXNr/3SDH1esUPgFbMz9KOBzdsamH + F32hva6NFI4FZHNnXmckB1eNiKD8fiGNN8NTg+K7rEJT + FXAWLDwbKQKjffZkQELfHGMubGct9jRkb4PcLkeY6G6a + ICxbIdWD/1oNeMUrO7ma42ii1k2gOeIocthJf6S7QRxU + 3sL7YCDSeL+qYRynyMRgYNbjGCKehdQsYvHLwFqgCPf5 + 9+dCKkK7Qu3u4hoUahircTW1jbe98jkjuo/qOgmUBT3S + j5dWR3wjV4EguKW1A936NxkGWMooVdxk2iV1jJkn8p1a + zsQAn4KhBH18sfzTR10zDxPC8pHEE9HyhOyVYsgiSh4V + 5X3aFICEYjb1LlxkycNuYv1Sd+PnUEMDTaFLgZyrj7pR + 5AKY4Kbb7cQTbCpxUbHSs4nie/Q2Inl22XQ6Mz7NTtQG + kNE7uUvOzc1J3OBl/vpyy3arKf6NfXIIKPD3I60pHzoB + 0OIPexhasJPHyBoQ/0P4k99JCBux6wt6scmRC6fUxvzV + FAf15Oo81W1Z51hLL30fFospXFPcknxo2FVxIs3yPvKJ + zBpOWBtLbznDHCf3IDPGoVQ1HuhguvFUylc0G7Z3rM5T + z3ORkHExX8V8Vb1ROFAOuo3X0jB8wzv+ir5bKykZXQmL + V01FQpF8Q+SvERgwNr1Gn8Gv5WVeoQ7XhA1pEmR+iOwK + VmH8LepXPQP9Ggm1fH/CSrjhMju+0YsrnIIuiiAWa/zw + ++guaPx02owWBd6FQVg7KrjyrWLdXmRwt1m8Hset7e7C + a3D1DttfOWFqrd87CE+2GSTR6WBptLGtWgsWkBsUx3kq + xtnW9t3eEDOIn3TmgRyQ4tekktczPS21FZwFLnx/s2dm + yEWAU1/2rswSSv83Hb+bKECbyFSLl4mKB89qjQ6vPYVu + hVwFer7xCyt6o5kh+/6MJ0Ts3lU0xqHgddsOxn3Vmtac + LwTBemQfIMo5CTOE222qeIuxXn9pxSN6/FpIBxHPUANH + fRzOS8G2/gSHX4cgP6JWPt1UYXWwY6aoeUj0jBWu4iwl + 8tNrI9W/8ELjji4IhIJB2zraowhL4ri81RogsCIyquaP + U5lvqD+y2glp7nD+eb8OhfaqsQAVIqZUm0oPgbqij2D8 + M2S2NSAmD1Fn4WzR8PtDN+6K7TJBP8qz/cNXIRcx8AZH + LYyhJ+oY4+mlxWVpyhM/K6VMJZ2757JMPNnuO8MwaGbj + xyoCfc0YPLHcdH9JI8x2QQtUwXb+kH8PtrEUcfm4BeXK + 0qjwCa7igKxA0QyzqG6WybelTNZYhSC0of1F1pN3eOqN + wtNvj4jN0R3iBG3wklEQ/ySh7RGdzaLqIRFpAudvZWVk + SnNYnmbEQyJFEv7o39kjvAPTL/Lw2oa0LHBdmgzueHZ7 + cb8avYCyuyiY4wf0cA+ZN7OBLmrzVuAffWNqf34yvTk1 + BcagiFN4idpmsjZWNu58L49LOPPO/HeVl9DBUqu1ISzi + TAPoEalrXmm/IDw65RAo7QuuEaUlxLFlrAvIUnbv6Ofp + nfkH4TgEwVDKwnlclvhV09NmhqUx2Zn7sSvbofNcvRPP + SNQrkLPRN8nScpYtr2dfoPQHCVI1mwxPfqd/pt9D0j64 + dfDM7gLYsxk7r7QeBF1f0d27vpQlYw3NNWFzV8rHhUwF + jwu+mc0REFuecKvuVk1ETajKX5uPnJ/wDK3dEHNQWYfx + O1lrlvqzyHhh4TJpjKn1FGIwCl7DsnBknkq/Ftg2MpE3 + 7bDsXbQTPVthfGoVwis46X7rf07zzFDQtLrDauZFKqVF + Xvq2JnMzIBuQKYoPZVJpI263kIznFrNex2dOiF1XfoRP + BN5KiwjgfQgQGbcDrRzaGScflHMAwhC/maZ/XH/RO7do + weNT0usHXBKdL5yuyeKJWN2WiNJUi4jYGH4gh9WOW88Z + YUQeOnQu7PiYhD9dGwJQF1L5Q8sgJXttoQVmc7hnQu2n + UdyO9zE+htxDuvmjS4up6rC0e1mmpbNcKZXzQf03iQIc + wmIT+9607OEw4p9c6efsFhwP8UE5hVplF1iVJ60MC8L1 + rhO90R47+S/xhvAr+BlY3bsOJdgAnacA4TAIPiwZ1HjU + 9Q533lQVU0ZaJhNZefomfmA4fi5OkC/rv73AMxIc0wtm + fZCAW06HrgTX/UJu6GmoPUF8XudtJcZIj9J20yepihji + 75pvJuzp0ELRB9uW8k+EqFZFtQyW4+WD8QQAAgEDBCDB + UpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eQ== + + kPCSMetadataiCDP + + kPCSMetadataiCDPArmed + + + SecureBackupiCloudIdentityPublicData + + YYGRMIGOAgECAgEBBCAXOlNsMQNVJQUY+dqcGt39XUTbDVT2ksgE + BMVvyOjkPaFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcw + RQIhAIL+1l8MsRW3rN9wMeM7tSinakp/c2/Dp2kO8Z8OZBxSAiAL + 15IC/CrJgkQLyS4rarGeTmMFKGz34i/jQ1AQHzQy0Q== + + + com.apple.securebackup.timestamp + 2018-09-28 19:45:25 + + SecureBackupStingrayMetadataHash + + BackupKeybagDigest + + LTrJHVHFZ5vQO59wUih1MEgg1qI= + + com.apple.securebackup.timestamp + 2018-09-28 19:45:25 + encodedMetadata + YnBsaXN0MDDTAAEAAwAFAAIABAAGXxAgY29tLmFwcGxlLnNlY3VyZWJhY2t1cC50aW1lc3RhbXBfEBMyMDE4LTA5LTI4IDE5OjQ1OjI1XxASQmFja3VwS2V5YmFnRGlnZXN0TxAULTrJHVHFZ5vQO59wUih1MEgg1qJeQ2xpZW50TWV0YWRhdGHVAAcADgDTANUBLAAIAA8A1ADWAS1fECBTZWN1cmVCYWNrdXBpQ2xvdWREYXRhUHJvdGVjdGlvbtMACQALAAwACgAKAA1fEBVrUENTTWV0YWRhdGFpQ0RQQXJtZWQJXxAQa1BDU01ldGFkYXRhaUNEUF8QGGtQQ1NNZXRhZGF0YUVzY3Jvd2VkS2V5c08RGs5kghrKMIIaxgRTAQA/LjzXYQ2ubBWTq3Rbqx8iuU7oCISCaqCfGfewvQch4TBFQa/EIha3eZBHT07JfrSM3jhozNg8A0uY1tbNwzVocMmbrIt07qFpASMC+Ybz/w0EghpGncTFcKF87OQTPfSvF9GLgPOT65Tdzao3+qY72Nx1gcHXyNqC14UABJJMrkmh94yo0ypud3zWXbBduELaB2iT91rBHzmRUJg47wF/TLylNplSuNfZvhRhH18N/v2Q0/SjK+dyfje72Rh2eHSr08Mp/UTRVgW3vg/ZlNFDEOB3mlKCVh7zaZ0VmG/S+CaMX6TKTOV8Vt+1i6CEzpaDym/Mw/7mW5GPfV6/OtzRxNLNRZIJAwuaKmRaDpEvv557Ry5FJ1LNDFgG/N3rW5zkZh/DpnbQHuqVUB1xIODKXj2GtIhvsllyk4dJUhV1xCI4Pz7TRq+mFPaAfUgSbVyQy1Oo5t+3CCteLKxCzjPLjY611YFyU4BOmfaHjWUGIpQ9F8uGJlEcOLZ7CXLp32/agcDifOjbJ3ErsiuaRCkbQca4nBAvRoErR7K721qmjQYEbaCms2K22GUyV47c2UY5wgP7ZlzZMWIt7RHdC2PdaT8++DUbXByE+LS4iAMGz7cZjX4Rjs4FJOVGJBBcbt2hDrxjIV8j1cMQmrZPl195K9D8iL4RFYNGB7W5nSnrSijHoG57y1nOj7I45APS5Ko+2VyOOxuQYfKRHcnSAFAvHGe4oXXuh0hj2h5Jysl+ydWaewT/9e2WWZwuAuFmPWNOGqpwQn+ODpmT6re+2Tkvi31zQfM2sNlgLwqdQ9nfFBUXnBiAGrJQvt8g60t8LMqZ1YzURlopum/Z+vCCz+6l1dEwUJPV2jXsWDOdGu4ahsFt9bkfOD0wCGeY6WqccqCsNMuWwvI5Q5g8rbDUOQhbPp4buUo3wkbAWAaMrrTD3/fAyyZnOxfZo56wy2eOnG0mDHTRpvusRan4cfx2k+rTRu61yyuJ4+SlNDszrmbqvV277Tm/GxwDEJrPEIqKBYrcHz5UFwk65BJDnDy5NsGgPlJ7FK/O6fsx4Jsu4jmnkHhYhNc6F6SfbewzAyxK3n7qJIA2O2c05jgNSKRhOOQn4JzqRZHeH0wiWaH5GiwNJF/5DICvKmb8QBjlfD2wesaxD7iWtu4SO/EoflvmQjxCysjmS13ENJmfVaJxuIwr5TUfjoolJoB5j1HBy50ahWekPZe+gPfb39OB2ChDrOtDRy5eX8zmwIvNyYUEslskPSDk768yGFzikXdR3LlfG66OLz/GlrkaRp7avBAvbw/9kI9FnJrNI7HRor1MIN8EGSDBjNhiZxJdaTRthiuzZmtpy63c2dQ3x58glvxKeNF3qQIta8yBLJF1Tu9tMx+OlrroyKJMXVq8OI0npZGYfDoeDM5cTsyIqTl3ZYQ8LqHfdn+MZWmK4WoxJqNd63BRtz3ud9+JPGtpoefECLxT4QvRfq7HJF3Eq7/98B9unDLhb0xnM4R31+SqiZJBvUDp8N+2xWEc/6buuT5YgZifoModIupAwadd0obVVDGptBmRetrZnpnjuiRfFq99QDxXLuqJPccNYNUCrkgoWcA7umW2SlhDwoFEKsXQlYM+5e5rbePKo1b3NSMbAbDf6FnZ2kZK5ghEZyenyF64l7zmOQndgZ5hdBJE80cdmqJ+UDs9xW0dNobQ7LpAMMrnuynufpQ6w43hLbEGY2QwneRcGVHbbvLbUesT9+da0EAH1Oyat3jJ1eKwhbirEpnMyQ2gFCUT7rxjzPBldqpEdDfMhqn3XpmZ2fmcCVZYNlbADtUDpbTYgC+PFA7tDlXzBneVDvtxklED252m19X+ha7ywjpT/D0m74NUAeZuf5jTzfhOkZqUPApxaCvB2AvRQJ39UdGgsr7l9w8rP1DUpdukVaSCVn2muIbNd9zczquUz3m2mChpuaOu4ZWc8gdicAqXzRK//X+BU5B/twewrmgqDZz165cpJ6i4kxsM93QO+1muYZS2JZmJeO+a4pqMiEs70AC25thYwGNCSKbDX+ijvEf2rKw+vie+/dLyADeZvCy2d4+o7iHeKJkkueRiu51Eo1arfDyo09jrdV3ohUJH1uPJJI6HBxea/AQZ7hW3P+WKfOMSyCvvmExhPfEkNeJeTTVrOxdsdYDLPloX6hBrPobo/JJAZRkZ43bqoI0vhVZ4W3uwZrfoycfm0lJzMs73JcxfeRuKomGPmKkMKB3R26Gx+qdRGJTtKYHh9hG69/DnAOcct9u5TrGrBpbQgpiwEG2C+f6LUC/GETlvBoyrKfZF0CDEyJEHwB9fotEGTRo4FwZqHCZssvG0t4YwPmO9tPiSR8Dq7bgB/eo9cIo7Tto/hhTJcy2u2Lz3CeTOpowAKK6Xw9V9d5a68YqEFUk9/fNwPXh90OT+h5NlGUfJ/k8PQPlwxtTWVW/7Ut2+bt/7Ogxcy/Xwh/alakrw1zqmobk64NryZx29HeJjrPQelNB1UxScffVjqmdxHolg5zoM9cXua9qLNS8rkmCXcnEGhlq4HDl/VlLiALpMPWiaQkROCZvaorLw7XioNKkUGWaDIKRctpw/yYrjFszYpThPP12b6Ny4Yf0ZhYsRHOQaKvaSxt4MtHzOM5TAUC8m4dgLzfmsvtN40joh5vnGrPZnQ4njSGJpqvGleiU2ifTQm84uOjcY+9MTR3+kD5JGJebUTPQC1oGRtjLCBtBhZsVm9CvzwQBM6fNpSsEchh+MIDFPlFU4dXOWEffkPaGFcPd+ltGlcZ6BdUb3V17ttvkRmDlocAbapN9w4D+th7Pg7xT/GHhEsgUv17D1+6WF+bWxSEqA9G178G6trNTp8DOXM09neygD+w3oLTHCFHoifFQevxa2snHxqT6z4hKZBq/uDCj01zgkXfjkdJQaApl58lwqSjmk6uxzKbw0MMQWEkMhIi27mvxJXvWF5KGj2VNcLXmv3zQHEL5M1OVdIqnq5rxxmPcy+fn9mLfb4j54up4CRseJE5mbSZe+SBJ6mUUGnsrZZ95JjY3vYBZxXZv1N1ncpDYxhO/eonO7ntYyTC8wZ8ZG6R+wYnAHF4WkmdUImcNDnDI9JfGRsg14A6EIoueSqlmMq6K9XPpNI0nxM6GCMrfwqEpBbilFj0c3AZHpVI17a/ElCg52yWBV6SX3UCX5GVTkBXKTIosTJy7rSD6uN6xOYM8/9Ov9va0ipGYAltzEzTltpQV2Q0BeLSP27ONm2KzZBB+qMs4h1JBRdYBDeZp/Deve82Oh+A7JXJJy5K/XRIpLGqqxmt6LHhp7opf2QawjRqX+XI8DqpC5Cl5YbseSMCZBz4AZ6YYyqu4l3/FtHKnbyC7GSJWwjnaWMcwr2K7SNQoZCcfvYev8icQBXGOTWzf/Cs6M6xiFriaE5K0u+7eofk0KpEME53r2HOkpG71BVTwx1u9ipuzP9YkjrIbyZOHlUUSGORVv9CFdNZKuGhexqq/yhAGThd172/aVbNCP1C/Bcp66WeBWx/x0SpXzEkPpIsf42hIvEB5uTWoQi1x95lPO8S3nvBYw5f7zNqUVIMuSoS5NZ3xWJD1mVKjlZXcAVtwoNxa+jIIXfjshUDvL4XNaZMtt9KNKa0oi79tfV3VaeUNmovmgA9FwyH42On1mHi6+c4E+fCjGdW86kOtuGvF+YXq1fNKPPb/Lrqak1Pa6lBkFEBMgrL2ufx90LRZRJNLKLYGvQlgqvDhqObtCSgYieJB5n5tu2pDJ+7aWAwpTJ5SYeGPu8fjjXFhyPpufpSbLmJj6gdv4mStxZCY0ocDl1OA4HflwLT+L2EH6OQ5YAwbHgwlnlKL2MJ72bKFZnO6T6SYWwC556D8eNiM0ER9i4xQyulEgmnOA9DsCiV9QT0SJ55XUI/NFluXUS14N0PVFh3vBajapbCFtgyikYZNm2CkFnCV0jGRKdEXC5p6pKrmHoUWuINu29kCyX6yZFU+BZCXc7oxRBB9FLYyp7iV+LXCLvOeEYQZmdCvbN6gp+51tTjGursLopx8KKd5nrqlFKpMXURGmjmiWJ6syyftDqwa97Nve6Y5oaLkqbKwvgJK0Ez+sx+ThQAk/z8kc57yGPkHMnRWPanRAf+JwufDFBc+W3cCfoSgtXJ95raf5fPnMGw+wV6bdoT4w7I24FP5aL32IhJQaNgJ6grQg8zEOjBCWA7xt0vl+sby/esYSJ1RgSRJfeS//d2qD+bb4v+sfNopmjT0dBIsZoIUGeDG+JQbMLshE11LA0ZaLPl2+8AuuQwOF6o1vlmz0odWebOzjHIo0eHavDOJgP6o/SC1y+NrtDuun/fQktSiHuUQdKWjHwtm+uFwqxfkWPa0nnLWAQBY5OGFGzDt5VVLTfgZS57voewfM0D5KzOHe/m1rBypW5deRUIk9ps9GOgRVPHPc2DOnXeqbW5Bx2yGYIGFJZnSykpKMhWZKAlsqP4ZEoG5dXj57bMUYwR+efIlda33WASsf/7bYtCZE6tZF65w2Z/YdZLREZov05R6GGuuJXVO3VjlgPwDbcO0StT701YIdzIXUqcvcKhjI1YpM+em2uoPw3tFpLbwk60NP1uLuGf+dODNqU7pJTMEhr1MpK6BB30X8AdB+IxNLIRvP5GtY1YeV9CNLkqO6jQYbaTKlzuNENJV4ednrEBa+X+CmX49TdHIAsOig8n3sRNgfmEyk4lrv8CeV24HBDJ34jHsODj5n6spCxw1LFz8Z9vb04EiLUtRT6DdaqIwrfhPXMXRCrPKcwxW3+vN54H9HV5r3I7cUhAK/I1VME4xs7C3faRIqtqJFrUlnXzfQ9gA4qgvLt4QL2H2fsktdXZX8X/U7v+VTpHMHjpJlSJH1h7zAp9OUDcRlxzkt1aBkUbfiQsQyvlno/mA49xi7Bp5CIxwFVgBvcJx7W4OyAuFI8lccl+FAbmYRooV+iY1775f58ry5imUY+MHSHGYk8iHiUUCo2EmEjq2jNPJ3/4qYkcexKeIEb4sRy5HrbVNBVR/nqbHpwITk/PFp57h9oQ+wL1dgro2id9e46kQWRsf2Y+whSmvA4T+zYw4EKDrJOCJDo6S74U2W0wabWZaQWqyC+QBRhMK8HbNh9XWpXGN/5WDInXWhQetswn6NnAohIpKe9MsCKrTXeYDkEni8OwNThLk71S8ZEeZ6OZtht+YZUjDnRPBOcUkcinKvCmSNk6qwnWn+T96tTDBnY4bFnzmo9NFMMTAKckZLEojsFsR+LvBs1Pg4EpbOVOa2v64JalHDqOhDvq/JhYe2PQGuYwrZNgqyXrNlkU8BEEIUas7yGOkCRDeT2hnmnwpTt1Zeyk/ACA4RJaWWY4TiRS25NYW5S23vu+jonLUeKb93yNCI11UFzD7uCdMYFfPOuWOrrm4E7anNQGR0bmeQFfAr/XrUTkxdBvpuRfE/ImqF4bO+RW0h9NL/MB6zAE75Y1fIao4059rupoaX4g+dVok9qVBe66Rr4jGwQwjCTD8ifTfH4lvoe53un2oBoLF30geus2rvcGRPDYZACbtVPCbmfMTrVZbC6HRdoqGq6x7TOc/HIGKNVQCTIG+G3s1pcDTjCPwdfWxMOdLAfVEUPJAgx6JXa5WuooW3JV9AvE1ufph9eNsDyLB62GQsYkZLmter9rKmTx+zau9hjLAvjyz6BwyDENt9a7yu7HwX3KY78Mzmw0lu4IJxz6RgvhUw0C0zbYIBkzT86sAvwi1RdSyfQy9UCzWyQNC7JkE+U9OYnlNrsM9egcmKR4xyU2SLpOOZE4W4Izrmsxrek5Otv5QqHSjOoryWuZhBVEnxkF+vjwOR2AcN3x0rJvXKZKYZZ312dLZ5XrYn6d3acoh9nSPUmIxjtyARIx6/WQPdJdF0IuV6fzQvSx0tGNwVvODszY+rohXlbni2C3gsqBh620+GUw2g94S9Q+uin4CRtYN96m1qTDGCZitGuHD2eGVtf2lopJn0lD/ayRSScE9zbNzTioIviCFfBwbxfj9rQPNpQEuJbfmunpbCqeaWd2TBR4npVKIfXXcmMrejJGB0NCAeF15x99DKxpafT7TdxzHx5V7cUwCSdfwpgjpD+IxS6b4qwZxQf8LNriptIRkoRG9zn2N43qtjX8ntT8kKjCePIp6VgnhqLSLaUx6embMz3GRfDxqaG5t4KIAQOmSWe1fSda5ViNLLaHOqjo3coLg/L7SxjS0CqnbcRidq3ELBhOtpBRnkIdbdLOw/g+M4sSGiLEG5fdv8eMbwLn0o3XxwhxEd1BTghgyaRlXcN/GkRbEDAzcz7WwAD5kfNhAHwj86mlXZiJlodwPENQ7lqP3zDdCvUFsTeXz1n60xYEh79CKAIDwkg5/TfYFD5EzlDmvOms7PIoJ8IkhzCxIy/dxCm6JY8bzv1OZbOR3gDK/2UpZsdjZ6hOqJ5FzkHj1920wCj3g4WVXMLoRj7zbezqmQjQuI65zk9HFGeF7FKLGwKtuxTt7/QNcFf28rgTZKEazcQkURu+yFu4NBIWK12zgeyi2YgG9kftNQWpsp9VTK5B90p3nebNn1HAhVU6V4y2PB91IUa63XmlQn9GpxIC1ho5udzjgRt56WYDkfMx+6OLoY76w33RRUP0n5aToE8h59F/4k6h/z1vIm5hLYhDtwVyQ9rZiN3yuhaBu6o0/mHyZVl/5LMw3BwdYgAcHExnvKaourhFyOuI3MZRjC/iEmyewwYUnPsc+DePGI0p7lEuxoXe+iVbVE5XICzx86gB0AlqxeHlIZuFbmOmkKQ2GuMmt9awcja1fy9sxU7ceGvTSavHUZrPuNwTzwfaRCu4O6q/RV0Uh94IgTMj0WgCHTG2PsgoFiFrM60gZc2v/dIMfV6xQ+AVszP0o4HN2xqYcXfaG9ro0UjgVkc2deZyQHV42IoPx+IY03w1OD4rusQlMVcBYsPBspAqN99mRAQt8cYy5sZy32NGRvg9wuR5jobpogLFsh1YP/Wg14xSs7uZrjaKLWTaA54ihy2El/pLtBHFTewvtgINJ4v6phHKfIxGBg1uMYIp6F1Cxi8cvAWqAI9/n350IqQrtC7e7iGhRqGKtxNbWNt73yOSO6j+o6CZQFPdKPl1ZHfCNXgSC4pbUD3fo3GQZYyihV3GTaJXWMmSfynVrOxACfgqEEfXyx/NNHXTMPE8LykcQT0fKE7JViyCJKHhXlfdoUgIRiNvUuXGTJw25i/VJ34+dQQwNNoUuBnKuPulHkApjgptvtxBNsKnFRsdKzieJ79DYieXbZdDozPs1O1AaQ0Tu5S87NzUnc4GX++nLLdqsp/o19cggo8PcjrSkfOgHQ4g97GFqwk8fIGhD/Q/iT30kIG7HrC3qxyZELp9TG/NUUB/Xk6jzVbVnnWEsvfR8WiylcU9ySfGjYVXEizfI+8onMGk5YG0tvOcMcJ/cgM8ahVDUe6GC68VTKVzQbtneszlPPc5GQcTFfxXxVvVE4UA66jdfSMHzDO/6KvlsrKRldCYtXTUVCkXxD5K8RGDA2vUafwa/lZV6hDteEDWkSZH6I7ApWYfwt6lc9A/0aCbV8f8JKuOEyO77Riyucgi6KIBZr/PD76C5o/HTajBYF3oVBWDsquPKtYt1eZHC3Wbwex63t7sJrcPUO2185YWqt3zsIT7YZJNHpYGm0sa1aCxaQGxTHeSrG2db23d4QM4ifdOaBHJDi16SS1zM9LbUVnAUufH+zZ2bIRYBTX/auzBJK/zcdv5soQJvIVIuXiYoHz2qNDq89hW6FXAV6vvELK3qjmSH7/ownROzeVTTGoeB12w7GfdWa1pwvBMF6ZB8gyjkJM4Tbbap4i7Fef2nFI3r8WkgHEc9QA0d9HM5Lwbb+BIdfhyA/olY+3VRhdbBjpqh5SPSMFa7iLCXy02sj1b/wQuOOLgiEgkHbOtqjCEviuLzVGiCwIjKq5o9TmW+oP7LaCWnucP55vw6F9qqxABUiplSbSg+BuqKPYPwzZLY1ICYPUWfhbNHw+0M37ortMkE/yrP9w1chFzHwBkctjKEn6hjj6aXFZWnKEz8rpUwlnbvnskw82e47wzBoZuPHKgJ9zRg8sdx0f0kjzHZBC1TBdv6Qfw+2sRRx+bgF5crSqPAJruKArEDRDLOobpbJt6VM1liFILSh/UXWk3d46o3C02+PiM3RHeIEbfCSURD/JKHtEZ3NouohEWkC529lZWRKc1ieZsRDIkUS/ujf2SO8A9Mv8vDahrQscF2aDO54dntxvxq9gLK7KJjjB/RwD5k3s4EuavNW4B99Y2p/fjK9OTUFxqCIU3iJ2mayNlY27nwvj0s48878d5WX0MFSq7UhLOJMA+gRqWteab8gPDrlECjtC64RpSXEsWWsC8hSdu/o5+md+QfhOATBUMrCeVyW+FXT02aGpTHZmfuxK9uh81y9E89I1CuQs9E3ydJyli2vZ1+g9AcJUjWbDE9+p3+m30PSPrh18MzuAtizGTuvtB4EXV/R3bu+lCVjDc01YXNXyseFTAWPC76ZzREQW55wq+5WTURNqMpfm4+cn/AMrd0Qc1BZh/E7WWuW+rPIeGHhMmmMqfUUYjAKXsOycGSeSr8W2DYykTftsOxdtBM9W2F8ahXCKzjpfut/TvPMUNC0usNq5kUqpUVe+rYmczMgG5Apig9lUmkjbreQjOcWs17HZ06IXVd+hE8E3kqLCOB9CBAZtwOtHNoZJx+UcwDCEL+Zpn9cf9E7t2jB41PS6wdcEp0vnK7J4olY3ZaI0lSLiNgYfiCH1Y5bzxlhRB46dC7s+JiEP10bAlAXUvlDyyAle22hBWZzuGdC7adR3I73MT6G3EO6+aNLi6nqsLR7Waals1wplfNB/TeJAhzCYhP73rTs4TDin1zp5+wWHA/xQTmFWmUXWJUnrQwLwvWuE73RHjv5L/GG8Cv4GVjduw4l2ACdpwDhMAg+LBnUeNT1DnfeVBVTRlomE1l5+iZ+YDh+Lk6QL+u/vcAzEhzTC2Z9kIBbToeuBNf9Qm7oaag9QXxe520lxkiP0nbTJ6mKGOLvmm8m7OnQQtEH25byT4SoVkW1DJbj5YPxBAACAQMEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5XxAXU2VjdXJlQmFja3VwS2V5UmVnaXN0cnnfECcAEAAVABoAHwAkACkALgAzADgAPQBCAEcATABRAFYAWwBgAGUAagBvAHQAeQB+AIMAiACNAJIAlwCcAKEApgCrALAAtQC6AL8AxADJAM4AEQAWABsAIAAlACoALwA0ADkAPgBDAEgATQBSAFcAXABhAGYAawBwAHUAegB/AIQAiQCOAJMAmACdAKIApwCsALEAtgC7AMAAxQDKAM9YQ2xvdWRLaXTRABIAE18QEFB1YmxpY0lkZW50aXRpZXOhABRPEQCVYYGSMIGPAgEEAgEBBCDX4Lqi2liRQKhXA2QYm0l7edIQPhVLwuk/TWLlyAT9PaFlMGMEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEgwRgIhAL2uoy74rk2RNImZA2BlpEt1lbYXDjQDLVWFl48ZiGflAiEArkFMxuEWlWOHBtNjjZ44fmxKxWsZi8+NGAHfBCd+IAVfECxjb20uYXBwbGUudGV4dGlucHV0LktleWJvYXJkU2VydmljZXMuU2VjdXJlMtEAFwAYXxAQUHVibGljSWRlbnRpdGllc6EAGU8RAPthgfgwgfUCASoCAQEEIO1UvRUh4/dXuAP2OSJpa7jHDF7bXm3c9qaZLQs2jZYhoGUwYzAKAgEDBAUwAwIBADAnAgEGBCIEICjCewMW8hJVh8JtsP/nRPnVlJnO3Th1oiXl90mmYjz2MCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTMwWqFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIhAIt+5X8e6Vvnhatzyk23WJszwgW43pe+QOOKOKvLLEZWAiAd9pVNkT8XZvTaHhdoA8GLVggO8wCjJzF33KVdAjVyvV8QEEtleWJvYXJkU2VydmljZXPRABwAHV8QEFB1YmxpY0lkZW50aXRpZXOhAB5PEQCVYYGSMIGPAgENAgEBBCAZ2Mqr74uDcAkMedabKkMBE1YVv3r9BY+ZQxiztbxuOaFlMGMEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEgwRgIhAJSI7dsRXpoxNc7bFCtPFSDwUrWlwNbNoa+j9VpBg/nqAiEAuj1iKHKO5ixZ92iBCwS6tta9CNYL8DZMMoJYhrkgLSBYTWFpbGRyb3DRACEAIl8QEFB1YmxpY0lkZW50aXRpZXOhACNPEQCTYYGQMIGNAgEHAgEBBCChFkKqgrWzOfMgBCCorBsVT8hy+zmWs15UbouBPzHsGKFjMGEEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEYwRAIgJUhOSBsTLydtk7Xu0V2PP7A+Q3VoDsDrJTGWbd8z01wCIE03dzox48zVifu5Uo5LPTqD5n1HxwNX21flE1bs+W8YXxAWY29tLmFwcGxlLmhlYWx0aC5zeW5jMtEAJgAnXxAQUHVibGljSWRlbnRpdGllc6EAKE8RAPphgfcwgfQCASwCAQEEIEL01a5kWCyuQN5cUMudqRaCgjgv9xfLP6bjeULYlZQkoGUwYzAKAgEDBAUwAwIBADAnAgEGBCIEICjCewMW8hJVh8JtsP/nRPnVlJnO3Th1oiXl90mmYjz2MCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTMwWqFjMGEEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEYwRAIgajftSwxdvsZot4HBh+DfTZNYa/TFszpcO6jGL9FfT1UCIE5IPiizk1f4ZNiot1F6sJNDl0RVJwhZpHqfjlIBMO5GV1Jhd2hpZGXRACsALF8QEFB1YmxpY0lkZW50aXRpZXOhAC1PEQD7YYH4MIH1AgE2AgEBBCAO/9RLJMcHo3qhFeFb3qanoK8t49rSDrm9ilPvAeiKJ6BlMGMwCgIBAwQFMAMCAQAwJwIBBgQiBCAownsDFvISVYfCbbD/50T51ZSZzt04daIl5fdJpmI89jAsAgEBBCcwJaAQDA5NYWMgT1MgWDsxN0Q0N6ERGA8yMDE4MDkyODE5NDUzMFqhZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCIEqa4Rq2iCw3ULDe3577bLpHuUyRvUDtEKE0rS7H4IIGAiEA4yG/enWyQuz+TacBVbe3U0cZ8mNarFnCWvjagNZ/BU5fEBxDb3JlU3VnZ2VzdGlvbnNQc2V1ZG9FdmVudHMy0QAwADFfEBBQdWJsaWNJZGVudGl0aWVzoQAyTxEA+mGB9zCB9AIBMwIBAQQgrzTyQdcce8f+FDq/uSB/9FM1Sl/kKb5ql+zgzpXjJKygZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiBnyilDS8GYaSIvTiKxLZK7Ae686XT0cf53PqXed2nqZgIgKyFAcdBAD7JRtU62B0izaNFwrReAtIoU0H2iTwQIsqhZTWVzc2FnZXMy0QA1ADZfEBBQdWJsaWNJZGVudGl0aWVzoQA3TxEA+mGB9zCB9AIBKQIBAQQgv6uQs7cTnM64Te8OT8U6trFqk03SERobf9vvoTbhqd+gZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiBAnAgyWAjqzPKgZ3QOwXhEIfIu9MHBSJN+L9IcgtVRHAIgHaRrjmDqvIgsnVwq2ZFDjgiyve33DvPQMWmg0OPa9ihaQWN0aXZpdGllc9EAOgA7XxAQUHVibGljSWRlbnRpdGllc6EAPE8RAJRhgZEwgY4CAQ4CAQEEINdOlpTfZX+WPGjvWza1yiNoWWvNZO73d26fN5jorlMroWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiEAzFPuXno+O0aMsz+srVMsB4maDlCSAi0yjvsVIfIwcf8CIGNHoY5q0UT4K1C5rPu4v4k0SgXRHT7UzKSgdFIeo8ilXxAgY29tLmFwcGxlLmljbG91ZC1hcHBsZWlkLnByaXZhY3nRAD8AQF8QEFB1YmxpY0lkZW50aXRpZXOhAEFPEQCUYYGRMIGOAgE/AgEBBCDyKeoxY5kg0jXZokvw9XIZk/dXsLybRdeGyOhCRXTz/6FkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIhANGlTEY7KpACQHm7qcSuuS/j63P5/AHuM/CFNtpxHPs2AiBB4iFuMmexGzcAdxjD8AweXzf3BuT2eAMPveTum/AsYVpDb250aW51aXR50QBEAEVfEBBQdWJsaWNJZGVudGl0aWVzoQBGTxEAlGGBkTCBjgIBFQIBAQQgAApHNADEW3GPIbDN5k5YGCaL6IT0o+kCI6NrQYRiRqGhZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCIByj6JhH8huGOaKq1FwtyCx/e3xWDS10/78Z8qZuJtzQAiEAzt7mRHE13w10++4iZXLTz51rbJFmhmXcWikhHUNRmgVfEBZCbHVldG9vdGhDbG91ZFBhaXJpbmcy0QBJAEpfEBBQdWJsaWNJZGVudGl0aWVzoQBLTxEA/GGB+TCB9gIBMgIBAQQgpX7w8xr3w20QI6XnHPfuzPon+MDv7XVkPLzm9dS9fqSgZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWUwYwQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEESDBGAiEA/g5zMFs3ClwqTTe7zg0qAhZ7jHh60Fdx3RO1uj7Se1sCIQDzZgGv6NIRmlaGUEDAzA8useGiC2Unr/qvh9Us8RVPT1hCdWxrTWFpbNEATgBPXxAQUHVibGljSWRlbnRpdGllc6EAUE8RAJRhgZEwgY4CARECAQEEIIjdeg4/gqiy7fDwz4QI9MwKeNszecuaMr/paUk5SgiBoWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiEAiDMjZtgfKpEcBClireWIjqO2fxlPW978/Pp65A/g0C4CIEHZ0hu2K7BLGBUiSojr31uFq5FE4eM72vjwWuOtMmVwVkJhY2t1cNEAUwBUXxAQUHVibGljSWRlbnRpdGllc6EAVU8RAJRhgZEwgY4CAQgCAQEEIF7MMhZ0znob8oFdqF6N0OD5bTo8hk5GrHzTwcGT4nZ2oWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiEA8XkD8dxJXiB+2Cn8k0m3didw3pRo7tZ83a4smkVVu0wCIF1vJvVH/v2rgCcy/4MUKxHbviP+dzhMEmXnaWJub6L2WUJUUGFpcmluZ9EAWABZXxAQUHVibGljSWRlbnRpdGllc6EAWk8RAJRhgZEwgY4CARICAQEEIGxGz1ZMgHL3aYgxV3pRG15JTGIDBGkcQqJPWTLQxk86oWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiBAODn1LywOgNLg6QUkoII4ij/SCQvLuiVsDR5ttGps5wIhAI41xTXyV6791UZyVY2A3gU9YgcxfdezpAPiH6GkkWz2W0FjY291bnREYXRh0QBdAF5fEBBQdWJsaWNJZGVudGl0aWVzoQBfTxEAlGGBkTCBjgIBJgIBAQQgKY6oKz6mSwVVKOEoS+1ZUF9eMywc4I4olT+pHlhOexuhZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCIGmjnKNWoi/Gyiyl7+FploOpEcExUI3WTEvhkSCZsXtaAiEAwHUsRvjfIqI1BXUQDJRqoMzGTFcSmQ4r4sn+ztGDkfVfEBNjb20uYXBwbGUucm91dGluZWQy0QBiAGNfEBBQdWJsaWNJZGVudGl0aWVzoQBkTxEA+2GB+DCB9QIBKwIBAQQgjumFy/X+D5JKBQkzmE3oz+ePP/p9kGC8nr/7/etLVUigZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiBtVhLAHrqTIUdb+/tUcVgeQKLJ24YJy7njNBU+MSGBYAIhAKJE9Ae6mvqUDCYFYicuPJiTsE2xU1XDfQrM9XG8Q+vsXUNsb3VkS2l0QXBwbGXRAGcAaF8QEFB1YmxpY0lkZW50aXRpZXOhAGlPEQCUYYGRMIGOAgEXAgEBBCAjsVTQ0pZmrzPCJAdrUjU8RDTgE57XNKIyvXPY0HkVhqFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIgfrBiTRmWf4KPF+HN26p3jCAjdIeTIySYCHoXSYnuDxMCIQDPm8w+aF9D5f8nZdPGAJgZGf7IfYYej7uksgAfWpiv6V8QF2NvbS5hcHBsZS5zaXJpLnByb2ZpbGUy0QBsAG1fEBBQdWJsaWNJZGVudGl0aWVzoQBuTxEA+mGB9zCB9AIBLQIBAQQgjiguBlj9OzF7ZybgF6clZEcK1wYRTH9XxL9RDS9hxRigZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiA+pB3ljZygNgkYh7TrLE4OyijDjTn+SvMJzrKQZPnfbwIgSkaV5AWx8zm23PUs+t1hHwIvtmeojmfr1Q1YqwGxa/xWR2FtaW5n0QBxAHJfEBBQdWJsaWNJZGVudGl0aWVzoQBzTxEAk2GBkDCBjQIBDwIBAQQgyW48v3kDee9VM/MD1rpChNEmWP0LyJQOBn5FctdNnwahYzBhBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRGMEQCIEqwVkXMaMdfwnbQoaA2F5mm4/GOL2WAUizoBzHSMCkKAiBJKuiiJo5b5pVgZHsMitI1MKksobbibibV7sdE1CiKWltpQ2xvdWREcml2ZdEAdgB3XxAQUHVibGljSWRlbnRpdGllc6EAeE8RAJRhgZEwgY4CAQICAQEEIBc6U2wxA1UlBRj52pwa3f1dRNsNVPaSyAQExW/I6OQ9oWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiEAgv7WXwyxFbes33Ax4zu1KKdqSn9zb8OnaQ7xnw5kHFICIAvXkgL8KsmCRAvJLitqsZ5OYwUobPfiL+NDUBAfNDLRVlNhZmFyadEAewB8XxAQUHVibGljSWRlbnRpdGllc6EAfU8RAJRhgZEwgY4CARYCAQEEIGoo/uNv5M+eGFOm/OIf0sbhoNrqLUgMsma0UGXu7sBcoWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiBhPW1rmcHkbUZFxxLNfKjzia/FvfFN6pJXQc3DfM/25QIhAOegBT7cu1cORUrifnW18tevddkhUTA8YiYEH+naobFBVU5vdGVz0QCAAIFfEBBQdWJsaWNJZGVudGl0aWVzoQCCTxEAlGGBkTCBjgIBCQIBAQQgiiKf8iak5uCLn/0lo/I9WEGums0ZqQmP2yqv4IjummahZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCIQDheScSZEg18OoTUhfXiZMLeXCkbDDFdybgySv3wRltZQIgAY2WdVPl88rRqeYtQOmIBO1VaUfW7SOv0EItomWxQAJfECFjb20uYXBwbGUud2FsbGV0LnBheW1lbnRzZXJ2aWNlczLRAIUAhl8QEFB1YmxpY0lkZW50aXRpZXOhAIdPEQD7YYH4MIH1AgEwAgEBBCDMr1rH/wSxKnXhhMuq2kmQAsbuu8aQ7CUjAaP7ltmt56BlMGMwCgIBAwQFMAMCAQAwJwIBBgQiBCAownsDFvISVYfCbbD/50T51ZSZzt04daIl5fdJpmI89jAsAgEBBCcwJaAQDA5NYWMgT1MgWDsxN0Q0N6ERGA8yMDE4MDkyODE5NDUzMFqhZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCIQC2O2y2BdX70rfntL/TRaSfQ2hi2HDlJRcDY4Ac7dTNDAIgMCCNLTjH3w3yanomcdUpUYpUXk0xg7rmWv776V2/ph1fEB1BY2Nlc3NpYmlsaXR5Vk9Qcm9udW5jaWF0aW9uMtEAigCLXxAQUHVibGljSWRlbnRpdGllc6EAjE8RAPxhgfkwgfYCATQCAQEEIN5dPjrSty+MgOnxokT64PDUkrKiyt3k5oI38p5AnL6SoGUwYzAKAgEDBAUwAwIBADAnAgEGBCIEICjCewMW8hJVh8JtsP/nRPnVlJnO3Th1oiXl90mmYjz2MCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTMwWqFlMGMEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEgwRgIhAM4B6CLjnTCbliTZC27uxJ/j+MZbMJZTRrgU9FBIKAJTAiEA2nI9I5z/KIIgh91hQusrBxnR2bvXR60pgU2K2u/xVHFfEB1BY2Nlc3NpYmlsaXR5Vk9Qcm9udW5jaWF0aW9uM9EAjwCQXxAQUHVibGljSWRlbnRpdGllc6EAkU8RAJVhgZIwgY8CATUCAQEEICY5ub8AyyEI+KyHDtmPlWoXunETPtY9gVChN01YLo+SoWUwYwQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEESDBGAiEApRyxYMo9vBC3ZMsebZvMNZNWDas5ituj7iwazSxPlqUCIQC/fHWNj8T/Fc0lt7HujLvHR0urgUaY0kUdYtCsNB0ZHFhSYXdoaWRlM9EAlACVXxAQUHVibGljSWRlbnRpdGllc6EAlk8RAPthgfgwgfUCATgCAQEEIN+LU3LnH9Fph0sdZb7EVs3D3RHlcJzmKwc3q52pobIqoGUwYzAKAgEDBAUwAwIBADAnAgEGBCIEICjCewMW8hJVh8JtsP/nRPnVlJnO3Th1oiXl90mmYjz2MCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTMwWqFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIhAKUXaMJ3HvqvjHbeLywEubqzKJBhiG8+YLZsS+fE+TFqAiBSD/AsQsZAyhF4PXZKKJCCUiAo23NK4KBF91SMBgHt9ldTaGFyaW5n0QCZAJpfEBBQdWJsaWNJZGVudGl0aWVzoQCbTxEAlGGBkTCBjgIBDAIBAQQgnoppjpqaZxLn0vbgK1JvD02fAEH1dXALMwjA/LiaDfahZDBiBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRHMEUCICMsr13SCWNkUUHAR6O1H/Ks2cKtxmB6isgm4d76IkdoAiEA/3IGnk6BOWe23sA+nrz1Uj0l8AXOzh9BSRcvtYqgnDpfEBljb20uYXBwbGUua25vd2xlZGdlc3RvcmUy0QCeAJ9fEBBQdWJsaWNJZGVudGl0aWVzoQCgTxEA+mGB9zCB9AIBLwIBAQQgWyKU+rabc+abidF3WG3EIjgU/SQ7R+KNVvXp9z+IST6gZTBjMAoCAQMEBTADAgEAMCcCAQYEIgQgKMJ7AxbyElWHwm2w/+dE+dWUmc7dOHWiJeX3SaZiPPYwLAIBAQQnMCWgEAwOTWFjIE9TIFg7MTdENDehERgPMjAxODA5MjgxOTQ1MzBaoWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiARBSYZikluYbi22N/VtgLjme7DMzsE5GvwZWjmA8P6jQIgTbLqYOOC+d6208tPiSLUATikDxTMkuIIDPt/MRIdaP9WUGhvdG9z0QCjAKRfEBBQdWJsaWNJZGVudGl0aWVzoQClTxEAk2GBkDCBjQIBAwIBAQQgnGr90u09c1SzPQfPLcly0+mORo0Q9owsw3ZSrGHX4bGhYzBhBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRGMEQCID8A1iTXEjdvswDeOx4NFHG58z0WxyQUdyaw6QThJ+6WAiArTTqC7lRMH6l+4wNn1+7KEFVH0+I/8t+AuQj6yGysS1NpQUTRAKgAqV8QEFB1YmxpY0lkZW50aXRpZXOhAKpPEQCTYYGQMIGNAgEQAgEBBCDcezl6FqtGyHkX174CEG8VSAOi4P3lIlFNO4qJfVX0saFjMGEEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEYwRAIgQvuSzR9rw1O2ySTcaQADxxJd1GuffZ2cxK1kGvS45cUCICC++3nOux4yl6TGku4P9QDla3NQp/7hH+lKmOIpvcOkWE1hcHNTeW5j0QCtAK5fEBBQdWJsaWNJZGVudGl0aWVzoQCvTxEAk2GBkDCBjQIBKAIBAQQgA2oLaQKK2tnS/GIAxrnRhrPUjQ303ZRJAJhXBA2FUe+hYzBhBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRGMEQCIGCGZznXFEVTtJoN5i5gdzHKRSLYk5abL9H4UjZbiWR2AiBF9jxPIXvjeD0ixKuBw4y9jVcBj1+5n14UEf5q3aw/pVROZXdz0QCyALNfEBBQdWJsaWNJZGVudGl0aWVzoQC0TxEAlWGBkjCBjwIBCwIBAQQgN2Zh4eSsuL19w0oUZ5VLkTxCC9ZP4OLbySW5BeSH1VmhZTBjBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRIMEYCIQDHk9qh4YVU22/9JheSDC5ZTgi+MJY0U01Ss3NrQ4XVSgIhAICVS3XDPdHft49emcZRdfeZJ6Xx7P/XaK9cBCIsXRI2XxAZY29tLmFwcGxlLnNpcmkua25vd2xlZGdlMtEAtwC4XxAQUHVibGljSWRlbnRpdGllc6EAuU8RAPxhgfkwgfYCAS4CAQEEIIzfihUm3ifzPM/Y3McNooAPAToGowS9Ztc9ecYuIl/NoGUwYzAKAgEDBAUwAwIBADAnAgEGBCIEICjCewMW8hJVh8JtsP/nRPnVlJnO3Th1oiXl90mmYjz2MCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTMwWqFlMGMEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEgwRgIhAP4c0nNzBSGf7ycZtiZpexiCNQ3kgYG6HAaSTCzdbrqkAiEAgdJu5Dufqn9GSOwo55U6rbllwv7eGJuIklki80Sq1JRfEB5jb20uYXBwbGUubmV3cy5wcml2YXRlLnNlY3VyZTLRALwAvV8QEFB1YmxpY0lkZW50aXRpZXOhAL5PEQD6YYH3MIH0AgExAgEBBCBjOqSZoGDwScKt5ncrZEkl/5e43V/wCItiOI3ffCu3XaBlMGMwCgIBAwQFMAMCAQAwJwIBBgQiBCAownsDFvISVYfCbbD/50T51ZSZzt04daIl5fdJpmI89jAsAgEBBCcwJaAQDA5NYWMgT1MgWDsxN0Q0N6ERGA8yMDE4MDkyODE5NDUzMFqhYzBhBBQBooabXxCiCkCbBNbvACGlyp96aAIBAQRGMEQCIBbcBuaykWaCE1IFXL/4nmckm8tSDLnSLUjeT2YtgVB6AiA7S+NREY9sOh3WrB5pVpmZfhd3Blv6JbeHkBsMjWDCUl5CVEFubm91bmNlbWVudNEAwQDCXxAQUHVibGljSWRlbnRpdGllc6EAw08RAJNhgZAwgY0CARMCAQEEIPTMF9d5k4kVLyhcz+Evysf0dozIoF4eg4ox1/Ay0Cj2oWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiBv/ZJx4OrvkvTubO81rciCeVSHyG+UACxMk/Ia2AUk3AIgY1aRKVg01AQZRBlH0YdWAhYwPxxxEqPPXuQy12glKQhZTWFzdGVyS2V50QDGAMdfEBBQdWJsaWNJZGVudGl0aWVzoQDITxEAxmGBwzCBwAIBAQIBAQQgwXd5uFhTeS7Kx8Qpj65nqUa2Rw8seul6PEhU0/LvW6agMDAuMCwCAQEEJzAloBAMDk1hYyBPUyBYOzE3RDQ3oREYDzIwMTgwOTI4MTk0NTI1WqFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIgfXzk2iTJUQyvhZKLb85CbowdarofTgcdwqpizaYq8tcCIQDieMFd3JCMHc5P2DZBmS6Ej/RocbKGN9MkCj6pGc0BEFhpTWVzc2FnZdEAywDMXxAQUHVibGljSWRlbnRpdGllc6EAzU8RAJNhgZAwgY0CAQoCAQEEIMr5O+MxnSPOECSWwa6jWdtSl8CxG60ieEJrS5eT8csDoWMwYQQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERjBEAiBoNoyLhIzMKe8exDIHiT3gFobrLfgVsHcsOUxPalrsRgIgckaB3CVttF8XJjOPTyiF9ekJFtyTlqRNsOQ7FFgh3IFeVFRZQ2FsbEhpc3RvcnnRANAA0V8QEFB1YmxpY0lkZW50aXRpZXOhANJPEQCUYYGRMIGOAgEUAgEBBCCNrMVagA0+ttQkY4NGtYqj49b4PHHV7YFaAHyVd9vodqFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcwRQIgAUD9nE+lBkcEnXyL0pcE/LE4diyBd/UbosjHyB5j22wCIQCUcJfgxHVChg8Ae6FjMuYjf7cVoyNf0YmuUEWkmwvoIl8QGVNlY3VyZUJhY2t1cENsaWVudFZlcnNpb25fEBBpUGhvbmUgT1M7MThBMjE0XxAaU2VjdXJlQmFja3VwU3RhYmxlTWV0YWRhdGHSANcA2QDYANpZRXNjcm93S2V5XxAsd1ZLYjEyZ093RUV0amFmVGMyUmd2RCtPTnROekZ0Wi92OW1Fa2YxRGQzaz1bTG9vc2VMZWF2ZXPfEBsA2wDeAOEA5ADnAOoA7QDwAPMA9gD5APwA/wECAQUBCAELAQ4BEQEUARcBGgEdASABIwEmASkA3ADfAOIA5QDoAOsA7gDxAPQA9wD6AP0BAAEDAQYBCQEMAQ8BEgEVARgBGwEeASEBJAEnASpYQ2xvdWRLaXShAN1PEQGhZIIBnTCCAZkEUwEA7mcfkI9joA5YRiHMKVPYdCl0EZbdHHSkd+XbtD7Mz1swmsOp0wrFLe6Vs8Fl/eLiARGAoFbEyqKuOqGBvVJcANDyON1SpccPYyE+m9Fv1N84BIH68b9LFxZu11g2wdpwAoLfHGAIpixj/l/ExdN1SejDh42zj68oMRJipC5Pzuy7Rsfo8hBqDgSCZQ0ASzcyZvd/r1eUVlkPdtfW3e1G8CiLvEJjalHXMK/q+ZkT5ix5RrImOK4L8KpwVcLyYf6RxPhvLtQIFuyDWZ/zcGeOQfXbEU0N3DEcM86jT5VpOVvbejiFABDV2auJtxAzcbPoimkyfQH6B0hb7J4MoUBqojYp3/WbXgd+xsZueOYaioaD5F47gGJJt68vV79KNCrerlvSaoAAFZMT3aj1EfjWzc2Q+XU2ugjdA7yNrxDXAtzteqcTbqVa7k48t+smmgQg1+C6otpYkUCoVwNkGJtJe3nSED4VS8LpP01i5cgE/T0CAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5XxAdQWNjZXNzaWJpbGl0eVZPUHJvbnVuY2lhdGlvbjOhAOBPEQGhZIIBnTCCAZkEUwEA7coGYUYS65YHnBubKFI66JIshlD/zcZadtS7UPht/gQw4Na60gEDpn3LLWAPmNzSU5aFq2i5FdGApmZz2ZjxJhKs34OzsSz2kh2Dpg1xkYYABIH6KTIPWejPTEmBIMu/M8MHedxNSBN92aCUaaFKlFpIEfr4ERxhq2+7aqBDUod+agFjj6BzEi4NBHu/j4LZsb4fcOMwq2G594K7cevsVg5hsWb800lTOnIWzgnPfk//T7CYB3S5UnPQnLtORz7gQZzWlqloHJSGltcXdt9nF5hOsawKZttCDaL60j00MtfeD0WO+aLl2BmD8syaCwNFRCG8zplq3ot9Anh6xzoeTGzljjuYmPQPAKVFkUNyBI81ZK04m9wxPUh164CPXdv2hsm+zGqNrTX1sny7hlcAVbMXspR54l7EpBlHw0hO9D+2wtrfI4cwtfSpKFG9oAQgJjm5vwDLIQj4rIcO2Y+Vahe6cRM+1j2BUKE3TVguj5ICAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5XxAQS2V5Ym9hcmRTZXJ2aWNlc6EA408RAaFkggGdMIIBmQRTAQD+0aNWKcvemMMRA9pFVsDUo4dRRagvLY7giYyVJk9DGjCPLe5WaLMKfACvgcKry1B7M5fpGavtRgR/gJdVDfQEK4qtMLiIjC2a+pa6TrwWHYwEgfrcVDNNsthPPweZ4CJ5B4Xu+Tf0c5xbWAki7icWTyfHWxz6wDnohZwVlgMfMmxq7KSPPix7NMT/jkKumXeqIKCcCB1Db19CcNmxBU4YKFkj4fzd03SWhu14Lg2zGTEQ5ZL5yw+8RhEQBxlYDPwLZyXYwQByuEqoBD7RDGKisfkKiJ/4z36edNEAA+ybDUw6oDsk15xF/BXr1bxKMAPx8lzHjqEf1p6Ed3R5WDFRnP2qhepVuM4QUvZnHVpi+pzbAbJYRQgOZ0JKh/cNhn9Tx48ZC15eNN25p60h9MM3z7iAT38A88OJU3PApplBg4ayGT4NnDvB505DCfTCBCAZ2Mqr74uDcAkMedabKkMBE1YVv3r9BY+ZQxiztbxuOQIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lTRkRFoQDmTxEBoGSCAZwwggGYBFMBADALK4P6VIMHF0WrlDwXMlkSmmiK4UrYTX70EjtqQRypMPHWinluqD956QYjJ14BmQKITJOVQ9s5S3f4x4Deby+FsKEdKIU9nGY2B81BvNT9aASB+U0dId7UXZWqfMDkQghIaEWmTl6Mz6EC3OlEG9OsmykhueFqliHomAw2ATUidz6p+6UyMW4csYOevYg8JwVpR2XDppW00D3j8dq/kMrLv2vD3/kvSGAZM+gQgaEvIiu3e2aJ3zuj+jm7lx0FyFHg6ngqhQsGCFbJQwVYsssL/L99M5igfhrOQiJcK5A1Hlxo4pirMp7uRYIYTijXNYa5n5/ly1fB7fnkvEpHI5rmeDQIsuGGacihlV/FRAu1rcJ1UL+w4+/gAUPnWWGWQyDJEWC33/LD+L4s6gyvP8Fzir9OrAaUhtWr7nlq9DuY18S3R7akI4xVP31zzwQgJH8/DbB4RLDJA8K/pSz+nX8BBr7PNwXtA8BvjsCNxlICAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5WEJ1bGtNYWlsoQDpTxEBoGSCAZwwggGYBFMBAPDFnDgLhUc74GG63drt3QYvw9VBWfaKjS9hHU4zO99eMDk0m2wKsoSGFnecJDcG8IeEEGTeWShHL/laSDi03OYIPXRfRgLau4lkJ3LS5SP0WQSB+eP37P0MM60iYXp+VNYrJISLFmwc3SvkLXXpIFRWCD9+ENvEGp4O3jdIWaPp3cogXKhyd5C+Zn5OmSKb3FBxaV4AtMMMU4Aw5k9MhwBDnr8IH9kJ4No6GxaeT8KR4sJqgiOEZbTFTMJ57+L4fMjPFmYoXrGRFzAYqkt4JlkZON3QUwigMx4Sj5UfNr2Rzk4iQ249xMKZ7tjI34zBSwvcIvg3LpPCtmumEauDeb6C0OQIryjv61v03uz+MKzm4AhLU1mWRE0JhEIzGu7hqgPKw98qFl1/k3FSI9QYYKbAiVE+pMmBL7/GOavaAmDDC8vuqNra1OeoH6tcTAQgiN16Dj+CqLLt8PDPhAj0zAp42zN5y5oyv+lpSTlKCIECAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5U2lBRKEA7E8RAZ9kggGbMIIBlwRTAQBPXIy3tf+0RvkMYIDYE8P3ODA9xrVmBM2IVp0LO081kTBDOW39aaiT3AEWdm0EXV5KgPBb6GTJZIeowtZvDueEMIYWwrmaHFdIPazKfZ3glgEEgfjd2sTR+RY576H+T+2WwDQr4xUriaMMZf5Ghv3toN74ArmFHhN3xM5M92KUx87ijkOlOgNDvDNUX61ip6wu+JlxMuVu0r7z44hvHHs6mtV3GnwvVRBxFEN7kyvMSmfJQZp39WYi+oFYldUf4hqotdMuGxVPVfBi9ozdDaCTeHcRgDrONMtQqX8ZqCIANKYlScv+zPp0jzV9eGy1xbAQu+/EzVWqkEhk9AncT1c81Nf3puDq12wfXHLN7OqKNqeFw6ohhxHx9u4+hy43bbQsk5nz2TSBBNhazBT1XvurDxMKIG7ooEvzaiYg1/nWgDdxehIyNAJAGdSX5AQg3Hs5eharRsh5F9e+AhBvFUgDouD95SJRTTuKiX1V9LECAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5WGlNZXNzYWdloQDvTxEBn2SCAZswggGXBFMBABGSg5qvbVq2huEN6LUJ8YQyv67PfpehHqbUNCRf4zwoMOLmtU9YPY/yAuDjpPTxFFEIseEeVWAk7LRPR7XVQuwIYTiGxVKfivJrN+iE43q10ASB+HoGSBviZC139p/VgkB79lHv3MOkm8RJirazbWH6rPOcfa4YWS2hGoOeZKO4av+Z70cgDdDDB9Q8VO04qXnE1s+MHuRUR1p9NNjzOE6jA3Iu/9PmevlAEMF8xfEsgF9dltlGZ7O/JiigiwljAX7I9g77tbGm+yyJ+HmR4jKtuW5PsObNpCP1+9nnunnjRqoT0tkMeWu7h0pLkP/jmE1BvL/9wM7G9Bs59IKZUu6XhVzQJvxcs2ITHlkFmz5VnPB3Q7Ic6aQm6l5AW16uUs5W4f+vKUzBwF2C1qlrFCxJILTYLv8wJuNOSw6lP6V29TMyJGyQG7LxqYnvBCDK+TvjMZ0jzhAklsGuo1nbUpfAsRutInhCa0uXk/HLAwIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lWR2FtaW5noQDyTxEBn2SCAZswggGXBFMBAC/aj6MRkzpaEJoPpOb/S/QytRVQyyPeCEqNEiJdoCFrMHvz04b+FMGAL2MtedSWJ1V0RqSIJVwod8DJkZ/x3gbdKcKHlXPEKbcOtA7Pfe3JxASB+D4t5omz0TG9dfJxs/g+AOW85v/fkmclvJV7K/b2/QqaUBFz98aftiKLBVdyfGIGYRZDZH6AfX3I40rpODRPvjZ6Blxtxak/PFK7w76cpBbbR7O6Hb/p9cjJ9R2JTig9JQq6dCwM7Eaw35vK0B7fF8QAkZgZlBrkf4a3g1sPpC2nln4u2CflDpQpjiVqNNo1MrrFaGrDcmIdPaAiT/D/o5ySmi2yO7ibLcuZCzKVRR6j/UTGAeRkE9J9fKtH1BDul0RIAUp9EjoONdiu14yWmXqhNA6pBfOx4tyS4Nc0YwBktgfZwHrP357bkHKP3sgj8SxwLKg2h7HnBCDJbjy/eQN571Uz8wPWukKE0SZY/QvIlA4GfkVy102fBgIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3laQ29udGludWl0eaEA9U8RAaBkggGcMIIBmARTAQAQnmzAB4p0aaUoHGjNJOmxML3vNV+338xa9iYV1UFqyTDRaBSRUeJ6Ba4coTnGmEBXBz3x8QevxZ3EN+tuDSTxf+hQECGMrT1AUF0oABPqwC4EgfkyJi+JAc64CcmYUhWUfqoyiK/4kfOCReXh+63BzBWgj+3xjxUTzWp5eA/o3rL2IX9WlFUaFWpoPuM2peNUXJyBavA5cdgXlXoeDEYgZ7v+UgjK2MDLRRuufghkafWEoaYUzf2viGgUWfhRgvXXBdOXfEIHEb423rq2cPa1lIy+VU6QGLVn+5bEWybu94NjMK95EjfzI4qZ2YbjOSd/D4BAXy1hxY4ph7f1MqHCA0Rh7n9Yj3/cLFZSrF30fSD3Bvo46VSOckQl//e6hgUtSkCVgvIM/wmUOoNp3VPEv3B1Sa34N6IcdMLvbAcK3RDVOe8cmEEGGJRHrHsEIAAKRzQAxFtxjyGwzeZOWBgmi+iE9KPpAiOja0GEYkahAgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eVpBY3Rpdml0aWVzoQD4TxEBoGSCAZwwggGYBFMBAIren1qPjibvrtAJoHi3Mi5IU4tlJzUovigqzD8Ku3C5MAw3wqdfbMfdYkVeujIzl58mnNit2eDXtGLtaUwPNDb3ym6CZ4A4CLBlxnYqR9EYlgSB+SFcR4rAvBSy5Ca06GL/c2TZLHLucYdb/f0QuNyBEPtVSGML8wpFBgn0TYP63+5hyE+KNJ0KabxG++UGz16B8wdk3pm6iWASA5bWEAa1UsCCNK8A4qQh/i6zzSZEXEKMkblbB9m2k9nuic9y+t9M3OL85g8bdrTxFn5bgo40D5IF/egNphdJRRfJRyEMlU0DsbOysIK63gpPdv11T6kv99UpaYWjFfO/2QpyrTKVW9Bd7hhTNtdu+Jr5fvN4IhDlIDKsw4TKjkiejFyIFtv5WKQc/lCqS2VRzZ2MwBSDvbKAx04Uhkf8AozhVaNj4WK7kvc8LTIPoibsvgQg106WlN9lf5Y8aO9bNrXKI2hZa81k7vd3bp83mOiuUysCAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5WUJUUGFpcmluZ6EA+08RAaBkggGcMIIBmARTAQBDehu166c2isPZKlk6kYH7zw6WpCAjiZhXMh6pjOsypzCOmBL4QxrIAISALLfSbBmRdX7LWbG1WjwnPmwAemuPfCKLIeu6vaq5CcuMknizzx0Egfny3/4qGlCzsFGZSChyjO1fxs2ika5zTxSrmEeIF5kvlDvaMe7zBEgL9JK7Paj5MdTIXwl26Hx+c5qcV1NNW+bixlU40IoIcXU7ZcDLmQ55hFjjf+iatLSsXIQuJJjUAFqXKQEIFBgf/lYLMYBCeHeHqzuVW5i9OmwWXP7DNbFeeEAfQdVJP0B/wI4SmJ3EBMBns5OkEBgP1Je8GZNrFKwHqw92FDzdYsYXPgP5bitrKaC5JEhBdRSPDQ9I/Ys8hpZqDDD/iERkanvg8gtA56I7MGN541vNN2vmvacgUJxCvWOZiHYRvZ+EH4eNTZaf0RfnJ3pU7Nd+oA4EIGxGz1ZMgHL3aYgxV3pRG15JTGIDBGkcQqJPWTLQxk86AgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eVtBY2NvdW50RGF0YaEA/k8RAaBkggGcMIIBmARTAQAiRETKF4ZMSnH3RiEHTO3eBbu/gmOCzZgX0rx8M50YVjAYMKQHhsHqP0VmvVkSDntQyOp2PCxQC2F7Ht49+WjTVafg/Nq0fWss7CMct9M77XYEgfk/kGbcDJpY8mpbXfw7PGx5l+TGZlrKMYra0exutGKC2HcCQ5S/Kxq1hyCYDNUV8FQhNzYXZ5Q4yVfTkur3wlYYlQ3XDHospgoICYhLLsZ9oMNJZ3fliVJFetgeXaaQOMalSRRPhEHZERWwEfo645czU0bewWtXczHstm3upa3yPx9unBP1LfqXvtPIkgw+7/GTLAbEtJQ/lQOOJvJ79nxPVISmrKKQ7H6vv9hjeJlzMiIpwNUkKTPFBsQYSRrhr2vyHflKAzm7LxvOM7+F5ciH06HFwq/ZtipBuWdsyO0vS8uqnaKFP1uUd/sllGtb/zpijSE7VXd7fXQEICmOqCs+pksFVSjhKEvtWVBfXjMsHOCOKJU/qR5YTnsbAgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eV1DbG91ZEtpdEFwcGxloQEBTxEBoGSCAZwwggGYBFMBANoDsK3M5Y5DwFh4EQAyeqPIHYC8sSin0VjallJ64rNeMOU7Mjv5tPa0DGGqqMyvdojXYioGVUuHsJ7Y50S9DCDX0LsRPN0Ve6xqwzt6BLienASB+VfAOuYKiJOZEO2YFPuGAzqYvM2XHzEj27LMOXz8tkXB9ddkW6EAD6Q0Vqn0QPr+qM7yFASxbd8h34WS6Xddz28cY2kio8Xf8S4XTFpN/VgHCJSEBU8rqwUtwtDbH6R9qFVY6DmiyP4r9XCCE44B4I1HEKF9etVmU1HKeAuxg+nhMVhjX3PZYe4xFzaLrUS+1tngTCCW3GtHDWqHp84fBHuLfwjXgblnthMdpGvimQURj0bsOKOU9lv4gjrt3WPosxYc6dQS2dAGwQ6ZhCCO/vHrzq1x6mF+6xLfRbXuWw72aDtYZjurCLrjjboivWneN81l3WTKjTmZOgQgI7FU0NKWZq8zwiQHa1I1PEQ04BOe1zSiMr1z2NB5FYYCAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5XxAgY29tLmFwcGxlLmljbG91ZC1hcHBsZWlkLnByaXZhY3mhAQRPEQGgZIIBnDCCAZgEUwEApcI++fPiMp2F7719sTxSJqaM6ee9DlujcuWuzM6tJVow1MYYRnnH8QbtORp2/ddi/I/oOoPNQ7y8LVOGFVyJoARvHXAuJbiyoT/PNy3FzHjbBIH5rEU6m8vdSuPs0ygcTuIPvXnGDYdkGzx4c39oflgmaFgUsuW++rH1HOa6cCgJ/lstbJUXRWhgoOMro9kMmgI89wzcd5DSBiG9UhQt9ZDVvWz262k5O01os9poHy5QWHECo4HqcfykUXLt/pQUo0QcQ9b4xGRis/X7vzpprRcK8M983alsaJH6Zeh87J6DDPajPfxHN/HPzB3D+GklTSbzm+WRA0d3Iea3wh5edoJl9HSqXgxx4UFnpQyz+Y9Yl467o7Yn42/C+2IvNFRQM98STxWssxamHdoHl5p1rUIUxseaHYCmdhvMUAslosNalc/pwDmXbrlFVqktBCDyKeoxY5kg0jXZokvw9XIZk/dXsLybRdeGyOhCRXTz/wIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lbaUNsb3VkRHJpdmWhAQdPEQGgZIIBnDCCAZgEUwEAhTriZPlk5ba8weQP8abhLwtXIMRdFUPlVDwmgqCY2U8w/ZpeoOaJ5wp+7NNBOQgGi88JCQfor7ChKRLSy0rdlAZDLKEHZiflNJMpqaRLDNMFBIH5Zo4hPORCAtqiKM6BZmXDM4ZnyqLNREjAw8SAyQKqviDGU5f55CavjkHluBLUzvddxRPue+IFc6+Yes+Rs6R0Xj9xZpprfAFk1vusLNajPhT+a4+ChnEtrp5c8keBz7xte8YgPINm9HyTERH4X/QrwHXE0un5d2iU5tE1Q9a+V9FctlUHl4DeEKk1cO6+UdckPo5l/1ozpxscvNptwgfla36ivuZQ8Nawz7Bc9s9EiFRvPa3EaHN1pJOMzJ3eWCqkFy+XheEaF6riryW/Ybl/prjzre3i0EKTzzXObnZ6OceTfOzMmPHKmCj56rjqharVhoo2e8zhwV0lBCAXOlNsMQNVJQUY+dqcGt39XUTbDVT2ksgEBMVvyOjkPQIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lWU2FmYXJpoQEKTxEBoGSCAZwwggGYBFMBAG26kq78j3vM6eU91omcumtqCKKfK0/fo8buyvJLf1E3MCuoxrigFshN7yrs8mBWbA+lte2gqtGRnwgMVOyzoPkrPk+QD+y7F0bC7huKrPHNkASB+Q1ThtNaRvEb1hWcTGJKuMR0x/lzz+jJItKaUW4qr715P0d4twlq+7HUXIBy61hLrttG+zDro66kWrcd8fS3gsnYYi4Jq/RvcUZvAJkZXGIqYA+PQ7L3eAReDZDVko7XOAOuOSMmQXR/hidiVkDrbm0/KRlhBEtsGgLrlJuOxX7TIHR99x34xsqRu3en+K56FOTYK2riK8/LgPXs00yXiWI+HSOACe9iwPBZ5WTTyfqdsHOQlk7iyhyo3APg0iYq3WCRhbrE4yYgZjwcxHx1k1PnRHHoUgjMSZ7CtLCmFMvBsfOjTAeU+6ivHc4L23qeweIor2OSoz4qzgQgaij+42/kz54YU6b84h/SxuGg2uotSAyyZrRQZe7uwFwCAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5VlBob3Rvc6EBDU8RAZ9kggGbMIIBlwRTAQDk3uWPUFMtQRE/nXFto3i6/CZoxi1g1l9e00Sq85dIvTCxs6Jq3n2+Ry3ea3bXVMGR7T0/xEFYPlKrOt1+G62qDzyyGoNW80+JgXMd8C/qzIMEgfij8cfPnXNhj0mE3AIdbwb/+ikfjYfOSVG6Vcs4XLbdDANFR+Ikhp7Y/pjyxNhsdTw1u4oFISizmLSyIh2oMPuVeLb9jry67pKTaM2dFlLax872o4UY7Bm/okYOHaLdgECm0OcRKvuGW8BnwdnKuXxJiLUg3pHQMdqWFMXSTH4r6Lvy7vKqKkEfqhR5hzoa4AViSRi3UTaizpvYzX4f2HjtKSXbWG9qH5QCcxelEe4OEVF01fLou1A+YqUo5K2noDBLclB9MS/WQR1S/btHYylCJvulDBcSfYvQwVBHhAWPVM8buE+Qc8jbmGi10Wh3R1XS/QsrpLYB/QQgnGr90u09c1SzPQfPLcly0+mORo0Q9owsw3ZSrGHX4bECAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5VkJhY2t1cKEBEE8RAaBkggGcMIIBmARTAQDcD+fhaHOfAX8u8vMCFMUETugjEqK8E2pTs5IToVMZZTDmktst3dSrvbFQ8fDicManuZib9o0rgn0EpuyCYoMs1XCWztqfGRImQDvTpcKxt2AEgfki399H04dYrO7yIcRp/thiFBJptag18lGllLUSQ1V70OiMkMl+DwTFxBCw+7olIsWFD5py88RaygrNbQ8ixVvmiKKpThZZ4AZRLktvEAQ0Z4AQ4mpudrQPuJZceSYQa1EqX6tpZJkCxcAalIobL15+yy0Ns0Y5w3iJ6+nwOdKQXBKhD4S+RQAxvUyiIIIIHQ0J+f4wrwsiDSD4yEEeneV/wcLwCJ76ByPmHNV6wx4bqWM454FUTwFLp9R63khahI2GFHIOjITRXmSNrgyvyFjlecHcbTvvRWgPBhiY9CPSOCsb6NLgBCxINbg+Sc3EuAoeT/tK0nu8nHoEIF7MMhZ0znob8oFdqF6N0OD5bTo8hk5GrHzTwcGT4nZ2AgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eVZFc2Nyb3ehARNPEQGhZIIBnTCCAZkEUwEAq92z+A2mGWeeOAh6/oSmx+1nNN8OVrv0OZFF9ACP0L0w3Tq7x0BsXOKji8FqrajsM0b/9vvFNDPKpeD0iM6qgjnOjXhTEVU35BNEd9eXuNpWBIH6NWYRYQLnDg/RX2JWnmomZjRrOIr058bkXVsn7nbECP5XP8UiniHnk1DchxDMlkkmckV9612PnxNyegWg29s0i1hf9s+NLrhk3KQEQ585xa6Ghc14F2oN8M6T1xMpK86u3bO7NeSVJXbst2LqeGFYf6nop176vubd+jrNAvMVemeCADoYLyDYLgNmAPrVfQC/THUMQVMC954K12m60I4xoenEvFOR6Vlg4wyuR9eJCcUhb4+iqBQO62xtbxakcQETMx4GBL/yy69NTEfA+hGKD0uTqiU1PTGmOtUrKTfH6X9y0aju9o0B5jAUMJ6rkOHunLQr6jYvW+L59gQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3kCAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5WE1haWxkcm9woQEWTxEBn2SCAZswggGXBFMBAKt0Mur+Q9Zvqn/voOmB5+uI31pFfEXpXsYscNrWPBnYMCenJjKgoLbzTvEvqPf7NkO8dYmO2fg9pdmEum6OUDLa9l8WbS+uPLypUF8PZvk3gwSB+NSxcQ9cse/8eKmKlUlIIliSUFR4I+ZXetxca3+0h/CTKpbgvw9t9q8N2hjayGyfQ3u2WQfdP9gUBL7d9R+e+MsugAOvX6+hCIGUA8PGmF8nux9GRJ1CL29LyaocSaJDvPqi68lWGadm/VRpgLUQrUiSZqPUkKgc2FQ8nkuRcHv+6k52E/+n+9H6yQXp9CDAdhegfWJodhHweZoCLWL0LIv4nnWdEqEoRIRC7/3ZDBUHxLAS+H1hoGXV1kiL2kA8P6/7daeUMQoBWsxGdz9jZmtwjjWHuA3Znc76wvaVP7J4HSpPFvsigfF4r6Kzb0gNryLTDcXKwT0OBCChFkKqgrWzOfMgBCCorBsVT8hy+zmWs15UbouBPzHsGAIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lVTm90ZXOhARlPEQGgZIIBnDCCAZgEUwEA5QBs7cwCbsgxb6+/WPrQqmz8PyGvRm1M9by43vPoXpEwIvaozyKcDGBuIUOKXPoZHm8qMLwCqjz3la7fD2E8zysNgHx8R94dZs6RTFm00Kd8BIH5+z6ZZmeFMqKu14NIZXFS4lpZ5wVa0dBMzkU34qNbdfzIGnOrtJdvTdBjlt7RBpwjdnxUOm9+v/7OqzfPvu7Jfs7knMiDYNdd4VV1RYSvXngW413oMoWQrgt7Di6D4yEXwB6iCTjo4eRzhwRKqGVXL+MBbzxKbQlQ5T5GmQO26dHeOW2bomPaRP7an00X2C82dZIO4ri0HO++9yhAOptmyos5C36lj4TASVuyHJddwmojRySv1ma4DezRxcCZzY3MF3ZjUIIKpIX5NzNCkFbCFYLz/YJ8vSmNm2TZC4FhwSEPI3M9BwqSdVXzVTO7I0CNU12UPyTaW6exBCCKIp/yJqTm4Iuf/SWj8j1YQa6azRmpCY/bKq/giO6aZgIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lYTWFwc1N5bmOhARxPEQGfZIIBmzCCAZcEUwEApFg3dOexxalj8nUrzt4S8lvykjPlpatoQaZV5jXHutow2+O3Yevp/vk2zN3BZA8Z57Rrirw/eSC66GQAIdaXTkQrQT/4pB6OiKxPo0t6Zy0tBIH4khoiH57Ia4E8v4OSvsWDJhdW+VG62anIBrNq/VjNYQGe0tNceaXA1xDmmCtATLQzjiZTcHCGXn5whPdXaNBnpWJZr5S2v6zFHbja5DQKAoJN9tX6SiHsnkjFKblN4FzcCXZwtcatnvzn7quAhczRe9MHaS6Fjx3sll9v/fhoVv59f8+NBoQxZKsEJVbJ3JiR2K5Gd5ddwMhckZjL2ukh2zheY7nH71M/0h+5tlvQD2JGAfGjjsIco0wMFkZRcB7TcnklYVrk+pn/Qvz8GAWmrThOJpwoNmYSgaSm+R2M4cL0KLSvuqyHjDHk0dDjXgoVU6FcHhuItnoEIANqC2kCitrZ0vxiAMa50Yaz1I0N9N2USQCYVwQNhVHvAgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eVROZXdzoQEfTxEBoWSCAZ0wggGZBFMBAGy4sFitGVvqnRO1UBf1YHOgmtOogGtCo5Qh8as32kFgME1Ma/ZsIvrBV52bSWUtZcY5n+w5M/5X6IM/qNgNHlDLU9r3gcOu+tMI0YNTlFRAEwSB+rlDPBh4cqnNb3ksAMK9TNo6Q6cNk9Shn4ymCJQ95QCgtEhLdtZvClnWWyvcCKSuVym5aZqme+Ins3kVslJuMGBNA2mUHdLjaQ3utzlOt+hsmwFzLydzWzWwYaF7Eu1a46eJbiat/x3NWdb/AbOf1VNHGigJR/zMSzSZwBbt8CszkqqarzNAJV7K2XfR2gTik8+nFaW+OnjOxpFzcmH6Ba4qZNl32CIAeGU0TCbLQG8PYgMXEnzelBNFWlWJPpHH3AuNZJv5LeckFzxLXrg4U2Rd+i7NPX5sEY68tuzt4M2LQvzdm3FyhL6jECR8Ove9jjQYzZMcr5HciCoEIDdmYeHkrLi9fcNKFGeVS5E8QgvWT+Di28kluQXkh9VZAgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eV5CVEFubm91bmNlbWVudKEBIk8RAZ9kggGbMIIBlwRTAQC33vXBbax4Y3VXJS1T1Sjbp/jl76fAlKU8O5mcnuTxjDCs5+39psW+kv0RCLnmt1oVxZkwD02bWSrIOejWVJzDtgOE9cU4Wa5EuJRx8lxW76UEgfjR9gVrpLBZpLUDh+kCZQsccmm4baTJr4RKccdkXDobqiTf2iPSOL8ZFNblaxaGMzGftgzOI3tlS4ibFNs0VDK9MTKY5UFrHFHowPsGD7KJ7+CVMdB0VQWXGc6KYjMLoCw8JtabxnsENMSvqLu3h/W2MO54BPsmPtTF71bZ5DPH/4n0luME9IHg7EdF+qlFzsN4wwZNnL98BAo0PpUAxg92GdQBEbECTORR/yACYkPedz+/00adTpMu3FGMTK0pJCFTL0DrPJdgzErufK/np1M8wafGDy4g500iLEAMiHLlZ5X+9Syfexpswc/u3Jdycy0HHJrCOCwvXgQg9MwX13mTiRUvKFzP4S/Kx/R2jMigXh6DijHX8DLQKPYCAQIEIMFSm9doDsBBLY2n03NkYLw/jjbTcxbWf7/ZhJH9Q3d5WU1hc3RlcktleaEBJU8RAdRkggHQMIIBzARTAQCXSlsz5M3/DLJ3LwoC2oHZFrvf2UpO6U65RLBuc2HfrTD4vA8PKYYeTPxv2pvwbwJDKxPKuaL5xdun1Zjw+lanFJ+vMrvyYYSPlos9UQddTSwEggEsr1H8WcrXyturoCCaMZmJ3omU/MG+8Y3oLvd6ZsF4xigAtHLFD8Nk6TjiPNw/fUth9I4Kj5DcwQqIhN0DbCnxyy6lhGH9TVuIWCyKf4p4aLtZyEHcZe+wTZeLK+qnvx7hXbSdWKGwaMd8AaAnep7smMkHF+zz5KiPF9ZEaUKuOOcVr7JjRXNeCoQsQo/5jZi+k+hLGrk1hZNsiQXb2aU9PyxsjSNbah1jVw3O48oJASmcr2jxp2o5Ih7pGr7C1RVFoC43Tg0JBkPyhV+PFN08arYReVtTH7mmjgr/IInMDjAE41HqfHNzwCwXSvJxKinVlpgw42syNCO1HX8m9Vmc2dlYFIO8HP/viB1E+6LSMbZ10qu5sjWlntOgQse13DlZ0ZFv4tWQOdxyGilwBCDBd3m4WFN5LsrHxCmPrmepRrZHDyx66Xo8SFTT8u9bpgIBAgQgwVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3lXU2hhcmluZ6EBKE8RAaBkggGcMIIBmARTAQAf+QXYIadowXsR5jmWz0V3lZK+6DKzqRB0vFdT367TGDD1mgeHWfq2X+XxONWfrwh+pwpS1uQYSBzCA+PujKQGcOVQnEQF1b8u1aV4XxenZjUEgfnNpqS2O0c7HiRtdY8s0o50X/Mt+Iacjfl+nNJnMsPsXV5qdtVogDFZw007/zdDuqKuNw47LyZTd01CYTr7HujAfUGnGT3sgldyovrZCby1t5Ab4rbDmKr5fsJljPHAqWjenDl2DO4FI+/uWVhyyOXOWJ7fNgMcUcOleG0kz+mAIZxnTHEkOLTA795Jzx5b7p5rtL0XzdpOIriUOI2X0OcNyjASldH2YHO9ZHJp/zJc79HbDBlsX1fjt5h94HuvYBmbKGehB212h63QDbsKnqOm68EW8uIupHZ0OFE6dj/YuyW6JjqpNyya1yg6WIc2NeRVdBZGLMMDZk4EIJ6KaY6ammcS59L24CtSbw9NnwBB9XVwCzMIwPy4mg32AgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eV5UVFlDYWxsSGlzdG9yeaEBK08RAaBkggGcMIIBmARTAQDFQfsYDNaI/OfOJ5wDDLVYGBdL6Nh3dY83ZtgyiXtkaDA4+baJ86jsz2zNb1yOX90jckzjX1x7bJaiD9NsUnZwBYql8HdawMTRzI+tQFgcgnoEgfkiYhn00ER0ys97XMqWsUsSfA7GdwkJ6ftGtB3f9u1ZIbjaxokjXRmTyVBJbT1gYnvGHxg1CnYg5YoHK2bF29H2MC52f/zPjDs1daqF+pimOvNWYbmfP1dPG3vkMHNujOqxi8pVBZ+ar8LsVdE8/3B7btIpeM02cyCTa7qKty6b61af05+0QQCzQRcZwjfRiqhMpyAux/IYaVOwbkL0/0J9/Ok62vNj6emsHFlKYhJwriIVPHo3zD6P1LeVB6pMu2G8EfoNNzrSkIIXg6fGBak/086b0iW0KCj1Ym+WUgYjlPVZPsLtKAynGxwu7zhoKsMRR3GMvxKk0EwEII2sxVqADT621CRjg0a1iqPj1vg8cdXtgVoAfJV32+h2AgECBCDBUpvXaA7AQS2Np9NzZGC8P44203MW1n+/2YSR/UN3eV8QJFNlY3VyZUJhY2t1cGlDbG91ZElkZW50aXR5UHVibGljRGF0YU8RAJRhgZEwgY4CAQICAQEEIBc6U2wxA1UlBRj52pwa3f1dRNsNVPaSyAQExW/I6OQ9oWQwYgQUAaKGm18QogpAmwTW7wAhpcqfemgCAQEERzBFAiEAgv7WXwyxFbes33Ax4zu1KKdqSn9zb8OnaQ7xnw5kHFICIAvXkgL8KsmCRAvJLitqsZ5OYwUobPfiL+NDUBAfNDLRAAgAFQA4AE4AYwB6AIkAngDBAM4A5gDnAPoBFRvnHAEcoBypHK4cwRzEHV0djB2RHaQdpx6mHrkevh7RHtQfbR92H3sfjh+RICggQSBGIFkgXCFaIWIhZyF6IX0ifCKbIqAisyK2I7QjviPDI9Yj2STXJOIk5yT6JP0llSW4Jb0l0CXTJmsmdiZ7Jo4mkScpJ0InRydaJ10oXShmKGsofiiBKRkpICklKTgpOynTKd0p4in1KfgqkCqcKqEqtCq3K08rZStqK30rgCx/LI0skiylLKgtQC1aLV8tci11LnMuei5/LpIulS8sLzgvPS9QL1Mv6y/yL/cwCjANMKUwqzCwMMMwxjFeMYIxhzGaMZ0ynDK8MsEy1DLXM9cz9zP8NA80EjSrNLQ0uTTMNM81zjXWNds17jXxNok2pTaqNr02wDe+N8U3yjfdN+A4dzh7OIA4kziWOS05Njk7OU45UTnoOe058joFOgg6oTq9OsI61TrYO9g7+Tv+PBE8FD0SPSE9Jj05PTw90z3dPeI99T34PsI+yz7QPuM+5j99P4w/kT+kP6dAP0BbQG5Ai0CUQJ5AzUDZQUhBUUFUQvlDGUMcRMFE1ETXRnxGgEaDSCdIMEgzSddJ20neS4FLikuNTTBNN006Tt1O6E7rUI9QmlCdUkFSS1JOU/JT/lQBVaVVs1W2V1pXfVeAWSRZMFkzWtda3lrhXIVcjFyPXjJeOV48X+Bf51/qYY9hmGGbYz5jRGNHZOtk9GT3Zppmn2aiaEdoVmhZafxqBmoJa+Fr6WvsbZBtn22ib0ZvbQAAAAAAAAICAAAAAAAAAS4AAAAAAAAAAAAAAAAAAHAF + + SecureBackupStableMetadata + + SecureBackupUsesRecoveryKey + + SecureBackupiCDPRecords + + + SecureBackupEscrowDate + 2020-01-31T03:07:40Z + SecureBackupRemainingAttempts + 10 + encodedMetadata + YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ== + label + com.apple.icdp.record + metadata + + BackupKeybagDigest + + yFGtyxY2ZzDt0j/26GkNSmrgVnY= + + ClientMetadata + + SecureBackupMetadataTimestamp + 2020-01-31 03:07:40 + SecureBackupNumericPassphraseLength + 6 + SecureBackupUsesComplexPassphrase + + SecureBackupUsesNumericPassphrase + + device_color + 1 + device_enclosure_color + 1 + device_mid + yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X + device_model + iPhone 8 Plus + device_model_class + iPhone + device_model_version + iPhone10,5 + device_name + iPhone + device_platform + 1 + + SecureBackupUsesMultipleiCSCs + + bottleID + DD5E3F9F-3702-4789-8ACF-2D28BC86A94C + bottleValid + valid + build + 18A214 + com.apple.securebackup.timestamp + 2020-01-31 03:07:40 + escrowedSPKI + + MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC + Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b + 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj + Ug+fyh0c0xABOXt2Kdup7IYTGrzn + + peerInfo + + MIIErjGCBGEwFAwPQ29uZmxpY3RWZXJzaW9uAgEDMCsM + D0FwcGxpY2F0aW9uRGF0ZQQYGBYyMDIwMDEzMDIyNDEy + Ni4yODAwNTdaMFUMEFB1YmxpY1NpZ25pbmdLZXkEQQTl + vn18gJwjGum8v3Chn9Yh5HM/VRLGuq6HAV4KyxlUm+w8 + uF80+32tY3/l9nKOmU61691beekwSWcfF+mDTGPrMFgM + D0FwcGxpY2F0aW9uVXNpZwRFMEMCIGOIXWe83FnflHu+ + yShdjivfTaPDFHvX+RYNgMy74iSnAh9OHeQzmDchZOi0 + 81lbhw/9rjEe8wEmozXX126RUOe/MHAMDURldmljZUdl + c3RhbHQxXzATDAlNb2RlbE5hbWUMBmlQaG9uZTATDAlP + U1ZlcnNpb24MBjE4QTIxNDAWDAxDb21wdXRlck5hbWUM + BmlQaG9uZTAbDBZNZXNzYWdlUHJvdG9jb2xWZXJzaW9u + AgEAMHwMF09jdGFnb25QdWJsaWNTaWduaW5nS2V5BGEE + oLohYY3GpRSv20AT67jLJ1s2dKr+1bT8JoY23QkCeJgj + GNb+vutEQhLFjLPsENtNE7+NA7wgac0QAXLDO9H/LbpN + UP8DF1Q0NpFX4JiFZqG876jS8HEgR6VOOJzhJzUZMH8M + Gk9jdGFnb25QdWJsaWNFbmNyeXB0aW9uS2V5BGEEDRnS + sPQ/mTEl5dmMEYnQYhcm9hiPzBnQ0ghQzb70auYoPbCR + xjCoG7MCpbb+4JGM4L74OdbJZJbTtHeZ0JtCbqo93ZyI + fULWz131HsOyxowTSSI9yDiPAyXZz6nRnnvnMIIB+AwQ + VjJEaWN0aW9uYXJ5RGF0YQSCAeIxggHeMBAMDEVzY3Jv + d1JlY29yZAUAMBwMDFNlcmlhbE51bWJlcgwMQzM5VjIw + OUFKOUw1MC0MCUJhY2t1cEtleQQgZlnxFs5NJO9YlR/4 + SDWH+e9rD/+Jf7lWWjMoTW9+n68wYAwMTWFjaGluZUlE + S2V5DFB5V25JOHZkTmc2RVdheWVXL0ZQNGNEWlJzZTNM + TW44UHhnL3gvc1B6WkpJUzVjczNSS280L3N0T1c0Nm5R + OThpTmxwU0hyblIwa2ZzYlIzWDCCARkMBVZpZXdz0YIB + DgwHQXBwbGVUVgwHSG9tZUtpdAwHUENTLUZERQwJUENT + LU5vdGVzDApQQ1MtQmFja3VwDApQQ1MtRXNjcm93DApQ + Q1MtUGhvdG9zDAtCYWNrdXBCYWdWMAwLUENTLVNoYXJp + bmcMDE5hbm9SZWdpc3RyeQwMUENTLUNsb3VkS2l0DAxQ + Q1MtRmVsZHNwYXIMDFBDUy1NYWlsZHJvcAwMUENTLWlN + ZXNzYWdlDA1QQ1MtTWFzdGVyS2V5DA5XYXRjaE1pZ3Jh + dGlvbgwOaUNsb3VkSWRlbnRpdHkMD1BDUy1pQ2xvdWRE + cml2ZQwQQWNjZXNzb3J5UGFpcmluZwwQQ29udGludWl0 + eVVubG9jawRHMEUCIES5okyKP4YMZqDjIGRMoLE83SYh + zjEyOvGPA0BoF6ViAiEAh6/dd57K+JBWmGXd4v4qGELp + vAeSjqcRUfdLtQj4DxI= + + serial + C39V209AJ9L5 + + osVersion + 18A214 + peerInfoSerialNumber + C39V209AJ9L5 + recordID + sNs6voV0N35D/T91SuGmJnGO29 + recordStatus + valid + silentAttemptAllowed + + + + SecureBackupiCloudDataProtectionEnabled + + + + +""" +#endif diff --git a/keychain/ot/tests/octagon/OctagonTests+ForwardCompatibility.swift b/keychain/ot/tests/octagon/OctagonTests+ForwardCompatibility.swift index 67c3928f..c8f7501b 100644 --- a/keychain/ot/tests/octagon/OctagonTests+ForwardCompatibility.swift +++ b/keychain/ot/tests/octagon/OctagonTests+ForwardCompatibility.swift @@ -8,7 +8,7 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { let peer1ID = self.assertResetAndBecomeTrustedInDefaultContext() // Now, we'll approve a new peer with a new policy! First, make that new policy. - let currentPolicyOptional = builtInPolicyDocuments().filter { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }.first + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") let currentPolicy = currentPolicyOptional! @@ -46,8 +46,9 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { osVersion: "something", policyVersion: newPolicy.version, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing the second peer") XCTAssertNotNil(peerID, "Should have a peerID") peer2ID = peerID! @@ -91,7 +92,7 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { voucherSig: voucherSig!, ckksKeys: [], tlkShares: [], - preapprovedKeys: []) { peerID, _, _, _, error in + preapprovedKeys: []) { peerID, _, _, error in XCTAssertNil(error, "Should be no error joining") XCTAssertNotNil(peerID, "Should have a peerID") joinExpectation.fulfill() @@ -118,9 +119,13 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { return nil } + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) self.wait(for: [updateTrustExpectation], timeout: 10) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() } func testRejectVouchingForPeerWithUnknownNewPolicy() throws { @@ -128,7 +133,7 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { _ = self.assertResetAndBecomeTrustedInDefaultContext() // Now, a new peer joins with a policy we can't fetch - let currentPolicyOptional = builtInPolicyDocuments().filter { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }.first + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") let currentPolicy = currentPolicyOptional! @@ -166,8 +171,9 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { osVersion: "something", policyVersion: newPolicy.version, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing the second peer") XCTAssertNotNil(peerID, "Should have a peerID") @@ -204,7 +210,7 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { let peer1ID = self.assertResetAndBecomeTrustedInDefaultContext() // Now, a new peer joins with a policy we can't fetch - let currentPolicyOptional = builtInPolicyDocuments().filter { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }.first + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") let currentPolicy = currentPolicyOptional! @@ -268,12 +274,13 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } func createOctagonAndCKKSUsingFuturePolicy() throws -> (TPPolicyDocument, CKRecordZone.ID) { // We want to set up a world with a peer, in Octagon, with TLKs for zones that don't even exist in our current policy. // First, make a new policy. - let currentPolicyOptional = builtInPolicyDocuments().filter { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }.first + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") let currentPolicyDocument = currentPolicyOptional! @@ -289,18 +296,43 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { XCTAssertFalse(currentPolicyDocument.categoriesByView.keys.contains(futureViewName), "Current policy should not include future view") let newPolicyDocument = try TPPolicyDocument(internalVersion: currentPolicyDocument.version.versionNumber + 1, - modelToCategory: currentPolicyDocument.modelToCategory, - categoriesByView: currentPolicyDocument.categoriesByView.merging([futureViewName: Set(["watch", "full", "tv"])]) { _, new in new }, - introducersByCategory: currentPolicyDocument.introducersByCategory, - redactions: [:], - keyViewMapping: [futureViewMapping] + currentPolicyDocument.keyViewMapping, - hashAlgo: .SHA256) + modelToCategory: currentPolicyDocument.modelToCategory, + categoriesByView: currentPolicyDocument.categoriesByView.merging([futureViewName: Set(["watch", "full", "tv"])]) { _, new in new }, + introducersByCategory: currentPolicyDocument.introducersByCategory, + redactions: [:], + keyViewMapping: [futureViewMapping] + currentPolicyDocument.keyViewMapping, + userControllableViewList: currentPolicyDocument.userControllableViewList, + piggybackViews: currentPolicyDocument.piggybackViews, + hashAlgo: .SHA256) self.fakeCuttlefishServer.policyOverlay.append(newPolicyDocument) return (newPolicyDocument, futureViewZoneID) } + func createFuturePolicyMovingAllItemsToLimitedPeers() throws -> (TPPolicyDocument) { + let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber } + XCTAssertNotNil(currentPolicyOptional, "Should have one current policy") + let currentPolicyDocument = currentPolicyOptional! + + let limitedPeersViewMapping = TPPBPolicyKeyViewMapping(view: "LimitedPeersAllowed", + matchingRule: TPDictionaryMatchingRule.trueMatch()) + + let newPolicyDocument = try TPPolicyDocument(internalVersion: currentPolicyDocument.version.versionNumber + 1, + modelToCategory: currentPolicyDocument.modelToCategory, + categoriesByView: currentPolicyDocument.categoriesByView, + introducersByCategory: currentPolicyDocument.introducersByCategory, + redactions: [:], + keyViewMapping: [limitedPeersViewMapping] + currentPolicyDocument.keyViewMapping, + userControllableViewList: currentPolicyDocument.userControllableViewList, + piggybackViews: currentPolicyDocument.piggybackViews, + hashAlgo: .SHA256) + + self.fakeCuttlefishServer.policyOverlay.append(newPolicyDocument) + + return newPolicyDocument + } + func testRestoreBottledPeerUsingFuturePolicy() throws { let (newPolicyDocument, futureViewZoneID) = try self.createOctagonAndCKKSUsingFuturePolicy() @@ -312,11 +344,9 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { self.putFakeKeyHierarchiesInCloudKit() try self.putSelfTLKSharesInCloudKit(context: futurePeerContext) - XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID)) + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID)) // Now, our peer (with no inbuilt knowledge of newPolicyDocument) joins via escrow recovery. - // It should be able to recover the FutureView TLK - self.assertAllCKKSViewsUpload(tlkShares: 1) let serverJoinExpectation = self.expectation(description: "peer1 joins successfully") self.fakeCuttlefishServer.joinListener = { joinRequest in @@ -333,12 +363,13 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { let peerID = self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: futurePeerContext) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertEqual(self.injectedManager!.policy?.version, newPolicyDocument.version, "CKKS should be configured with new policy") + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) self.verifyDatabaseMocks() self.wait(for: [serverJoinExpectation], timeout: 10) // And the joined peer should have recovered the TLK, and uploaded itself a share - XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: peerID, senderPeerID: peerID, zoneID: futureViewZoneID)) + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: peerID, senderPeerID: peerID, zoneID: futureViewZoneID)) } func testPairingJoinUsingFuturePolicy() throws { @@ -352,7 +383,7 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { self.putFakeKeyHierarchiesInCloudKit() try self.putSelfTLKSharesInCloudKit(context: futurePeerContext) - XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID)) + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID)) // Now, our peer (with no inbuilt knowledge of newPolicyDocument) joins via pairing // It should be able to recover the FutureView TLK @@ -374,7 +405,7 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { // And then fake like the other peer uploaded TLKShares after the join succeeded (it would normally happen during, but that's okay) try self.putAllTLKSharesInCloudKit(to: self.cuttlefishContext, from: futurePeerContext) - self.sendAllCKKSViewsZoneChanged() + self.injectedManager!.zoneChangeFetcher.notifyZoneChange(nil) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertEqual(self.injectedManager!.policy?.version, newPolicyDocument.version, "CKKS should be configured with new policy") @@ -383,7 +414,7 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { self.wait(for: [serverJoinExpectation], timeout: 10) // And the joined peer should have recovered the TLK, and uploaded itself a share - XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: peerID, senderPeerID: peerID, zoneID: futureViewZoneID)) + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: peerID, senderPeerID: peerID, zoneID: futureViewZoneID)) } func testRecoveryKeyJoinUsingFuturePolicy() throws { @@ -397,7 +428,7 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { self.putFakeKeyHierarchiesInCloudKit() try self.putSelfTLKSharesInCloudKit(context: futurePeerContext) - XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID)) + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID)) // Create the recovery key let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String @@ -428,9 +459,6 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { return nil } - // It should recover and upload the FutureView TLK - self.assertAllCKKSViewsUpload(tlkShares: 1) - self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) @@ -439,10 +467,15 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) XCTAssertEqual(self.injectedManager!.policy?.version, newPolicyDocument.version, "CKKS should be configured with new policy") + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + + // And double-check that the future view is covered + let accountMetadata = try self.cuttlefishContext.accountMetadataStore.loadOrCreateAccountMetadata() + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: accountMetadata.peerID, senderPeerID: accountMetadata.peerID, zoneID: futureViewZoneID)) self.verifyDatabaseMocks() self.wait(for: [serverJoinExpectation], timeout: 10) @@ -513,28 +546,49 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { self.assertResetAndBecomeTrustedInDefaultContext() // Now, another peer comes along and joins via BP recovery, using a new policy - let (newPolicyDocument, _) = try self.createOctagonAndCKKSUsingFuturePolicy() + let (newPolicyDocument, futureZoneID) = try self.createOctagonAndCKKSUsingFuturePolicy() let futurePeerContext = self.makeInitiatorContext(contextID: "futurePeer") futurePeerContext.policyOverride = newPolicyDocument.version let serverJoinExpectation = self.expectation(description: "futurePeer joins successfully") - self.fakeCuttlefishServer.joinListener = { joinRequest in - XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") - let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") + let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() - XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") - XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") - serverJoinExpectation.fulfill() - return nil - } + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + serverJoinExpectation.fulfill() + return nil + } let peer2ID = self.assertJoinViaEscrowRecovery(joiningContext: futurePeerContext, sponsor: self.cuttlefishContext) self.wait(for: [serverJoinExpectation], timeout: 10) + // And the other peer creates the new View, and shares it with us + self.putFakeKeyHierarchiesInCloudKit { zoneID in + return zoneID.zoneName == futureZoneID.zoneName + } + + // The remote peer uploads tlkshares for itself, because it received them during its escrow recovery + try self.putSelfTLKSharesInCloudKit(context: futurePeerContext) //, filter) + try self.putTLKShareInCloudKit(to: self.cuttlefishContext, from: futurePeerContext, zoneID: futureZoneID) + + // First, tell all existing CKKS views to fetch, and wait for it to do so. This will ensure that it receives the tlkshares uploaded above, and + // won't immediately upload new ones when the peer list changes. + self.silentFetchesAllowed = false + self.expectCKFetch() + try XCTUnwrap(self.injectedManager).zoneChangeFetcher.notifyZoneChange(nil) + self.verifyDatabaseMocks() + self.silentFetchesAllowed = true + // Now, tell our first peer about the new changes. It should trust the new peer, and update its policy + // It should also upload itself a TLKShare for the future view + self.assertAllCKKSViewsUpload(tlkShares: 1, filter: { $0.zoneName == futureZoneID.zoneName }) + let updateTrustExpectation = self.expectation(description: "updateTrustExpectation successfully") - self.fakeCuttlefishServer.updateListener = { request in + self.fakeCuttlefishServer.updateListener = { + request in let newStableInfo = request.stableInfoAndSig.stableInfo() XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") @@ -549,6 +603,201 @@ class OctagonForwardCompatibilityTests: OctagonTestsBase { self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) self.wait(for: [updateTrustExpectation], timeout: 10) + + // Once we've uploaded the TLKShare for the future view, then we're fairly sure the view object has been created locally. + self.verifyDatabaseMocks() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + } + + func testRecoverFromPeerUsingOldPolicy() throws { + self.startCKAccountStatusMock() + + let pastPeerContext = self.makeInitiatorContext(contextID: "pastPeer") + + let policyV6Document = builtInPolicyDocuments().filter { $0.version.versionNumber == 6 }.first! + pastPeerContext.policyOverride = policyV6Document.version + + let serverEstablishExpectation = self.expectation(description: "futurePeer establishes successfully") + self.fakeCuttlefishServer.establishListener = { establishRequest in + XCTAssertTrue(establishRequest.peer.hasStableInfoAndSig, "Establishing peer should have a stable info") + let newStableInfo = establishRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Frozen policy version in peer should be frozen version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, policyV6Document.version, "Prevailing policy version in peer should be v6") + serverEstablishExpectation.fulfill() + return nil + } + + self.assertResetAndBecomeTrusted(context: pastPeerContext) + self.wait(for: [serverEstablishExpectation], timeout: 10) + + self.putFakeKeyHierarchiesInCloudKit(filter: { zoneID in policyV6Document.keyViewMapping.contains { $0.view == zoneID.zoneName } }) + try self.putSelfTLKSharesInCloudKit(context: pastPeerContext, filter: { zoneID in policyV6Document.keyViewMapping.contains { $0.view == zoneID.zoneName } }) + + // Ensure that CKKS will bring up the Backstop view + self.injectedManager!.setSyncingViewsAllowList(Set(["Backstop"] + self.intendedCKKSZones!.map { $0.zoneName })) + + // Now, Octagon comes along and recovers the bottle. + + // Right now, Octagon will join and then immediately updateTrust to upload the new set of TLKs + // This probably can be reworked for performance. + let serverJoinExpectation = self.expectation(description: "joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertEqual(joinRequest.viewKeys.count, 0, "Should have zero sets of new viewkeys during join") + serverJoinExpectation.fulfill() + return nil + } + + // TVs do not participate in the backstop view, and so won't upload anything + #if !os(tvOS) + let serverUpdateTrustExpectation = self.expectation(description: "updateTrust successfully") + self.fakeCuttlefishServer.updateListener = { updateRequest in + XCTAssertEqual(updateRequest.viewKeys.count, 1, "Should have one new set of viewkeys during update") + serverUpdateTrustExpectation.fulfill() + return nil + } + #endif + + self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: pastPeerContext) + self.wait(for: [serverJoinExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + #if !os(tvOS) + self.wait(for: [serverUpdateTrustExpectation], timeout: 10) + #endif + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testRecoverFromPeerUsingExtremelyOldPolicy() throws { + self.startCKAccountStatusMock() + + let pastPeerContext = self.makeInitiatorContext(contextID: "pastPeer") + + let policyV1Document = builtInPolicyDocuments().filter { $0.version.versionNumber == 1 }.first! + pastPeerContext.policyOverride = policyV1Document.version + + let serverEstablishExpectation = self.expectation(description: "futurePeer establishes successfully") + self.fakeCuttlefishServer.establishListener = { establishRequest in + XCTAssertTrue(establishRequest.peer.hasStableInfoAndSig, "Establishing peer should have a stable info") + let newStableInfo = establishRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertNil(newStableInfo.flexiblePolicyVersion, "Peer should be from before prevailing policy version were set") + XCTAssertEqual(newStableInfo.frozenPolicyVersion, policyV1Document.version, "Frozen policy version in peer should be v1 - a very old peer") + serverEstablishExpectation.fulfill() + return nil + } + + self.assertResetAndBecomeTrusted(context: pastPeerContext) + self.wait(for: [serverEstablishExpectation], timeout: 10) + + // This filtering should only add Manatee + self.putFakeKeyHierarchiesInCloudKit(filter: { zoneID in policyV1Document.keyViewMapping.contains { $0.view == zoneID.zoneName } }) + try self.putSelfTLKSharesInCloudKit(context: pastPeerContext, filter: { zoneID in policyV1Document.keyViewMapping.contains { $0.view == zoneID.zoneName } }) + + // Ensure that CKKS will bring up the Backstop view, and allow it to bring up PCSEscrow if that's what it wants (it shouldn't) + self.injectedManager!.setSyncingViewsAllowList(Set(["Backstop", "PCSEscrow"] + self.intendedCKKSZones!.map { $0.zoneName })) + + // Now, Octagon comes along and recovers the bottle. + + // Right now, Octagon will join and then immediately updateTrust to upload the new set of TLKs + // This probably can be reworked for performance. + let serverJoinExpectation = self.expectation(description: "joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + // Since Octagon ignores the other peer's policy, it will create the TLKs at establish time + let zones = Set(joinRequest.viewKeys.map { $0.view }) + + #if !os(tvOS) + XCTAssertEqual(zones.count, 3, "Should have three sets of new viewkeys during join") + XCTAssertTrue(zones.contains("Manatee"), "Should have a TLK for the manatee view") + #else + XCTAssertEqual(zones.count, 1, "Should have one set of new viewkeys during join") + #endif + XCTAssertTrue(zones.contains("LimitedPeersAllowed"), "Should have a TLK for the LimitedPeersAllowed view") + + XCTAssertFalse(zones.contains("PCSEscrow"), "Should not have a TLK for the PCSEscrow view") + + let joiningPeer = joinRequest.peer.stableInfoAndSig.stableInfo() + XCTAssertEqual(joiningPeer.flexiblePolicyVersion, prevailingPolicyVersion, "Our current policy should be the prevailing policy - the sponsor peer should be ignored") + XCTAssertEqual(joiningPeer.frozenPolicyVersion, frozenPolicyVersion, "Frozen policy version in peer should be the real policy") + + serverJoinExpectation.fulfill() + return nil + } + + self.assertJoinViaEscrowRecovery(joiningContext: self.cuttlefishContext, sponsor: pastPeerContext) + self.wait(for: [serverJoinExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContext, sender: self.cuttlefishContext) + } + + func testCKKSRequestPolicyCheck() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + let newPolicyDocument = try self.createFuturePolicyMovingAllItemsToLimitedPeers() + + let futurePeerContext = self.makeInitiatorContext(contextID: "futurePeer") + futurePeerContext.policyOverride = newPolicyDocument.version + + let serverJoinExpectation = self.expectation(description: "futurePeer joins successfully") + self.fakeCuttlefishServer.joinListener = { joinRequest in + XCTAssertTrue(joinRequest.peer.hasStableInfoAndSig, "Joining peer should have a stable info") + let newStableInfo = joinRequest.peer.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + serverJoinExpectation.fulfill() + return nil + } + + self.assertJoinViaEscrowRecovery(joiningContext: futurePeerContext, sponsor: self.cuttlefishContext) + self.wait(for: [serverJoinExpectation], timeout: 10) + + // And the peer adds a new item to the LimitedPeersAllowed view, but one that didn't used to go there + var item = self.fakeRecordDictionary("account0", zoneID: self.limitedPeersAllowedZoneID) + item["vwht"] = "asdf" + + self.addItem(toCloudKitZone: item, recordName: "7B598D31-F9C5-481E-98AC-5A507ACB2D85", zoneID: self.limitedPeersAllowedZoneID) + + let limitedPeersView = self.injectedManager?.findView("LimitedPeersAllowed") + XCTAssertNotNil(limitedPeersView, "Should have a LimitedPeersAllowed view") + + // This CKKS notification should cause Octagon to update trust, and then fill CKKS in (which should then accept the item) + + let updateExpectation = self.expectation(description: "peer updates successfully") + self.fakeCuttlefishServer.updateListener = { request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + + XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version") + XCTAssertEqual(newStableInfo.flexiblePolicyVersion, newPolicyDocument.version, "Prevailing policy version in peer should match new policy version") + + updateExpectation.fulfill() + return nil + } + + // CKKS will also upload TLKShares for the new peer + self.assertAllCKKSViewsUpload(tlkShares: 1) + + try XCTUnwrap(self.injectedManager).zoneChangeFetcher.notifyZoneChange(nil) + limitedPeersView!.waitForFetchAndIncomingQueueProcessing() + + // And wait for the updateTrust to occur, then for Octagon to return to ready, then for any incoming queue processing in ckks + self.wait(for: [updateExpectation], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + limitedPeersView!.waitForOperations(of: CKKSIncomingQueueOperation.self) + self.verifyDatabaseMocks() + + // The item should be found + self.findGenericPassword("account0", expecting: errSecSuccess) } } diff --git a/keychain/ot/tests/octagon/OctagonTests+HealthCheck.swift b/keychain/ot/tests/octagon/OctagonTests+HealthCheck.swift index 6591eb61..1da7c30a 100644 --- a/keychain/ot/tests/octagon/OctagonTests+HealthCheck.swift +++ b/keychain/ot/tests/octagon/OctagonTests+HealthCheck.swift @@ -1,7 +1,6 @@ #if OCTAGON class OctagonHealthCheckTests: OctagonTestsBase { - func testHealthCheckAllTrusted() throws { let containerName = OTCKContainerName let contextName = OTDefaultContext @@ -70,9 +69,9 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) #if os(tvOS) - XCTAssertEqual(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), false, "Should not have posted a CFU on aTV") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should not have posted a CFU on aTV") #else - XCTAssertEqual(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), true, "Should have posted a CFU (due to being untrusted)") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should have posted a CFU (due to being untrusted)") #endif self.verifyDatabaseMocks() @@ -92,9 +91,9 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.wait(for: [healthCheckCallback2], timeout: 10) #if os(tvOS) - XCTAssertEqual(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), false, "Should not have posted a CFU on aTV") + XCTAssertFalse(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should not have posted a CFU on aTV") #else - XCTAssertEqual(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), true, "Should have posted a CFU") + XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should have posted a CFU") #endif } @@ -589,7 +588,6 @@ class OctagonHealthCheckTests: OctagonTestsBase { } func testHealthCheckWhenLocked() throws { - let containerName = OTCKContainerName let contextName = OTDefaultContext @@ -642,6 +640,37 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) } + func testHealthCheckBeforeClassCUnlock() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + // Now, the device restarts, and isn't unlocked immediately. + self.aksLockState = true + SecMockAKS.lockClassA_C() + self.lockStateTracker.recheck() + + do { + _ = try OTAccountMetadataClassC.loadFromKeychain(forContainer: self.cuttlefishContext.containerName, contextID: self.cuttlefishContext.contextID) + XCTFail("shouldn't have been able to load the class c metadata") + } catch { + // We expected this error; fall through + } + + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForClassCUnlock, within: 10 * NSEC_PER_SEC) + + // A health check should fail, and leave us waiting for the initial unlock + + let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") + self.manager.healthCheck(self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID, skipRateLimitingCheck: false) { error in + XCTAssertNotNil(error, "error should be present") + healthCheckCallback.fulfill() + } + self.wait(for: [healthCheckCallback], timeout: 20) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForClassCUnlock, within: 10 * NSEC_PER_SEC) + } + func testLastHealthCheckPersistedTime() throws { let containerName = OTCKContainerName let contextName = OTDefaultContext @@ -909,6 +938,244 @@ class OctagonHealthCheckTests: OctagonTestsBase { self.assertEnters(context: cuttlefishContext, state: OctagonStateWaitForHSA2, within: 10 * NSEC_PER_SEC) } + + func testRPCTrustStatusReturnsIsLocked() throws { + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + do { + clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + + self.aksLockState = true + self.lockStateTracker.recheck() + + let configuration = OTOperationConfiguration() + + let statusexpectation = self.expectation(description: "status callback occurs") + self.cuttlefishContext.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, _, isLocked, error in + XCTAssertEqual(egoStatus, .in, "Self peer for OTDefaultContext should be trusted") + XCTAssertNotNil(egoPeerID, "Should have a peerID") + XCTAssertEqual(isLocked, true, "should be true") + XCTAssertNil(error, "error should be nil") + statusexpectation.fulfill() + } + self.wait(for: [statusexpectation], timeout: 10) + + let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") + self.manager.healthCheck(OTCKContainerName, context: OTDefaultContext, skipRateLimitingCheck: false) { error in + XCTAssertNil(error, "error should be nil") + healthCheckCallback.fulfill() + } + self.wait(for: [healthCheckCallback], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) + } + + func testBecomeUntrustedResultsInWaitForUnlock() throws { + self.startCKAccountStatusMock() + + // First, peer 1 establishes, preapproving both peer2 and peer3. Then, peer2 and peer3 join and harmonize. + // Peer1 is never told about the follow-on joins. + // Then, the test can begin. + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + let peer3SOSMockPeer = self.createSOSPeer(peerID: "peer3ID") + + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + self.mockSOSAdapter.trustedPeers.add(peer3SOSMockPeer) + + // Due to how everything is shaking out, SOS TLKShares will be uploaded in a second transaction after Octagon uploads its TLKShares + // This isn't great: Octagon: upload SOS TLKShares alongside initial key hierarchy + self.assertAllCKKSViewsUpload(tlkShares: 3) + + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + let peer1ID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + // peer2 + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + let peer2 = self.makeInitiatorContext(contextID: "peer2", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + + peer2.startOctagonStateMachine() + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + let peer2ID = try peer2.accountMetadataStore.getEgoPeerID() + + // peer3 + let peer3mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer3SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + let peer3 = self.makeInitiatorContext(contextID: "peer3", authKitAdapter: self.mockAuthKit3, sosAdapter: peer3mockSOS) + + peer3.startOctagonStateMachine() + self.assertEnters(context: peer3, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer3) + let peer3ID = try peer3.accountMetadataStore.getEgoPeerID() + + // Now, tell peer2 about peer3's join + self.sendContainerChangeWaitForFetch(context: peer2) + + // Peer 1 should preapprove both peers. + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trustsByPreapproval, target: peer2ID)), + "peer 1 should trust peer 2 by preapproval") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trustsByPreapproval, target: peer2ID)), + "peer 1 should trust peer 3 by preapproval") + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer1ID)), + "peer 2 should trust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer3ID)), + "peer 2 should trust peer 3") + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer3ID, opinion: .trusts, target: peer1ID)), + "peer 3 should trust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer3ID, opinion: .trusts, target: peer2ID)), + "peer 3 should trust peer 2") + + // Now, the test can begin. Peer2 decides it rules the world. + let removalExpectation = self.expectation(description: "removal occurs") + peer2.rpcRemoveFriends(inClique: [peer1ID, peer3ID]) { removeError in + XCTAssertNil(removeError, "Should be no error removing peer1 and peer3") + removalExpectation.fulfill() + } + self.wait(for: [removalExpectation], timeout: 5) + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .excludes, target: peer1ID)), + "peer 2 should distrust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .excludes, target: peer3ID)), + "peer 2 should distrust peer 3") + + // And we notify peer3 about this, and it should become sad + let updateTrustExpectation = self.expectation(description: "fetchChanges") + + // Ths push will only be delivered when the device is unlocked, so simulate the device locking during the fetch + self.fakeCuttlefishServer.fetchChangesListener = { request in + self.fakeCuttlefishServer.fetchChangesListener = nil + + self.aksLockState = true + self.lockStateTracker.recheck() + + updateTrustExpectation.fulfill() + return nil + } + peer3.notifyContainerChange(nil) + self.wait(for: [updateTrustExpectation], timeout: 10) + + self.assertEnters(context: peer3, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) + + self.aksLockState = false + self.lockStateTracker.recheck() + + self.assertEnters(context: peer3, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: peer3) + } + + func testEvaluateTPHOctagonTrust() throws { + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + do { + clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + + let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") + self.manager.healthCheck(OTCKContainerName, context: OTDefaultContext, skipRateLimitingCheck: false) { error in + XCTAssertNil(error, "error should be nil") + healthCheckCallback.fulfill() + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateTPHTrustCheck, within: 10 * NSEC_PER_SEC) + + self.aksLockState = true + self.lockStateTracker.recheck() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) + + self.wait(for: [healthCheckCallback], timeout: 10) + + self.aksLockState = false + self.lockStateTracker.recheck() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + } + + func testEvaluateSecdOctagonTrust() throws { + self.cuttlefishContext.startOctagonStateMachine() + self.startCKAccountStatusMock() + + XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let clique: OTClique + do { + clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + XCTAssertNotNil(clique.cliqueMemberIdentifier, "Should have a member identifier after a clique newFriends call") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + throw error + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + + let leaveExpectation = self.expectation(description: "rpcLeaveClique returns") + self.cuttlefishContext.rpcLeaveClique { leaveError in + XCTAssertNil(leaveError, "Should be no error leaving") + leaveExpectation.fulfill() + } + self.wait(for: [leaveExpectation], timeout: 10) + + let healthCheckCallback = self.expectation(description: "healthCheckCallback callback occurs") + self.manager.healthCheck(OTCKContainerName, context: OTDefaultContext, skipRateLimitingCheck: false) { error in + XCTAssertNotNil(error, "error should not be nil") + healthCheckCallback.fulfill() + } + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStatePostRepairCFU, within: 10 * NSEC_PER_SEC) + + self.aksLockState = true + self.lockStateTracker.recheck() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) + + self.wait(for: [healthCheckCallback], timeout: 10) + + self.aksLockState = false + self.lockStateTracker.recheck() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + } } #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+Helpers.swift b/keychain/ot/tests/octagon/OctagonTests+Helpers.swift index 70ed71e6..7b7cb3fa 100644 --- a/keychain/ot/tests/octagon/OctagonTests+Helpers.swift +++ b/keychain/ot/tests/octagon/OctagonTests+Helpers.swift @@ -30,4 +30,75 @@ extension EstablishRequest { } } +extension OctagonTestsBase { + func simulateRestart(context: OTCuttlefishContext) -> OTCuttlefishContext { + self.manager.removeContext(forContainerName: context.containerName, contextID: context.contextID) + + if context.contextID == OTDefaultContext { + self.restartCKKSViews() + } + + let newContext = self.manager.context(forContainerName: context.containerName, contextID: context.contextID) + + if context.contextID == OTDefaultContext { + XCTAssertNil(self.injectedManager?.policy, "CKKS should not have a policy after 'restart'") + } + + newContext.startOctagonStateMachine() + + return newContext + } + + func cliqueFor(context: OTCuttlefishContext) -> OTClique { + let otcliqueContext = OTConfigurationContext() + otcliqueContext.context = context.contextID + otcliqueContext.altDSID = try! context.authKitAdapter.primaryiCloudAccountAltDSID() + otcliqueContext.otControl = self.otControl + + return OTClique(contextData: otcliqueContext) + } + + func assertFetchUserControllableViewsSyncStatus(clique: OTClique, status: Bool) { + do { + let result = try clique.fetchUserControllableViewsSyncingEnabled() + XCTAssertEqual(result, status, "API should report that sync status matches expectation") + } catch { + XCTFail("Should be no error fetching status: \(error)") + } + } + + func assertModifyUserViews(clique: OTClique, intendedSyncStatus: Bool) { + let updateTrustExpectation = self.expectation(description: "updateTrust") + self.fakeCuttlefishServer.updateListener = { request in + let newStableInfo = request.stableInfoAndSig.stableInfo() + if intendedSyncStatus { + XCTAssertEqual(newStableInfo.syncUserControllableViews, .ENABLED, "User views should now be enabled") + } else { + XCTAssertEqual(newStableInfo.syncUserControllableViews, .DISABLED, "User views should now be disabled") + } + updateTrustExpectation.fulfill() + + return nil + } + + XCTAssertNoThrow(try clique.setUserControllableViewsSyncStatus(intendedSyncStatus), "Should be no error setting user-visible sync status") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: intendedSyncStatus) + + self.wait(for: [updateTrustExpectation], timeout: 10) + self.fakeCuttlefishServer.updateListener = nil + } + + func assertModifyUserViewsWithNoPeerUpdate(clique: OTClique, intendedSyncStatus: Bool, finalSyncStatus: Bool? = nil) { + self.fakeCuttlefishServer.updateListener = { request in + XCTFail("Expected no updates during user view status modification") + return nil + } + + XCTAssertNoThrow(try clique.setUserControllableViewsSyncStatus(intendedSyncStatus), "Should be no error setting user-visible sync status") + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: finalSyncStatus ?? intendedSyncStatus) + + self.fakeCuttlefishServer.updateListener = nil + } +} + #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+RecoveryKey.swift b/keychain/ot/tests/octagon/OctagonTests+RecoveryKey.swift index 10172e35..9bada6c8 100644 --- a/keychain/ot/tests/octagon/OctagonTests+RecoveryKey.swift +++ b/keychain/ot/tests/octagon/OctagonTests+RecoveryKey.swift @@ -14,12 +14,23 @@ extension Container { @objcMembers class OctagonRecoveryKeyTests: OctagonTestsBase { override func setUp() { + // Please don't make the SOS API calls, no matter what + OctagonSetSOSFeatureEnabled(false) + super.setUp() + + // Set this to what it normally is. Each test can muck with it, if they like + #if os(macOS) || os(iOS) + OctagonSetPlatformSupportsSOS(true) + self.manager.setSOSEnabledForPlatformFlag(true) + #else + self.manager.setSOSEnabledForPlatformFlag(false) + OctagonSetPlatformSupportsSOS(false) + #endif } func testSetRecoveryKey() throws { self.startCKAccountStatusMock() - self.manager.setSOSEnabledForPlatformFlag(false) self.cuttlefishContext.startOctagonStateMachine() XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) @@ -73,6 +84,7 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String @@ -91,8 +103,13 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) self.verifyDatabaseMocks() + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + let bottle = self.fakeCuttlefishServer.state.bottles[0] let initiatorContextID = "new guy" @@ -111,8 +128,11 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.verifyDatabaseMocks() self.sendContainerChangeWaitForFetch(context: initiatorContext) + + self.assertAllCKKSViewsUpload(tlkShares: 1) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() let stableInfoCheckDumpCallback = self.expectation(description: "stableInfoCheckDumpCallback callback occurs") @@ -178,6 +198,7 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String @@ -196,6 +217,8 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) let bottle = self.fakeCuttlefishServer.state.bottles[0] @@ -303,10 +326,15 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { thirdPeerStableInfoCheckDumpCallback.fulfill() } self.wait(for: [thirdPeerStableInfoCheckDumpCallback], timeout: 10) + + // And ensure that the original peer uploads shares for the third as well + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() } func createEstablishContext(contextID: String) -> OTCuttlefishContext { - return self.manager.context(forContainerName: OTCKContainerName, contextID: contextID, sosAdapter: self.mockSOSAdapter, @@ -346,10 +374,11 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.assertEnters(context: establishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: establishContext) + let establishedPeerID = self.fetchEgoPeerID(context: establishContext) + // Fake that this peer also created some TLKShares for itself self.putFakeKeyHierarchiesInCloudKit() try self.putSelfTLKSharesInCloudKit(context: establishContext) - self.assertSelfTLKSharesInCloudKit(context: establishContext) let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String @@ -364,8 +393,10 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { } self.wait(for: [createRecoveryExpectation], timeout: 10) + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID)) self.sendContainerChangeWaitForFetch(context: establishContext) + // Now, join from a new device let recoveryContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) recoveryContext.startOctagonStateMachine() @@ -378,8 +409,11 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + let joinedPeerID = self.fetchEgoPeerID(context: recoveryContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.sendContainerChangeWaitForFetch(context: recoveryContext) let stableInfoCheckDumpCallback = self.expectation(description: "stableInfoCheckDumpCallback callback occurs") @@ -427,7 +461,19 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { stableInfoAcceptorCheckDumpCallback.fulfill() } self.wait(for: [stableInfoAcceptorCheckDumpCallback], timeout: 10) - try self.putSelfTLKSharesInCloudKit(context: recoveryContext) + + // And check the current state of the world + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: joinedPeerID, opinion: .trusts, target: joinedPeerID)), + "joined peer should trust itself") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: joinedPeerID, opinion: .trusts, target: establishedPeerID)), + "joined peer should trust establish peer") + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: establishedPeerID, opinion: .trusts, target: establishedPeerID)), + "establish peer should trust itself") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: establishedPeerID, opinion: .trusts, target: joinedPeerID)), + "establish peer should trust joined peer") + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.assertSelfTLKSharesInCloudKit(context: recoveryContext) } @@ -493,7 +539,7 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) self.assertConsidersSelfTrusted(context: recoveryContext) self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLK, within: 10 * NSEC_PER_SEC) @@ -605,6 +651,7 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { XCTAssertNotNil(entropy, "entropy should not be nil") self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) let bottle = self.fakeCuttlefishServer.state.bottles[0] @@ -654,9 +701,9 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { } self.wait(for: [setRecoveryKeyExpectation], timeout: 10) - let recoveryKey2 = SecRKCreateRecoveryKeyString(nil) + let recoveryKey2 = try XCTUnwrap(SecRKCreateRecoveryKeyString(nil)) let setRecoveryKeyExpectationAgain = self.expectation(description: "setRecoveryKeyExpectationAgain callback occurs") - TestsObjectiveC.setNewRecoveryKeyWithData(initiatorConfigurationContext, recoveryKey: recoveryKey2!) { rk, error in + TestsObjectiveC.setNewRecoveryKeyWithData(initiatorConfigurationContext, recoveryKey: recoveryKey2) { rk, error in XCTAssertNil(error, "error should be nil") XCTAssertNotNil(rk, "rk should not be nil") setRecoveryKeyExpectationAgain.fulfill() @@ -664,7 +711,16 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.wait(for: [setRecoveryKeyExpectationAgain], timeout: 10) self.sendContainerChangeWaitForFetch(context: initiatorContext) + + // When the original peer responds to the new peer, it should upload tlkshares for the new peer and the new RK + // (since the remote peer didn't upload shares for the new RK) + self.assertAllCKKSViewsUpload(tlkShares: 2) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey2, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey2, salt: try XCTUnwrap(self.mockAuthKit.altDSID), sender: self.cuttlefishContext)) var initiatorRecoverySigningKey: Data? var initiatorRecoveryEncryptionKey: Data? @@ -760,20 +816,21 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { // Fake that this peer also created some TLKShares for itself self.putFakeKeyHierarchiesInCloudKit() try self.putSelfTLKSharesInCloudKit(context: establishContext) - self.assertSelfTLKSharesInCloudKit(context: establishContext) - let recoveryKey = SecRKCreateRecoveryKeyString(nil) + let recoveryKey = try XCTUnwrap(SecRKCreateRecoveryKeyString(nil)) XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") self.manager.setSOSEnabledForPlatformFlag(true) let setRecoveryKeyExpectation = self.expectation(description: "setRecoveryKeyExpectation callback occurs") - TestsObjectiveC.setNewRecoveryKeyWithData(recoverykeyotcliqueContext, recoveryKey: recoveryKey!) { _, error in + TestsObjectiveC.setNewRecoveryKeyWithData(recoverykeyotcliqueContext, recoveryKey: recoveryKey) { _, error in XCTAssertNil(error, "error should be nil") setRecoveryKeyExpectation.fulfill() } self.wait(for: [setRecoveryKeyExpectation], timeout: 10) + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID)) + self.sendContainerChangeWaitForFetch(context: establishContext) let newCliqueContext = OTConfigurationContext() @@ -786,17 +843,22 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { newGuyContext.startOctagonStateMachine() self.sendContainerChangeWaitForUntrustedFetch(context: newGuyContext) + self.verifyDatabaseMocks() self.manager.setSOSEnabledForPlatformFlag(true) let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") - OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey!) { error in + OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey) { error in XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) self.sendContainerChangeWaitForFetch(context: newGuyContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) + let stableInfoAcceptorCheckDumpCallback = self.expectation(description: "stableInfoAcceptorCheckDumpCallback callback occurs") self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") @@ -848,33 +910,46 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.wait(for: [stableInfoCheckDumpCallback], timeout: 10) } - func testOTCliqueJoinUsingANotEnrolledRecoveryKey() throws { + func testJoinWithUnknownRecoveryKey() throws { OctagonRecoveryKeySetIsEnabled(true) - self.manager.setSOSEnabledForPlatformFlag(false) + self.startCKAccountStatusMock() - let recoveryKey = SecRKCreateRecoveryKeyString(nil) - XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") + let remote = self.makeInitiatorContext(contextID: "remote") + self.assertResetAndBecomeTrusted(context: remote) - let newCliqueContext = OTConfigurationContext() - newCliqueContext.context = OTDefaultContext - newCliqueContext.dsid = self.otcliqueContext.dsid - newCliqueContext.altDSID = self.mockAuthKit.altDSID! - newCliqueContext.otControl = self.otControl + let recoveryKey = try XCTUnwrap(SecRKCreateRecoveryKeyString(nil), "recoveryKey should not be nil") - let recoveryGuyContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.manager.setSOSEnabledForPlatformFlag(true) + #if !os(macOS) && !os(iOS) + let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") + TestsObjectiveC.recoverOctagon(usingData: self.otcliqueContext, recoveryKey: recoveryKey) { error in + XCTAssertNotNil(error, "error should exist") + joinWithRecoveryKeyExpectation.fulfill() + } + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + // double-check that the status is not in + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + + #else let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") - TestsObjectiveC.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey!) { error in + TestsObjectiveC.recoverOctagon(usingData: self.otcliqueContext, recoveryKey: recoveryKey) { error in XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) - self.sendContainerChange(context: recoveryGuyContext) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) - let newGuyCheckDumpCallback = self.expectation(description: "newGuyCheckDumpCallback callback occurs") + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) + self.verifyDatabaseMocks() + + let rejoinedDumpCallback = self.expectation(description: "dump callback occurs") self.tphClient.dump(withContainer: OTCKContainerName, context: OTDefaultContext) { dump, _ in XCTAssertNotNil(dump, "dump should not be nil") let egoSelf = dump!["self"] as? [String: AnyObject] @@ -892,12 +967,10 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { XCTAssertEqual(included!.count, 1, "should be 1 peer ids") let vouchers = dump!["vouchers"] XCTAssertNotNil(vouchers, "vouchers should not be nil") - newGuyCheckDumpCallback.fulfill() + rejoinedDumpCallback.fulfill() } - self.wait(for: [newGuyCheckDumpCallback], timeout: 10) - self.assertEnters(context: recoveryGuyContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - - self.assertSelfTLKSharesInCloudKit(context: recoveryGuyContext) + self.wait(for: [rejoinedDumpCallback], timeout: 10) + #endif } func testSetRecoveryKeyAsLimitedPeer() throws { @@ -974,12 +1047,11 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.assertSelfTLKSharesInCloudKit(context: establishContext) - let recoveryKey = SecRKCreateRecoveryKeyString(nil) - XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") + let recoveryKey = try XCTUnwrap(SecRKCreateRecoveryKeyString(nil), "should be able to create a recovery key") self.manager.setSOSEnabledForPlatformFlag(true) let setRecoveryKeyExpectation = self.expectation(description: "setRecoveryKeyExpectation callback occurs") - TestsObjectiveC.setNewRecoveryKeyWithData(recoverykeyotcliqueContext, recoveryKey: recoveryKey!) { _, error in + TestsObjectiveC.setNewRecoveryKeyWithData(recoverykeyotcliqueContext, recoveryKey: recoveryKey) { _, error in XCTAssertNil(error, "error should be nil") setRecoveryKeyExpectation.fulfill() } @@ -1005,13 +1077,19 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.sendContainerChangeWaitForUntrustedFetch(context: newGuyContext) + // We'll perform a reset here. Allow for CKKS to do the same. + self.silentZoneDeletesAllowed = true + self.manager.setSOSEnabledForPlatformFlag(true) let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") - OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey!) { error in + OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey) { error in XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) } func testVouchWithWrongRecoveryKey() throws { @@ -1081,11 +1159,16 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { recoveryKey = SecRKCreateRecoveryKeyString(nil) XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") + // We'll reset Octagon here, so allow for CKKS to reset as well + self.silentZoneDeletesAllowed = true + OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey!) { error in XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } func testRecoveryWithDistrustedPeers() throws { @@ -1137,6 +1220,8 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.sendContainerChangeWaitForFetch(context: establishContext) + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey!, salt: self.mockAuthKit.altDSID!) + //now this peer will leave octagon XCTAssertNoThrow(try clique.leave(), "Should be no error departing clique") @@ -1158,11 +1243,17 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.manager.setSOSEnabledForPlatformFlag(true) let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") + // We expect an Octagon reset here, because the RK is for a distrusted peer + // This also performs a CKKS reset + self.silentZoneDeletesAllowed = true + OTClique.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey!) { error in XCTAssertNil(error, "error should be nil") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } func testMalformedRecoveryKey() throws { @@ -1233,27 +1324,26 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { XCTAssertEqual((error! as NSError).domain, "com.apple.security.octagon", "error code domain should be com.apple.security.octagon") joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) } @discardableResult - func createAndSetRecoveryKey(context: OTCuttlefishContext) -> String { + func createAndSetRecoveryKey(context: OTCuttlefishContext) throws -> String { let cliqueConfiguration = OTConfigurationContext() cliqueConfiguration.context = context.contextID cliqueConfiguration.altDSID = try! context.authKitAdapter.primaryiCloudAccountAltDSID() cliqueConfiguration.otControl = self.otControl - let recoveryKey = SecRKCreateRecoveryKeyString(nil) - XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") + let recoveryKey = try XCTUnwrap(SecRKCreateRecoveryKeyString(nil), "should be able to create a recovery key") let setRecoveryKeyExpectation = self.expectation(description: "setRecoveryKeyExpectation callback occurs") - TestsObjectiveC.setNewRecoveryKeyWithData(cliqueConfiguration, recoveryKey: recoveryKey!) { _, error in + TestsObjectiveC.setNewRecoveryKeyWithData(cliqueConfiguration, recoveryKey: recoveryKey) { _, error in XCTAssertNil(error, "error should be nil") setRecoveryKeyExpectation.fulfill() } self.wait(for: [setRecoveryKeyExpectation], timeout: 10) - return recoveryKey! + return recoveryKey } func testConcurWithTrustedPeer() throws { @@ -1271,8 +1361,8 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.verifyDatabaseMocks() // peer1 sets a recovery key - var rkSigningPubKey : Data? = nil - var rkEncryptionPubKey : Data? = nil + var rkSigningPubKey: Data? + var rkEncryptionPubKey: Data? let setRKExpectation = self.expectation(description: "setRecoveryKey") self.fakeCuttlefishServer.setRecoveryKeyListener = { request in @@ -1286,7 +1376,7 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { return nil } - self.createAndSetRecoveryKey(context: self.cuttlefishContext) + try self.createAndSetRecoveryKey(context: self.cuttlefishContext) self.wait(for: [setRKExpectation], timeout: 10) // And peer2 concurs with it upon receiving a push @@ -1317,9 +1407,9 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.startCKAccountStatusMock() self.manager.setSOSEnabledForPlatformFlag(true) - let _ = self.assertResetAndBecomeTrustedInDefaultContext() + _ = self.assertResetAndBecomeTrustedInDefaultContext() // peer1 sets a recovery key - self.createAndSetRecoveryKey(context: self.cuttlefishContext) + try self.createAndSetRecoveryKey(context: self.cuttlefishContext) // Restart TPH self.tphClient.containerMap.removeAllContainers() @@ -1331,9 +1421,9 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.startCKAccountStatusMock() self.manager.setSOSEnabledForPlatformFlag(true) - let _ = self.assertResetAndBecomeTrustedInDefaultContext() + _ = self.assertResetAndBecomeTrustedInDefaultContext() // peer1 sets a recovery key - self.createAndSetRecoveryKey(context: self.cuttlefishContext) + try self.createAndSetRecoveryKey(context: self.cuttlefishContext) // Before restarting TPH, emulate a world in which the RK variables were not set on the container @@ -1346,5 +1436,131 @@ class OctagonRecoveryKeyTests: OctagonTestsBase { self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) } + + func testCKKSSendsTLKSharesToRecoveryKey() throws { + #if os(tvOS) || os(watchOS) + self.startCKAccountStatusMock() + throw XCTSkip("Apple TVs and watches will not set recovery key") + #else + + self.startCKAccountStatusMock() + + // To get into a state where we don't upload the TLKShares to each RK on RK creation, put Octagon into a waitfortlk state + // Right after CKKS fetches for the first time, insert a new key hierarchy into CloudKit + self.silentFetchesAllowed = false + self.expectCKFetchAndRun { + self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() + self.silentFetchesAllowed = true + } + + do { + let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) + XCTAssertNotNil(clique, "Clique should not be nil") + } catch { + XCTFail("Shouldn't have errored making new friends: \(error)") + } + + // Now, we should be in 'ready' + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) + + // and all subCKKSes should enter waitfortlk, as they don't have the TLKs uploaded by the other peer + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLK, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + // And a recovery key is set + let recoveryKey = try self.createAndSetRecoveryKey(context: self.cuttlefishContext) + + // and now, all TLKs arrive! CKKS should upload two shares: one for itself, and one for the recovery key + self.assertAllCKKSViewsUpload(tlkShares: 2) + self.saveTLKMaterialToKeychain() + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID))) + + #endif // tvOS || watchOS + } + + func testRKRecoveryRecoversCKKSCreatedShares() throws { + self.startCKAccountStatusMock() + + let remote = self.createEstablishContext(contextID: "remote") + self.assertResetAndBecomeTrusted(context: remote) + + #if os(tvOS) || os(watchOS) + self.manager.setSOSEnabledForPlatformFlag(true) + let recoveryKey = try self.createAndSetRecoveryKey(context: remote) + self.manager.setSOSEnabledForPlatformFlag(false) + #else + let recoveryKey = try self.createAndSetRecoveryKey(context: remote) + #endif + + // And TLKShares for the RK are sent from the Octagon peer + self.putFakeKeyHierarchiesInCloudKit() + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID), sender: remote) + XCTAssertTrue(try self.recoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID), sender: remote)) + + // Now, join! This should recover the TLKs. + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + self.assertAllCKKSViewsUpload(tlkShares: 1) + + let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKey callback occurs") + self.cuttlefishContext.join(withRecoveryKey: recoveryKey) { error in + XCTAssertNil(error, "error should be nil") + joinWithRecoveryKeyExpectation.fulfill() + } + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + } + + func testRecoverTLKSharesSentToRKAfterCKKSTimeout() throws { + OctagonRecoveryKeySetIsEnabled(true) + self.manager.setSOSEnabledForPlatformFlag(false) + self.startCKAccountStatusMock() + + let remote = self.createEstablishContext(contextID: "remote") + self.assertResetAndBecomeTrusted(context: remote) + + // Fake that this peer also created some TLKShares for itself + self.putFakeKeyHierarchiesInCloudKit() + try self.putSelfTLKSharesInCloudKit(context: remote) + self.assertSelfTLKSharesInCloudKit(context: remote) + + self.manager.setSOSEnabledForPlatformFlag(true) + let recoveryKey = try self.createAndSetRecoveryKey(context: remote) + + try self.putRecoveryKeyTLKSharesInCloudKit(recoveryKey: recoveryKey, salt: try XCTUnwrap(self.mockAuthKit.altDSID)) + + // Now, join from a new device + // Simulate CKKS fetches taking forever. In practice, this is caused by many round-trip fetches to CK happening over minutes. + self.holdCloudKitFetches() + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKey callback occurs") + self.cuttlefishContext.join(withRecoveryKey: recoveryKey) { error in + XCTAssertNil(error, "error should be nil") + joinWithRecoveryKeyExpectation.fulfill() + } + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateFetch, within: 10 * NSEC_PER_SEC) + + self.assertAllCKKSViewsUpload(tlkShares: 1) + self.releaseCloudKitFetchHold() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + } } #endif diff --git a/keychain/ot/tests/octagon/OctagonTests+Reset.swift b/keychain/ot/tests/octagon/OctagonTests+Reset.swift index db3fb52f..8daace77 100644 --- a/keychain/ot/tests/octagon/OctagonTests+Reset.swift +++ b/keychain/ot/tests/octagon/OctagonTests+Reset.swift @@ -117,8 +117,8 @@ class OctagonResetTests: OctagonTestsBase { self.verifyDatabaseMocks() // CKKS should pass through "waitfortrust" during a reset - let waitfortrusts = self.ckksViews.compactMap { view in - (view as! CKKSKeychainView).keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust] as? CKKSCondition + let waitfortrusts = self.injectedManager!.views.allValues.map { view in + (view as! CKKSKeychainView).keyHierarchyConditions[SecCKKSZoneKeyStateWaitForTrust]! } XCTAssert(!waitfortrusts.isEmpty, "Should have at least one waitfortrust condition") @@ -148,6 +148,7 @@ class OctagonResetTests: OctagonTestsBase { func testOctagonResetAlsoResetsCKKSViewsMissingTLKs() { self.putFakeKeyHierarchiesInCloudKit() + self.putFakeDeviceStatusesInCloudKit() let zoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys XCTAssertNotNil(zoneKeys, "Should have some zone keys") @@ -157,7 +158,7 @@ class OctagonResetTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) self.silentZoneDeletesAllowed = true @@ -167,7 +168,7 @@ class OctagonResetTests: OctagonTestsBase { XCTFail("failed to make new friends: \(error)") } - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) let laterZoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys XCTAssertNotNil(laterZoneKeys, "Should have some zone keys") @@ -239,7 +240,8 @@ class OctagonResetTests: OctagonTestsBase { } func testOctagonResetWithRemoteDevicesWithKeysDoesNotResetCKKS() { - // CKKS has no keys, and there's another device claiming to have them already, so CKKS won't immediately reset it + // CKKS has no keys, and there's another device claiming to have them already, so CKKS won't immediately reset it. + // But, Octagon will! self.putFakeKeyHierarchiesInCloudKit() self.putFakeDeviceStatusesInCloudKit() @@ -266,13 +268,13 @@ class OctagonResetTests: OctagonTestsBase { XCTFail("failed to make new friends: \(error)") } - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLK, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) #if !os(tvOS) let laterZoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys XCTAssertNotNil(laterZoneKeys, "Should have some zone keys") XCTAssertNotNil(laterZoneKeys?.tlk, "Should have a tlk in the newly created keyset") - XCTAssertEqual(zoneKeys?.tlk?.uuid, laterZoneKeys?.tlk?.uuid, "CKKS zone should now have the same keys") + XCTAssertNotEqual(zoneKeys?.tlk?.uuid, laterZoneKeys?.tlk?.uuid, "CKKS zone should not have the same keys - a reset should have occurred") #else let laterZoneKeys = self.keys![self.manateeZoneID!] as? ZoneKeys XCTAssertNil(laterZoneKeys, "Should have no Manatee zone keys for aTV") @@ -281,7 +283,7 @@ class OctagonResetTests: OctagonTestsBase { let lpLaterZoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys XCTAssertNotNil(lpLaterZoneKeys, "Should have some zone keys for LimitedPeersAllowed") XCTAssertNotNil(lpLaterZoneKeys?.tlk, "Should have a tlk in the newly created keyset for LimitedPeersAllowed") - XCTAssertEqual(lpZoneKeys?.tlk?.uuid, lpLaterZoneKeys?.tlk?.uuid, "CKKS zone should now have the same keys for LimitedPeersAllowed") + XCTAssertNotEqual(lpZoneKeys?.tlk?.uuid, lpLaterZoneKeys?.tlk?.uuid, "CKKS zone should not have the same keys for LimitedPeersAllowed - a reset should have occurred") } func testOctagonResetWithTLKsDoesNotResetCKKS() { @@ -357,6 +359,19 @@ class OctagonResetTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() + + // And after this reset, can we put together an escrow record? + let escrowContentsExpectation = self.expectation(description: "fetchEscrowContents") + self.cuttlefishContext.fetchEscrowContents { entropy, bottleID, signingPubKey, error in + XCTAssertNil(error, "Should be no error fetching escrow contents") + + XCTAssertNotNil(entropy, "Should have some entropy") + XCTAssertNotNil(bottleID, "Should have some bottleID") + XCTAssertNotNil(signingPubKey, "Should have some signing public key") + + escrowContentsExpectation.fulfill() + } + self.wait(for: [escrowContentsExpectation], timeout: 10) } func testResetReasonUnknown() throws { @@ -439,15 +454,6 @@ class OctagonResetTests: OctagonTestsBase { _ = try self.cuttlefishContext.accountAvailable("13453464") - let resetExpectation = self.expectation(description: "resetExpectation") - - self.fakeCuttlefishServer.resetListener = { request in - self.fakeCuttlefishServer.resetListener = nil - resetExpectation.fulfill() - XCTAssertTrue(request.resetReason.rawValue == CuttlefishResetReason.recoveryKey.rawValue, "reset reason should be recovery key") - return nil - } - let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil") @@ -457,15 +463,42 @@ class OctagonResetTests: OctagonTestsBase { newCliqueContext.altDSID = self.mockAuthKit.altDSID! newCliqueContext.otControl = self.otControl + // Calling with an unknown RK only resets if the local device is SOS capable, so pretend it is + OctagonSetSOSFeatureEnabled(false) + #if os(macOS) || os(iOS) + OctagonSetPlatformSupportsSOS(true) + self.manager.setSOSEnabledForPlatformFlag(true) + + let resetExpectation = self.expectation(description: "resetExpectation") + + self.fakeCuttlefishServer.resetListener = { request in + self.fakeCuttlefishServer.resetListener = nil + resetExpectation.fulfill() + XCTAssertTrue(request.resetReason.rawValue == CuttlefishResetReason.recoveryKey.rawValue, "reset reason should be recovery key") + return nil + } + #else + self.manager.setSOSEnabledForPlatformFlag(false) + OctagonSetPlatformSupportsSOS(false) + #endif + let joinWithRecoveryKeyExpectation = self.expectation(description: "joinWithRecoveryKeyExpectation callback occurs") TestsObjectiveC.recoverOctagon(usingData: newCliqueContext, recoveryKey: recoveryKey) { error in + #if os(macOS) || os(iOS) XCTAssertNil(error, "error should be nil") + #else + XCTAssertNotNil(error, "error should not be nil") + #endif joinWithRecoveryKeyExpectation.fulfill() } - self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 10) - self.wait(for: [resetExpectation], timeout: 10) + self.wait(for: [joinWithRecoveryKeyExpectation], timeout: 20) + #if os(macOS) || os(iOS) + self.wait(for: [resetExpectation], timeout: 10) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + #else + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + #endif self.verifyDatabaseMocks() } @@ -509,11 +542,9 @@ class OctagonResetTests: OctagonTestsBase { throw error } self.wait(for: [resetExpectation], timeout: 10) - } func testResetReasonHealthCheck() throws { - let containerName = OTCKContainerName let contextName = OTDefaultContext @@ -564,7 +595,8 @@ class OctagonResetTests: OctagonTestsBase { } self.wait(for: [healthCheckCallback, resetExpectation], timeout: 10) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() let dumpCallback = self.expectation(description: "dumpCallback callback occurs") @@ -575,9 +607,6 @@ class OctagonResetTests: OctagonTestsBase { dumpCallback.fulfill() } self.wait(for: [dumpCallback], timeout: 10) - - self.verifyDatabaseMocks() - self.assertEnters(context: cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) } func testLegacyJoinCircleDoesNotReset() throws { @@ -767,7 +796,7 @@ class OctagonResetTests: OctagonTestsBase { self.wait(for: [joinWithBottleExpectation], timeout: 10) self.assertEnters(context: joinerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - self.assertConsidersSelfTrusted(context:joinerContext) + self.assertConsidersSelfTrusted(context: joinerContext) self.silentZoneDeletesAllowed = true @@ -783,17 +812,32 @@ class OctagonResetTests: OctagonTestsBase { self.sendContainerChangeWaitForFetchForStates(context: joinerContext, states: [OctagonStateUntrusted]) self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, states: [OctagonStateReady]) - self.assertConsidersSelfTrusted(context:self.cuttlefishContext) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) let statusExpectation = self.expectation(description: "status callback occurs") let configuration = OTOperationConfiguration() - joinerContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _ in + joinerContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _, _ in XCTAssertEqual(.notIn, egoStatus, "cliqueStatus should be 'Not In'") statusExpectation.fulfill() } self.wait(for: [statusExpectation], timeout: 10) + } + + func testAcceptResetRemovesSelfPeer() throws { + self.startCKAccountStatusMock() + self.assertResetAndBecomeTrustedInDefaultContext() + + let otherPeer = self.makeInitiatorContext(contextID: "peer2") + self.assertResetAndBecomeTrusted(context: otherPeer) + + // And we get told about the reset + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, + states: [OctagonStateReadyUpdated, + OctagonStateUntrusted, ]) + XCTAssertEqual(self.cuttlefishContext.stateMachine.paused.wait(5 * NSEC_PER_SEC), 0, "State machine should have paused") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 1 * NSEC_PER_SEC) } } diff --git a/keychain/ot/tests/octagon/OctagonTests+SOS.swift b/keychain/ot/tests/octagon/OctagonTests+SOS.swift index 11961ed3..b1640e56 100644 --- a/keychain/ot/tests/octagon/OctagonTests+SOS.swift +++ b/keychain/ot/tests/octagon/OctagonTests+SOS.swift @@ -1,7 +1,6 @@ #if OCTAGON class OctagonSOSTests: OctagonTestsBase { - func testSOSOctagonKeyConsistency() throws { self.putFakeKeyHierarchiesInCloudKit() self.putSelfTLKSharesInCloudKit() @@ -67,11 +66,13 @@ class OctagonSOSTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() self.waitForCKModifications() + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) let peerID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() @@ -85,8 +86,6 @@ class OctagonSOSTests: OctagonTestsBase { self.aksLockState = true self.lockStateTracker.recheck() - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - // Now restart the context self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) self.restartCKKSViews() @@ -124,17 +123,18 @@ class OctagonSOSTests: OctagonTestsBase { self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) XCTAssertTrue(OctagonPerformSOSUpgrade(), "SOS upgrade should be on") + self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() self.waitForCKModifications() self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) let peerID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() XCTAssertNotNil(peerID, "Should have a peer ID") @@ -144,11 +144,6 @@ class OctagonSOSTests: OctagonTestsBase { self.mockSOSAdapter.trustedPeers.add(newSOSPeer) - self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) - self.assertConsidersSelfTrustedCachedAccountStatus(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - // Now restart the context self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) self.restartCKKSViews() @@ -160,7 +155,7 @@ class OctagonSOSTests: OctagonTestsBase { self.lockStateTracker.recheck() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) self.assertAllCKKSViewsUpload(tlkShares: 2) self.aksLockState = false @@ -176,7 +171,7 @@ class OctagonSOSTests: OctagonTestsBase { self.verifyDatabaseMocks() self.waitForCKModifications() - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } func testSOSPerformOctagonKeyConsistencyOnCircleChange() throws { @@ -241,11 +236,16 @@ class OctagonSOSTests: OctagonTestsBase { XCTAssertNotNil(error, "error should not be nil") } + /* + * I don't see any way in swift to call a deprecated API. + * But, since we're not actually testing behavior here, it's + * okay to ignore. do { try clique.safariPasswordSyncingEnabled() } catch { XCTAssertNotNil(error, "error should not be nil") } + */ do { try clique.waitForInitialSync() @@ -253,7 +253,12 @@ class OctagonSOSTests: OctagonTestsBase { XCTAssertNotNil(error, "error should not be nil") } + /* + * I don't see any way in swift to call a deprecated API. + * But, since we're not actually testing behavior here, it's + * okay to ignore. clique.viewSet(Set(), disabledViews: Set()) + */ do { try clique.setUserCredentialsAndDSID("", password: Data()) diff --git a/keychain/ot/tests/octagon/OctagonTests+SOSUpgrade.swift b/keychain/ot/tests/octagon/OctagonTests+SOSUpgrade.swift index 86e5caf3..671bed83 100644 --- a/keychain/ot/tests/octagon/OctagonTests+SOSUpgrade.swift +++ b/keychain/ot/tests/octagon/OctagonTests+SOSUpgrade.swift @@ -38,6 +38,15 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { // Also, CKKS should be configured with the prevailing policy version XCTAssertNotNil(self.injectedManager?.policy, "Should have given CKKS a TPPolicy during SOS upgrade") XCTAssertEqual(self.injectedManager?.policy?.version, prevailingPolicyVersion, "Policy given to CKKS should be prevailing policy") + + // And we should have followed the SOS Safari view state + XCTAssertTrue(self.mockSOSAdapter.safariViewEnabled, "SOS adapter should say that the safari view is enabled") + + // And we should have told SOS that CKKS4All is on + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") + + let clique = self.cliqueFor(context: self.cuttlefishContext) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) } // Verify that an SOS upgrade only does one establish (and no update trust). @@ -208,6 +217,8 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.wait(for: [establishExpectation], timeout: 10) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + XCTAssertFalse(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should not have been told that CKKS4All is enabled") + // It should be paused XCTAssertEqual(self.cuttlefishContext.stateMachine.possiblePendingFlags(), [], "Should have zero pending flags after 'not reachable'") } @@ -286,6 +297,90 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLK, within: 10 * NSEC_PER_SEC) } + func testDontSOSUpgradeIfWouldRemovePreapprover() throws { + // If a remote peer resets Octagon, they might preapprove the local device's SOS identity. + // But, if the local device responds to the reset and rejoins, it might not have received the + // SOS circle containing the remote peer. + // + // In that case, it should accept its kicked-out fate and not rejoin (and kick out the reset device). + + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.startCKAccountStatusMock() + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.verifyDatabaseMocks() + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + // Now, peer2 comes along, and resets the world + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + // but note: this peer is not yet added to the mockSOSAdapter + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, + trustedPeers: self.mockSOSAdapter.allPeers(), + essential: false) + let peer2 = self.makeInitiatorContext(contextID: "peer2", + authKitAdapter: self.mockAuthKit2, + sosAdapter: peer2mockSOS) + + self.assertResetAndBecomeTrusted(context: peer2) + + // Peer1 should accept the reset, and not rejoin. + self.fakeCuttlefishServer.joinListener = { _ in + XCTFail("Should not have attemped to re-join") + return nil + } + + self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, + states: [OctagonStateReadyUpdated, + OctagonStateBecomeUntrusted, + OctagonStateAttemptSOSUpgrade, + OctagonStateUntrusted, ]) + + XCTAssertEqual(self.cuttlefishContext.stateMachine.paused.wait(5 * NSEC_PER_SEC), 0, "State machine should have paused") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 1 * NSEC_PER_SEC) + + // But when SOS does catch up, we join just fine. + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + self.assertAllCKKSViewsUpload(tlkShares: 2) + + self.fakeCuttlefishServer.joinListener = { joinRequest in + let newDynamicInfo = joinRequest.peer.dynamicInfoAndSig.dynamicInfo() + XCTAssertEqual(newDynamicInfo.includedPeerIDs.count, 2, "Peer should trust two identities") + return nil + } + + self.mockSOSAdapter.sendTrustedPeerSetChangedUpdate() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") + + self.verifyDatabaseMocks() + } + + func testDontSOSUpgradeIfErrorFetchingPeers() throws { + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.mockSOSAdapter.trustedPeersError = NSError(domain: NSOSStatusErrorDomain, + code: 1) + self.startCKAccountStatusMock() + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateAttemptSOSUpgrade, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + } + func testSOSJoin() throws { if !OctagonPerformSOSUpgrade() { return @@ -314,6 +409,10 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() + XCTAssertTrue(self.mockSOSAdapter.safariViewEnabled, "SOS adapter should say that the safari view is enabled") + let clique = self.cliqueFor(context: self.cuttlefishContext) + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + // Peer1 should have sent a request for silent escrow update self.wait(for: [peer1EscrowRequestNotification], timeout: 5) @@ -340,6 +439,9 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: peer2) + XCTAssertTrue(peer2mockSOS.safariViewEnabled, "SOS adapter should say that the safari view is enabled") + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2), status: true) + // Peer2 should have sent a request for silent escrow update self.wait(for: [peer2EscrowRequestNotification], timeout: 5) @@ -354,12 +456,108 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { "peer 1 should not trust peer 2 (as it hasn't responded to peer2's upgradeJoin yet)") // Now, tell peer1 about the change + self.assertAllCKKSViewsUpload(tlkShares: 1) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) // Peer1 should trust peer2 now, since it upgraded it from implicitly explicitly trusted XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), "peer 1 should trust peer 2 after update") XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles") + + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + } + + func testSOSJoinWithDisabledSafariView() throws { + self.startCKAccountStatusMock() + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.mockSOSAdapter.safariViewEnabled = false + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + + self.assertAllCKKSViewsUpload(tlkShares: 2) + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + let clique = self.cliqueFor(context: self.cuttlefishContext) + + XCTAssertFalse(self.mockSOSAdapter.safariViewEnabled, "SOS adapter should say that the safari view is disabled") + + #if os(tvOS) + // TVs won't ever turn this off + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + // Watches don't have SOS, but in this test, we fake that they do. They should follow "SOS"'s state, just like phones and macs + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, + trustedPeers: self.mockSOSAdapter.allPeers(), + essential: false) + peer2mockSOS.safariViewEnabled = false + + let peer2 = self.makeInitiatorContext(contextID: "peer2", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + + peer2.startOctagonStateMachine() + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + + #if os(tvOS) + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2), status: true) + #else + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2), status: false) + #endif + } + + func testSOSJoinWithEnabledSafariViewButDisabledByPeer() throws { + self.startCKAccountStatusMock() + + // This peer joins with disabled user views + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.mockSOSAdapter.safariViewEnabled = false + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + + self.assertAllCKKSViewsUpload(tlkShares: 2) + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + XCTAssertFalse(self.mockSOSAdapter.safariViewEnabled, "SOS adapter should say that the safari view is disabled") + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") + let clique = self.cliqueFor(context: self.cuttlefishContext) + + #if os(tvOS) + // TVs won't ever turn this off + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: true) + #else + // Watches don't have SOS, but in this test, we fake that they do. They should follow "SOS"'s state, just like phones and macs + self.assertFetchUserControllableViewsSyncStatus(clique: clique, status: false) + #endif + + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, + trustedPeers: self.mockSOSAdapter.allPeers(), + essential: false) + // peer2 joins via SOS preapproval, but with the safari view enabled. It should enable user view syncing, even though the other peer has it off + peer2mockSOS.safariViewEnabled = true + + let peer2 = self.makeInitiatorContext(contextID: "peer2", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + + peer2.startOctagonStateMachine() + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + + self.assertFetchUserControllableViewsSyncStatus(clique: self.cliqueFor(context: peer2), status: true) } func testSOSJoinUponNotificationOfPreapproval() throws { @@ -382,6 +580,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { XCTAssertNotNil(peerID, "Should have a peer ID after making new friends") assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") // Peer 2 attempts to join via preapproval let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") @@ -499,7 +698,6 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { updateTrustExpectation2.fulfill() return nil - } updateTrustExpectation1.fulfill() @@ -691,10 +889,11 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { // Now, the circle status changes self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.mockSOSAdapter.trustedPeers.add(originalPeerSOSMockPeer) self.cuttlefishContext.startOctagonStateMachine() // Peer1 should upload TLKShares for SOS Peer2 via CK CRUD. We should probably fix that someday? - self.assertAllCKKSViewsUpload(tlkShares: 1) + self.assertAllCKKSViewsUpload(tlkShares: 2) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 40 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) @@ -768,6 +967,90 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") + } + + func testNotInSOSCircleAndWaitForUpgrade() throws { + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() + + self.startCKAccountStatusMock() + + self.mockSOSAdapter.sosEnabled = true + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCNotInCircle) + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) + + let upgradeExpectation = self.expectation(description: "waitForOctagonUpgrade") + self.manager.wait(forOctagonUpgrade: OTCKContainerName, context: self.otcliqueContext.context) { error in + XCTAssertNotNil(error, "error should not be nil") + XCTAssertEqual((error! as NSError).domain, "com.apple.security.sos.error", "domain should be com.apple.security.sos.error") + XCTAssertEqual((error! as NSError).code, 1037, "code should be 1037") + upgradeExpectation.fulfill() + } + self.wait(for: [upgradeExpectation], timeout: 2) + } + + func testSosUpgradeFromDisabledCDPStatus() throws { + self.putFakeKeyHierarchiesInCloudKit() + self.putSelfTLKSharesInCloudKit() + self.saveTLKMaterialToKeychain() + + self.startCKAccountStatusMock() + + self.mockSOSAdapter.sosEnabled = true + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") + + // SOS arrives! + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + + // Attempting the upgrade succeeds, now that SOS is present + let upgradeExpectation = self.expectation(description: "waitForOctagonUpgrade") + self.manager.wait(forOctagonUpgrade: OTCKContainerName, context: self.otcliqueContext.context) { error in + XCTAssertNil(error, "operation should not fail") + upgradeExpectation.fulfill() + } + self.wait(for: [upgradeExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 40 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .enabled, "CDP status should be 'enabled'") + + self.verifyDatabaseMocks() + + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + } + + func testSosUpgradeAPIWhenCDPStateOff() { + // this test checks that calling waitForOctagonUpgrade (when SOS is still absent) doesn't unconditionally set the CDP bit. + self.startCKAccountStatusMock() + + self.mockSOSAdapter.sosEnabled = true + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCCircleAbsent) + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") + + let upgradeExpectation = self.expectation(description: "waitForOctagonUpgrade") + self.manager.wait(forOctagonUpgrade: OTCKContainerName, context: self.otcliqueContext.context) { error in + XCTAssertNotNil(error, "operation should have failed - SOS is absent and Octagon cannot upgrade from it") + XCTAssertEqual((error! as NSError).domain, "com.apple.security.sos.error", "domain should be com.apple.security.sos.error") + XCTAssertEqual((error! as NSError).code, kSOSErrorNoCircle, "code should be kSOSErrorNoCircle") + upgradeExpectation.fulfill() + } + self.wait(for: [upgradeExpectation], timeout: 10) + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateWaitForCDP, within: 10 * NSEC_PER_SEC) + XCTAssertEqual(self.fetchCDPStatus(context: self.cuttlefishContext), .disabled, "CDP status should be 'disabled'") } func testDoNotAttemptUpgradeOnRestart() throws { @@ -784,12 +1067,11 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) self.verifyDatabaseMocks() self.waitForCKModifications() self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) let peerID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() XCTAssertNotNil(peerID, "Should have a peer ID after making new friends") @@ -798,15 +1080,11 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.assertAllCKKSViewsUpload(tlkShares: 1) self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) - self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - - self.cuttlefishContext.startOctagonStateMachine() self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() let restartedPeerID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() XCTAssertNotNil(restartedPeerID, "Should have a peer ID after restarting") @@ -1015,7 +1293,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() self.waitForCKModifications() @@ -1053,13 +1331,12 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) // But, SOS doesn't send this update. Let's test that the upload occurs on the next securityd restart - self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.cuttlefishContext.startOctagonStateMachine() + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) self.verifyDatabaseMocks() self.wait(for: [updateTrustExpectation], timeout: 10) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) // BUT, a second restart shouldn't hit the server @@ -1067,10 +1344,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { XCTFail("shouldn't have updateTrusted") return nil } - self.manager.removeContext(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.cuttlefishContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) - self.cuttlefishContext.startOctagonStateMachine() - + self.cuttlefishContext = self.simulateRestart(context: self.cuttlefishContext) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) } @@ -1236,6 +1510,21 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateAttemptSOSUpgrade, within: 10 * NSEC_PER_SEC) + + let updateChangesExpectation = self.expectation(description: "fetchChanges") + self.fakeCuttlefishServer.fetchChangesListener = { request in + self.fakeCuttlefishServer.fetchChangesReturnEmptyResponse = true + updateChangesExpectation.fulfill() + self.fakeCuttlefishServer.fetchChangesListener = nil + self.mockAuthKit.machineIDFetchErrors.append(NSError(domain: AKAppleIDAuthenticationErrorDomain, + code: AKAppleIDAuthenticationError.authenticationErrorCannotFindServer.rawValue, + userInfo: nil)) + + return nil + } + self.wait(for: [updateChangesExpectation], timeout: 10) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) } @@ -1366,7 +1655,7 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { // And if peer3 decides to reupgrade, but it shouldn't: there's no potentially-trusted peer that preapproves it let upgradeExpectation = self.expectation(description: "sosUpgrade call returns") - peer3.attemptSOSUpgrade { error in + peer3.waitForOctagonUpgrade { error in XCTAssertNotNil(error, "should be an error performing an SOS upgrade (the second time)") upgradeExpectation.fulfill() } @@ -1384,6 +1673,80 @@ class OctagonSOSUpgradeTests: OctagonTestsBase { } self.wait(for: [upgradeWaitExpectation], timeout: 5) } + + func testSOSJoinByPreapprovalAfterUnknownState() throws { + self.startCKAccountStatusMock() + + // First, peer 1 establishes, preapproving both peer2 and peer3. Then, peer2 and peer3 join and harmonize. + // Peer1 is never told about the follow-on joins. + // Then, the test can begin. + + self.mockSOSAdapter.circleStatus = SOSCCStatus(kSOSCCInCircle) + + let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID") + let peer3SOSMockPeer = self.createSOSPeer(peerID: "peer3ID") + + self.mockSOSAdapter.trustedPeers.add(peer2SOSMockPeer) + self.mockSOSAdapter.trustedPeers.add(peer3SOSMockPeer) + + // Due to how everything is shaking out, SOS TLKShares will be uploaded in a second transaction after Octagon uploads its TLKShares + // This isn't great: Octagon: upload SOS TLKShares alongside initial key hierarchy + self.assertAllCKKSViewsUpload(tlkShares: 3) + + self.cuttlefishContext.startOctagonStateMachine() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + let peer1ID = try self.cuttlefishContext.accountMetadataStore.getEgoPeerID() + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + + // peer2 + let peer2mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer2SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + let peer2 = self.makeInitiatorContext(contextID: "peer2", authKitAdapter: self.mockAuthKit2, sosAdapter: peer2mockSOS) + + peer2.startOctagonStateMachine() + self.assertEnters(context: peer2, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer2) + let peer2ID = try peer2.accountMetadataStore.getEgoPeerID() + + // peer3 + let peer3mockSOS = CKKSMockSOSPresentAdapter(selfPeer: peer3SOSMockPeer, trustedPeers: self.mockSOSAdapter.allPeers(), essential: false) + let peer3 = self.makeInitiatorContext(contextID: "peer3", authKitAdapter: self.mockAuthKit3, sosAdapter: peer3mockSOS) + + peer3.startOctagonStateMachine() + self.assertEnters(context: peer3, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: peer3) + let peer3ID = try peer3.accountMetadataStore.getEgoPeerID() + + // Now, tell peer2 about peer3's join + self.sendContainerChangeWaitForFetch(context: peer2) + + // Peer 1 should preapprove both peers. + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trustsByPreapproval, target: peer2ID)), + "peer 1 should trust peer 2 by preapproval") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trustsByPreapproval, target: peer2ID)), + "peer 1 should trust peer 3 by preapproval") + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer1ID)), + "peer 2 should trust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer3ID)), + "peer 2 should trust peer 3") + + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer3ID, opinion: .trusts, target: peer1ID)), + "peer 3 should trust peer 1") + XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer3ID, opinion: .trusts, target: peer2ID)), + "peer 3 should trust peer 2") + + let container = try! self.tphClient.getContainer(withContainer: self.cuttlefishContext.containerName, context: "peer3") + container.moc.performAndWait { + container.model.deletePeer(withID: peer3ID) + } + + // And we notify peer3 about this, and it should become sad + self.sendContainerChangeWaitForFetchForStates(context: peer3, states: [OctagonStateReadyUpdated, OctagonStateReady]) + self.assertConsidersSelfTrusted(context: peer3) + } } #endif // OCTAGON diff --git a/keychain/ot/tests/octagon/OctagonTests-BridgingHeader.h b/keychain/ot/tests/octagon/OctagonTests-BridgingHeader.h index 64bca2d7..0202448f 100644 --- a/keychain/ot/tests/octagon/OctagonTests-BridgingHeader.h +++ b/keychain/ot/tests/octagon/OctagonTests-BridgingHeader.h @@ -6,6 +6,7 @@ #import #import +#import #import #import "KeychainCircle/KCJoiningSession.h" @@ -37,6 +38,7 @@ #import "keychain/ot/OT.h" #import "keychain/ot/OTClique.h" +#import "keychain/ot/OTClique+Private.h" #import "keychain/ot/OTControl.h" #import "keychain/ot/OTControlProtocol.h" #import "keychain/ot/OTManager.h" @@ -82,6 +84,7 @@ #import "keychain/SecureObjectSync/SOSControlServer.h" #import "KeychainCircle/Tests/FakeSOSControl.h" #import "keychain/escrowrequest/Framework/SecEscrowRequest.h" +#import "OSX/sec/ipc/server_security_helpers.h" //CDP #import @@ -100,3 +103,6 @@ #include #import "keychain/ot/OctagonCKKSPeerAdapter.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecord.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h" +#import "keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h" diff --git a/keychain/ot/tests/octagon/OctagonTests.swift b/keychain/ot/tests/octagon/OctagonTests.swift index 5e17bae5..b8294ab7 100644 --- a/keychain/ot/tests/octagon/OctagonTests.swift +++ b/keychain/ot/tests/octagon/OctagonTests.swift @@ -42,7 +42,7 @@ class OTMockDeviceInfoAdapter: OTDeviceInformationAdapter { return self.mockOsVersion } - func serialNumber() -> String { + func serialNumber() -> String? { return self.mockSerialNumber } @@ -189,8 +189,8 @@ class OTMockLogger: NSObject, SFAnalyticsProtocol { } let OTMockEscrowRequestNotification = Notification.Name("silent-escrow-request-triggered") -class OTMockSecEscrowRequest: NSObject, SecEscrowRequestable { +class OTMockSecEscrowRequest: NSObject, SecEscrowRequestable { static var populateStatuses = false var statuses: [String: String] = [:] @@ -220,7 +220,6 @@ class OTMockSecEscrowRequest: NSObject, SecEscrowRequestable { } class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { - var tmpPath: String! var tmpURL: URL! @@ -232,6 +231,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { var intendedCKKSZones: Set! var manateeZoneID: CKRecordZone.ID! var limitedPeersAllowedZoneID: CKRecordZone.ID! + var passwordsZoneID: CKRecordZone.ID! var fakeCuttlefishServer: FakeCuttlefishServer! var fakeCuttlefishCreator: FakeCuttlefishInvocableCreator! @@ -286,6 +286,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { self.manateeZoneID = CKRecordZone.ID(zoneName: "Manatee") self.limitedPeersAllowedZoneID = CKRecordZone.ID(zoneName: "LimitedPeersAllowed") + self.passwordsZoneID = CKRecordZone.ID(zoneName: "Passwords") // We'll use this set to limit the views that CKKS brings up in the tests (mostly for performance reasons) if self.intendedCKKSZones == nil { @@ -333,21 +334,12 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { self.injectedManager!.setSyncingViewsAllowList(Set(self.intendedCKKSZones!.map { $0.zoneName })) - // Ensure we've made the CKKSKeychainView objects we're interested in - self.ckksZones.forEach { obj in - let zoneID = obj as! CKRecordZone.ID - self.ckksViews.add(self.injectedManager!.findOrCreateView(zoneID.zoneName)) - } + // Octagon is responsible for creating CKKS views; so we don't create any in the test setup // Double-check that the world of zones and views looks like what we expect XCTAssertEqual(self.ckksZones as? Set, self.intendedCKKSZones, "should still operate on our expected zones only") - XCTAssertEqual(self.ckksZones.count, self.ckksViews.count, "Should have the same number of views as expected zones") XCTAssertEqual(self.ckksZones.count, self.zones!.count, "Should have the same number of fake zones as expected zones") - XCTAssertEqual(Set(self.ckksViews.map { ($0 as! CKKSKeychainView).zoneName }), - Set(self.ckksZones.map { ($0 as! CKRecordZone.ID).zoneName }), - "ckksViews should match ckksZones") - // Octagon must initialize the views self.automaticallyBeginCKKSViewCloudKitOperation = false @@ -412,6 +404,11 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { XCTAssertTrue(self.manager.allContextsPause(10 * NSEC_PER_SEC), "All cuttlefish contexts should pause") + do { + try self.tphClient.containerMap.deleteAllPersistentStores() + } catch { + XCTFail("Failed to clean up CoreData databases: \(error)") + } self.tphClient.containerMap.removeAllContainers() super.tearDown() @@ -448,7 +445,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { } override func managedViewList() -> Set { - if(self.overrideUseCKKSViewsFromPolicy) { + if self.overrideUseCKKSViewsFromPolicy { let viewNames = self.ckksZones.map { ($0 as! CKRecordZone.ID).zoneName } return Set(viewNames) } else { @@ -463,9 +460,13 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { } func fetchEgoPeerID() -> String { + return self.fetchEgoPeerID(context: self.cuttlefishContext) + } + + func fetchEgoPeerID(context: OTCuttlefishContext) -> String { var ret: String! let fetchPeerIDExpectation = self.expectation(description: "fetchPeerID callback occurs") - self.cuttlefishContext.rpcFetchEgoPeerID { peerID, fetchError in + context.rpcFetchEgoPeerID { peerID, fetchError in XCTAssertNil(fetchError, "should not error fetching ego peer ID") XCTAssertNotNil(peerID, "Should have a peer ID") ret = peerID @@ -481,8 +482,8 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { self.tphClient.setAllowedMachineIDsWithContainer(container, context: context, allowedMachineIDs: self.mockAuthKit.currentDeviceList(), honorIDMSListChanges: honorIDMSListChanges) { _, error in - XCTAssertNil(error, "Should be no error setting allow list") - allowListExpectation.fulfill() + XCTAssertNil(error, "Should be no error setting allow list") + allowListExpectation.fulfill() } self.wait(for: [allowListExpectation], timeout: 10) } @@ -520,7 +521,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { let statusexpectation = self.expectation(description: "trust status returns") let configuration = OTOperationConfiguration() configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, isLocked, _ in + context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, isLocked, _, _ in XCTAssertEqual(egoStatus, .in, "Self peer (for \(context)) should be trusted") XCTAssertNotNil(egoPeerID, "Should have a peerID") XCTAssertEqual(isLocked, isLocked, "should be \(isLocked)") @@ -537,7 +538,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { configuration.useCachedAccountStatus = true configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, _, _ in + context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, _, _, _ in XCTAssertEqual(egoStatus, .in, "Cached self peer (for \(context)) should be trusted") XCTAssertNotNil(egoPeerID, "Should have a (cached) peerID") cachedStatusexpectation.fulfill() @@ -556,7 +557,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { configuration.useCachedAccountStatus = false let statusexpectation = self.expectation(description: "(cached) trust status returns") - context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, _, _ in + context.rpcTrustStatus(configuration) { egoStatus, egoPeerID, _, _, _, _ in XCTAssertEqual(egoStatus, .in, "Self peer (for \(context)) should be trusted") XCTAssertNotNil(egoPeerID, "Should have a peerID") statusexpectation.fulfill() @@ -569,7 +570,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { let statusexpectation = self.expectation(description: "trust status returns") let configuration = OTOperationConfiguration() configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - context.rpcTrustStatus(configuration) { egoStatus, _, _, _, _ in + context.rpcTrustStatus(configuration) { egoStatus, _, _, _, _, _ in // TODO: separate 'untrusted' and 'no trusted peers for account yet' XCTAssertTrue([.notIn, .absent].contains(egoStatus), "Self peer (for \(context)) should be distrusted or absent") statusexpectation.fulfill() @@ -582,7 +583,7 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { let statusexpectation = self.expectation(description: "trust status returns") let configuration = OTOperationConfiguration() configuration.timeoutWaitForCKAccount = 500 * NSEC_PER_MSEC - context.rpcTrustStatus(configuration) { egoStatus, _, _, _, _ in + context.rpcTrustStatus(configuration) { egoStatus, _, _, _, _, _ in // TODO: separate 'untrusted' and 'no trusted peers for account yet' XCTAssertTrue([.notIn, .absent].contains(egoStatus), "Self peer (for \(context)) should be distrusted or absent") statusexpectation.fulfill() @@ -626,36 +627,29 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { } func restartCKKSViews() { - let viewNames = self.ckksViews.map { ($0 as! CKKSKeychainView).zoneName } - self.ckksViews.removeAllObjects() + let viewNames = self.intendedCKKSZones.map { $0.zoneName } self.injectedManager!.resetSyncingPolicy() for view in viewNames { - self.ckksViews.add(self.injectedManager!.restartZone(view)) + self.injectedManager!.restartZone(view) } } func sendAllCKKSTrustedPeersChanged() { - self.ckksViews.forEach { view in + self.injectedManager!.views.forEach { _, view in (view as! CKKSKeychainView).trustedPeerSetChanged(nil) } } - func sendAllCKKSViewsZoneChanged() { - for expectedView in self.ckksZones { - let view = self.injectedManager?.findView((expectedView as! CKRecordZone.ID).zoneName) - XCTAssertNotNil(view, "Should have a view '\(expectedView)'") - view!.notifyZoneChange(nil) - } - } - func assert(ckks: CKKSKeychainView, enters: String, within: UInt64) { - XCTAssertEqual(0, (ckks.keyHierarchyConditions[enters] as! CKKSCondition).wait(within), "CKKS state machine should enter '\(enters)' (currently '\(ckks.keyHierarchyState)')") + XCTAssertEqual(0, (ckks.stateMachine.stateConditions[enters] as! CKKSCondition).wait(within), "CKKS state machine should enter '\(enters)' (currently '\(ckks.stateMachine.currentState)')") } - func assertAllCKKSViews(enter: String, within: UInt64) { - for expectedView in self.ckksZones { + func assertAllCKKSViews(enter: String, within: UInt64, filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { expectedView in let view = self.injectedManager?.findView((expectedView as! CKRecordZone.ID).zoneName) XCTAssertNotNil(view, "Should have a view '\(expectedView)'") self.assert(ckks: view!, enters: enter, within: within) @@ -670,32 +664,42 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { } } - func assertAllCKKSViewsUpload(tlkShares: UInt) { - for expectedView in self.ckksZones { + func assertAllCKKSViewsUpload(tlkShares: UInt, filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { expectedView in self.expectCKModifyKeyRecords(0, currentKeyPointerRecords: 0, tlkShareRecords: tlkShares, zoneID: expectedView as! CKRecordZone.ID) } } - func putFakeKeyHierarchiesInCloudKit() { - self.ckksZones.forEach { zone in + func putFakeKeyHierarchiesInCloudKit(filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { zone in self.putFakeKeyHierarchy(inCloudKit: zone as! CKRecordZone.ID) } } - func putSelfTLKSharesInCloudKit() { - self.ckksZones.forEach { zone in + func putSelfTLKSharesInCloudKit(filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { zone in self.putSelfTLKShares(inCloudKit: zone as! CKRecordZone.ID) } } - func putFakeDeviceStatusesInCloudKit() { - self.ckksZones.forEach { zone in + func putFakeDeviceStatusesInCloudKit(filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { zone in self.putFakeDeviceStatus(inCloudKit: zone as! CKRecordZone.ID) } } - func saveTLKMaterialToKeychain() { - self.ckksZones.forEach { zone in + func saveTLKMaterialToKeychain(filter: ((CKRecordZone.ID) -> Bool)? = nil) { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { zone in self.saveTLKMaterial(toKeychain: zone as! CKRecordZone.ID) } } @@ -710,8 +714,10 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { self.wait(for: [resetExpectation], timeout: 30) } - func putSelfTLKSharesInCloudKit(context: OTCuttlefishContext) throws { - try self.ckksZones.forEach { zone in + func putSelfTLKSharesInCloudKit(context: OTCuttlefishContext, filter: ((CKRecordZone.ID) -> Bool)? = nil) throws { + let f: ((CKRecordZone.ID) -> Bool) = filter ?? { (zone: CKRecordZone.ID) in return true } + + try self.ckksZones.filter { f($0 as! CKRecordZone.ID) }.forEach { zone in try self.putTLKShareInCloudKit(to: context, from: context, zoneID: zone as! CKRecordZone.ID) } } @@ -734,16 +740,41 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { } func putRecoveryKeyTLKSharesInCloudKit(recoveryKey: String, salt: String) throws { - try self.ckksZones.forEach { zone in - try self.putRecoveryKeyTLKShareInCloudKit(recoveryKey: recoveryKey, salt: salt, zoneID: zone as! CKRecordZone.ID) + let recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) + + self.ckksZones.forEach { zone in + let zoneID = zone as! CKRecordZone.ID + let zoneKeys = self.keys![zoneID] as! ZoneKeys + self.putTLKShare(inCloudKit: zoneKeys.tlk!, from: recoveryKeys.peerKeys, to: recoveryKeys.peerKeys, zoneID: zoneID) } } - func putRecoveryKeyTLKShareInCloudKit(recoveryKey: String, salt: String, zoneID: CKRecordZone.ID) throws { + func putRecoveryKeyTLKSharesInCloudKit(recoveryKey: String, salt: String, sender: OTCuttlefishContext) throws { let recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) - let zoneKeys = self.keys![zoneID] as! ZoneKeys - self.putTLKShare(inCloudKit: zoneKeys.tlk!, from: recoveryKeys.peerKeys, to: recoveryKeys.peerKeys, zoneID: zoneID) + let senderAccountMetadata = try sender.accountMetadataStore.loadOrCreateAccountMetadata() + let senderPeerKeys: OctagonSelfPeerKeys = try loadEgoKeysSync(peerID: senderAccountMetadata.peerID) + + self.ckksZones.forEach { zone in + let zoneID = zone as! CKRecordZone.ID + let zoneKeys = self.keys![zoneID] as! ZoneKeys + self.putTLKShare(inCloudKit: zoneKeys.tlk!, from: senderPeerKeys, to: recoveryKeys.peerKeys, zoneID: zoneID) + } + } + + func recoveryKeyTLKSharesInCloudKit(recoveryKey: String, salt: String) throws -> Bool { + let recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) + + return self.tlkSharesInCloudKit(receiverPeerID: recoveryKeys.peerKeys.peerID, + senderPeerID: recoveryKeys.peerKeys.peerID) + } + + func recoveryKeyTLKSharesInCloudKit(recoveryKey: String, salt: String, sender: OTCuttlefishContext) throws -> Bool { + let recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt) + let senderAccountMetadata = try sender.accountMetadataStore.loadOrCreateAccountMetadata() + + return self.tlkSharesInCloudKit(receiverPeerID: recoveryKeys.peerKeys.peerID, + senderPeerID: senderAccountMetadata.peerID) } func assertSelfTLKSharesInCloudKit(context: OTCuttlefishContext) { @@ -764,12 +795,20 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { } func assertTLKSharesInCloudKit(receiverPeerID: String, senderPeerID: String) { - for case let view as CKKSKeychainView in self.ckksViews { - XCTAssertNoThrow(try self.assertTLKShareInCloudKit(receiverPeerID: receiverPeerID, senderPeerID: senderPeerID, zoneID: view.zoneID), "view \(view) should have a self TLK uploaded") + XCTAssertTrue(self.tlkSharesInCloudKit(receiverPeerID: receiverPeerID, senderPeerID: senderPeerID), "All views should have a self TLK uploaded") + } + + func tlkSharesInCloudKit(receiverPeerID: String, senderPeerID: String) -> Bool { + let tlkContains: [Bool] = self.ckksViews.map { + let view: CKKSKeychainView = $0 as! CKKSKeychainView + return self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, senderPeerID: senderPeerID, zoneID: view.zoneID) } + + // return true if all entries in tlkContains is true + return tlkContains.allSatisfy { $0 == true } } - func tlkShareInCloudKit(receiverPeerID: String, senderPeerID: String, zoneID: CKRecordZone.ID) throws -> Bool { + func tlkShareInCloudKit(receiverPeerID: String, senderPeerID: String, zoneID: CKRecordZone.ID) -> Bool { guard let zone = self.zones![zoneID] as? FakeCKZone else { return false } @@ -785,8 +824,8 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { return false } - func assertTLKShareInCloudKit(receiverPeerID: String, senderPeerID: String, zoneID: CKRecordZone.ID) throws { - XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, senderPeerID: senderPeerID, zoneID: zoneID), + func assertTLKShareInCloudKit(receiverPeerID: String, senderPeerID: String, zoneID: CKRecordZone.ID) { + XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, senderPeerID: senderPeerID, zoneID: zoneID), "Should have found a TLKShare for peerID \(String(describing: receiverPeerID)) sent by \(String(describing: senderPeerID)) for \(zoneID)") } @@ -895,9 +934,11 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { // Please ensure that the first state in this list is not the state that the context is currently in func sendContainerChangeWaitForFetchForStates(context: OTCuttlefishContext, states: [String]) { - // Pull the first state out before sending the notification - let firstState = states.first! - let firstCondition = (context.stateMachine.stateConditions[firstState] as! CKKSCondition) + + // If we wait for each condition in order here, we might lose thread races and cause issues. + // Fetch every state we'll examine (note that this doesn't handle repeated checks for the same state) + + let stateConditions = states.map { ($0, context.stateMachine.stateConditions[$0] as! CKKSCondition) } let updateTrustExpectation = self.expectation(description: "fetchChanges") @@ -909,10 +950,11 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { context.notifyContainerChange(nil) self.wait(for: [updateTrustExpectation], timeout: 10) - // Wait for the previously acquired first state, then wait for each in turn - XCTAssertEqual(0, firstCondition.wait(10 * NSEC_PER_SEC), "State machine should enter '\(String(describing: firstState))'") - for state in states.dropFirst() { - self.assertEnters(context: context, state: state, within: 10 * NSEC_PER_SEC) + for (state, stateCondition) in stateConditions { + XCTAssertEqual(0, stateCondition.wait(10 * NSEC_PER_SEC), "State machine should enter '\(String(describing: state))'") + if state == OctagonStateReady || state == OctagonStateUntrusted { + XCTAssertEqual(0, context.stateMachine.paused.wait(10 * NSEC_PER_SEC), "State machine should pause soon") + } } } @@ -1049,7 +1091,6 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { } func assertSelfOSVersion(_ osVersion: String) { - let statusExpectation = self.expectation(description: "status callback occurs") self.tphClient.dumpEgoPeer(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { _, _, stableInfo, _, error in XCTAssertNil(error, "should be no error dumping ego peer") @@ -1063,6 +1104,8 @@ class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest { class OctagonTests: OctagonTestsBase { func testTPHPrepare() { + self.startCKAccountStatusMock() + let contextName = "asdf" let containerName = "test_container" @@ -1079,22 +1122,34 @@ class OctagonTests: OctagonTestsBase { osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in - XCTAssertNil(error, "Should be no error preparing identity") - XCTAssertNotNil(peerID, "Should be a peer ID") - XCTAssertNotNil(permanentInfo, "Should have a permenent info") - XCTAssertNotNil(permanentInfoSig, "Should have a permanent info signature") - XCTAssertNotNil(stableInfo, "Should have a stable info") - XCTAssertNotNil(stableInfoSig, "Should have a stable info signature") + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in + XCTAssertNil(error, "Should be no error preparing identity") + XCTAssertNotNil(peerID, "Should be a peer ID") + XCTAssertNotNil(permanentInfo, "Should have a permenent info") + XCTAssertNotNil(permanentInfoSig, "Should have a permanent info signature") + XCTAssertNotNil(stableInfo, "Should have a stable info") + XCTAssertNotNil(stableInfoSig, "Should have a stable info signature") - tphPrepareExpectation.fulfill() + let adapter = OctagonCKKSPeerAdapter(peerID: peerID!, containerName: containerName, contextID: contextName, cuttlefishXPC: CuttlefishXPCWrapper(cuttlefishXPCConnection: self.tphXPCProxy.connection())) + + do { + let selves = try adapter.fetchSelfPeers() + try TestsObjectiveC.testSecKey(selves) + } catch { + XCTFail("Test failed: \(error)") + } + + tphPrepareExpectation.fulfill() } self.wait(for: [tphPrepareExpectation], timeout: 10) } func testTPHMultiPrepare() throws { + self.startCKAccountStatusMock() + let contextName = OTDefaultContext let containerName = OTCKContainerName @@ -1113,8 +1168,9 @@ class OctagonTests: OctagonTestsBase { osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -1141,8 +1197,9 @@ class OctagonTests: OctagonTestsBase { osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -1200,8 +1257,9 @@ class OctagonTests: OctagonTestsBase { osVersion: "asdf", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(peerID, "Should be a peer ID") XCTAssertNotNil(permanentInfo, "Should have a permenent info") @@ -1543,29 +1601,23 @@ class OctagonTests: OctagonTestsBase { // these should be failures assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKUpload, within: 10 * NSEC_PER_SEC) self.cuttlefishContext.rpcStatus { _, _ in - } + } self.verifyDatabaseMocks() XCTAssertEqual(0, self.cuttlefishContext.stateMachine.paused.wait(60 * NSEC_PER_SEC), "Main cuttlefish context should quiesce before the test ends") } - func testNewFriendsForEmptyAccountWithTLKs() throws { + func testNewFriendsForEmptyAccountWithExistingTLKs() throws { self.putFakeKeyHierarchiesInCloudKit() self.saveTLKMaterialToKeychain() self.startCKAccountStatusMock() - // CKKS should go into 'logged out', as Octagon hasn't told it to go yet - assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC) - self.cuttlefishContext.startOctagonStateMachine() XCTAssertNoThrow(try self.cuttlefishContext.setCDPEnabled()) self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) - assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) - - // CKKS should reset the zones after Octagon has entered - self.silentZoneDeletesAllowed = true + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) do { let clique = try OTClique.newFriends(withContextData: self.otcliqueContext, resetReason: .testGenerated) @@ -1578,13 +1630,11 @@ class OctagonTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) - // and all subCKKSes should enter ready upload... - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() } func testLoadToReadyOnRestart() throws { - let startDate = Date() self.startCKAccountStatusMock() @@ -1849,6 +1899,9 @@ class OctagonTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: self.cuttlefishContext) assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) self.verifyDatabaseMocks() + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatusIsSet, "SOS adapter should have been told that CKKS4All is not enabled") + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled") + self.mockSOSAdapter.ckks4AllStatusIsSet = false // Technically, it's a server-side cuttlefish error for the last signed-in peer to leave. But, for now, just go for it. XCTAssertNoThrow(try clique.leave(), "Should be no error departing clique") @@ -1858,6 +1911,9 @@ class OctagonTests: OctagonTestsBase { self.assertConsidersSelfUntrusted(context: self.cuttlefishContext) assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTrust, within: 10 * NSEC_PER_SEC) + XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatusIsSet, "SOS adapter should have been told that CKKS4All is not enabled") + XCTAssertFalse(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is not enabled") + // TODO: an item added here shouldn't sync } @@ -1881,7 +1937,7 @@ class OctagonTests: OctagonTestsBase { self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) self.assertConsidersSelfTrusted(context: self.cuttlefishContext) self.verifyDatabaseMocks() - assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) let peer1ID = fetchEgoPeerID() @@ -1926,8 +1982,9 @@ class OctagonTests: OctagonTestsBase { osVersion: peer2DeviceAdapter.osVersion(), policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(permanentInfo, "Should have a permanent identity") XCTAssertNotNil(permanentInfoSig, "Should have a permanent identity signature") @@ -1950,7 +2007,7 @@ class OctagonTests: OctagonTestsBase { voucherSig: voucherSig!, ckksKeys: [], tlkShares: [], - preapprovedKeys: []) { peerID, _, _, _, error in + preapprovedKeys: []) { peerID, _, _, error in XCTAssertNil(error, "Should be no error joining") XCTAssertNotNil(peerID, "Should have a peerID") peer2ID = peerID @@ -1973,6 +2030,7 @@ class OctagonTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: peer2) // Now that we've lied enough... + self.assertAllCKKSViewsUpload(tlkShares: 1, filter: { $0.zoneName == "LimitedPeersAllowed" }) self.sendContainerChangeWaitForFetch(context: self.cuttlefishContext) XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer1ID, opinion: .trusts, target: peer2ID)), @@ -1980,6 +2038,10 @@ class OctagonTests: OctagonTestsBase { XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: peer2ID, opinion: .trusts, target: peer1ID)), "peer 2 should trust peer 1") + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + self.verifyDatabaseMocks() + // But does peer1 claim to know peer2? do { let peersByID = try clique.peerDeviceNamesByPeerID() @@ -2028,7 +2090,6 @@ class OctagonTests: OctagonTestsBase { let status = clique.fetchStatus(nil) XCTAssertEqual(status, CliqueStatus.in, "clique should return In") - } catch { XCTFail("Shouldn't have errored making new friends: \(error)") throw error @@ -2058,7 +2119,6 @@ class OctagonTests: OctagonTestsBase { OctagonSetPlatformSupportsSOS(true) let status = newClique.fetchStatus(nil) XCTAssertEqual(status, CliqueStatus.in, "clique should return In") - } catch { XCTFail("Shouldn't have errored making new friends: \(error)") throw error @@ -2151,10 +2211,10 @@ class OctagonTests: OctagonTestsBase { let path = OctagonStateTransitionPath(from: [ OctagonStateResetAndEstablish: [ OctagonStateBottleJoinVouchWithBottle: [ - OctagonStateResetAndEstablish: OctagonStateTransitionPathStep.success(), - ], + OctagonStateResetAndEstablish: OctagonStateTransitionPathStep.success(), ], - ]) + ], + ]) let watcher = OctagonStateTransitionWatcher(named: "should-fail", serialQueue: self.cuttlefishContext.queue, path: path!, @@ -2210,7 +2270,7 @@ class OctagonTests: OctagonTestsBase { let cfuExpectation = self.expectation(description: "cfu callback occurs") self.cuttlefishContext.followupHandler.clearAllPostedFlags() - self.cuttlefishContext.checkTrustStatusAndPostRepairCFUIfNecessary { _, posted, _, error in + self.cuttlefishContext.checkTrustStatusAndPostRepairCFUIfNecessary { _, posted, _, _, error in #if !os(tvOS) XCTAssertTrue(posted, "posted should be true") #else @@ -2228,9 +2288,6 @@ class OctagonTests: OctagonTestsBase { self.startCKAccountStatusMock() - self.aksLockState = true - self.lockStateTracker.recheck() - let initiatorContext = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext, sosAdapter: self.mockSOSAdapter, @@ -2239,14 +2296,19 @@ class OctagonTests: OctagonTestsBase { accountStateTracker: self.accountStateTracker, deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iPhone9,1", deviceName: "test-SOS-iphone", serialNumber: "456", osVersion: "iOS (fake version)")) - let accountMetadataStoreActual = initiatorContext.accountMetadataStore //grab the previously instantiated account state holder + // Pre-create some Account metadata, so that Octagon will experience a keychain locked error when loading + try initiatorContext.accountMetadataStore.persistAccountChanges { metadata in + return metadata + } - initiatorContext.setAccountStateHolder(self.accountMetaDataStore) // set the mocked account state holder + // Lock all AKS classes + self.aksLockState = true + SecMockAKS.lockClassA_C() + self.lockStateTracker.recheck() initiatorContext.startOctagonStateMachine() - self.assertEnters(context: initiatorContext, state: OctagonStateWaitForUnlock, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: initiatorContext, state: OctagonStateWaitForClassCUnlock, within: 10 * NSEC_PER_SEC) - initiatorContext.setAccountStateHolder(accountMetadataStoreActual) //re-set the actual store self.aksLockState = false self.lockStateTracker.recheck() @@ -2304,21 +2366,23 @@ class OctagonTests: OctagonTestsBase { self.assertConsidersSelfTrusted(context: self.cuttlefishContext) #if !os(tvOS) - let expectedViews = Set(["ProtectedCloudStorage", - "AutoUnlock", - "LimitedPeersAllowed", - "SecureObjectSync", - "DevicePairing", - "Engram", - "Home", - "Applications", - "WiFi", - "Health", - "Manatee", - // Cuttlefish: remove Safari prefix from view names - "SafariCreditCards", - "SafariPasswords", - "ApplePay", ]) + let expectedViews = Set([ + "ApplePay", + "Applications", + "AutoUnlock", + "Backstop", + "CreditCards", + "DevicePairing", + "Engram", + "Health", + "Home", + "LimitedPeersAllowed", + "Manatee", + "Passwords", + "ProtectedCloudStorage", + "SecureObjectSync", + "WiFi", + ]) #else let expectedViews = Set(["LimitedPeersAllowed", "Home", @@ -2326,9 +2390,9 @@ class OctagonTests: OctagonTestsBase { #endif let getViewsExpectation = self.expectation(description: "getViews callback happens") - self.tphClient.fetchCurrentPolicy(withContainer: OTCKContainerName, context: OTDefaultContext) { outViews, _, error in + self.tphClient.fetchCurrentPolicy(withContainer: OTCKContainerName, context: OTDefaultContext, modelIDOverride: nil) { outPolicy, _, error in XCTAssertNil(error, "should not have failed") - XCTAssertEqual(expectedViews, Set(outViews!)) + XCTAssertEqual(expectedViews, outPolicy!.viewList) getViewsExpectation.fulfill() } self.wait(for: [getViewsExpectation], timeout: 10) @@ -2337,7 +2401,6 @@ class OctagonTests: OctagonTestsBase { let octagonNotificationName = "com.apple.security.octagon.trust-status-change" func testNotifications() throws { - let contextName = OTDefaultContext let containerName = OTCKContainerName @@ -2505,7 +2568,6 @@ class OctagonTests: OctagonTestsBase { } func testAPSRateLimiter() throws { - let untrustedNotification = XCTDarwinNotificationExpectation(notificationName: octagonNotificationName) self.startCKAccountStatusMock() @@ -2631,7 +2693,7 @@ class OctagonTests: OctagonTestsBase { //this call uses the default value and should timeout in 10 seconds let upgradeCallback = self.expectation(description: "attempting sos upgrade callback") - self.manager.attemptSosUpgrade(OTCKContainerName, context: OTDefaultContext) { error in + self.manager.wait(forOctagonUpgrade: OTCKContainerName, context: OTDefaultContext) { error in XCTAssertNotNil(error, "error should not be nil") upgradeCallback.fulfill() } @@ -2639,7 +2701,6 @@ class OctagonTests: OctagonTestsBase { } func testTTRTrusted() { - self.startCKAccountStatusMock() self.cuttlefishContext.startOctagonStateMachine() @@ -2681,13 +2742,13 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { let limitedTLKs: Bool } - func assertTLKs(expectation: TestCase, receiverPeerID: String, senderPeerID: String) throws { - let haveManateeTLK = try self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, - senderPeerID: senderPeerID, - zoneID: self.manateeZoneID) - let haveLimitedPeersAllowedTLK = try self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, - senderPeerID: senderPeerID, - zoneID: self.limitedPeersAllowedZoneID) + func assertTLKs(expectation: TestCase, receiverPeerID: String, senderPeerID: String) { + let haveManateeTLK = self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, + senderPeerID: senderPeerID, + zoneID: self.manateeZoneID) + let haveLimitedPeersAllowedTLK = self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, + senderPeerID: senderPeerID, + zoneID: self.limitedPeersAllowedZoneID) XCTAssertEqual(haveManateeTLK, expectation.manateeTLKs, "manatee should be what's expected: \(expectation)") XCTAssertEqual(haveLimitedPeersAllowedTLK, expectation.limitedTLKs, "limited should be what's expected: \(expectation)") @@ -2714,9 +2775,8 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) - let ckksKeys: [CKKSKeychainBackedKeySet] = self.ckksViews.compactMap { view in - let viewName = (view as! CKKSKeychainView).zoneName - let currentKeySet = CKKSCurrentKeySet.load(forZone: CKRecordZone.ID(zoneName: viewName)) + let ckksKeys: [CKKSKeychainBackedKeySet] = self.intendedCKKSZones.compactMap { zoneID in + let currentKeySet = CKKSCurrentKeySet.load(forZone: zoneID) return try! currentKeySet.asKeychainBackedSet() } @@ -2751,8 +2811,9 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { osVersion: "something", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(permanentInfo, "Should have a permanent identity") XCTAssertNotNil(permanentInfoSig, "Should have a permanent identity signature") @@ -2771,9 +2832,9 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { XCTAssertNotNil(voucher, "Should have a voucher") XCTAssertNotNil(voucherSig, "Should have a voucher signature") - try! self.assertTLKs(expectation: testCase, - receiverPeerID: peerID!, - senderPeerID: senderPeerID) + self.assertTLKs(expectation: testCase, + receiverPeerID: peerID!, + senderPeerID: senderPeerID) self.tphClient.join(withContainer: OTCKContainerName, context: peer2ContextID, @@ -2781,7 +2842,7 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { voucherSig: voucherSig!, ckksKeys: [], tlkShares: [], - preapprovedKeys: []) { peerID, _, _, _, error in + preapprovedKeys: []) { peerID, _, _, error in XCTAssertNil(error, "Should be no error joining") XCTAssertNotNil(peerID, "Should have a peerID") joinExpectation.fulfill() @@ -2800,14 +2861,13 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { XCTAssertNil(voucherSig, "voucherSig should be nil") XCTAssertNotNil(error, "error should be non nil") - try! self.assertTLKs(expectation: testCase, - receiverPeerID: peerID!, - senderPeerID: senderPeerID) + self.assertTLKs(expectation: testCase, + receiverPeerID: peerID!, + senderPeerID: senderPeerID) joinExpectation.fulfill() } } - } self.wait(for: [joinExpectation], timeout: 10) } @@ -2859,8 +2919,9 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { osVersion: "something", policyVersion: nil, policySecrets: nil, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, _, error in XCTAssertNil(error, "Should be no error preparing identity") XCTAssertNotNil(permanentInfo, "Should have a permanent identity") XCTAssertNotNil(permanentInfoSig, "Should have a permanent identity signature") @@ -2883,7 +2944,7 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { voucherSig: voucher!.sig, ckksKeys: [], tlkShares: [], - preapprovedKeys: []) { peerID, _, _, _, error in + preapprovedKeys: []) { peerID, _, _, error in if expectedSuccess { XCTAssertNil(error, "expected success") XCTAssertNotNil(peerID, "peerID should be set") @@ -2893,7 +2954,6 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { } joinExpectation.fulfill() } - } self.wait(for: [joinExpectation], timeout: 10) @@ -2928,9 +2988,9 @@ class OctagonTestsOverrideModelBase: OctagonTestsBase { self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) } - try self.assertTLKs(expectation: testCase, - receiverPeerID: peer2ID, - senderPeerID: peer1ID) + self.assertTLKs(expectation: testCase, + receiverPeerID: peer2ID, + senderPeerID: peer1ID) } } } diff --git a/keychain/ot/tests/octagon/OctagonTestsXPCConnections.swift b/keychain/ot/tests/octagon/OctagonTestsXPCConnections.swift index a972b584..bfb7d304 100644 --- a/keychain/ot/tests/octagon/OctagonTestsXPCConnections.swift +++ b/keychain/ot/tests/octagon/OctagonTestsXPCConnections.swift @@ -17,14 +17,14 @@ class ProxyXPCConnection: NSObject, NSXPCListenerDelegate { self.listener.resume() } - public func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool { + func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool { newConnection.exportedInterface = self.serverInterface newConnection.exportedObject = self.obj newConnection.resume() return true } - public func connection() -> NSXPCConnection { + func connection() -> NSXPCConnection { let connection = NSXPCConnection(listenerEndpoint: self.listener.endpoint) connection.remoteObjectInterface = self.serverInterface connection.resume() diff --git a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+Piggybacking.swift b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+Piggybacking.swift index 2c76a5ec..9c45c969 100644 --- a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+Piggybacking.swift +++ b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+Piggybacking.swift @@ -77,7 +77,6 @@ let version0_txt: [UInt8] = [ let version0_txt_len = 395 extension OctagonPairingTests { - func testPiggybacking() { self.startCKAccountStatusMock() @@ -214,6 +213,7 @@ extension OctagonPairingTests { XCTAssertNotNil(requestSession, "requestSession should not be nil") XCTAssertNotNil(requestDelegate, "requestDelegate should not be nil") XCTAssertNotNil(acceptDelegate, "acceptDelegate should not be nil") + OctagonSetPlatformSupportsSOS(false) do { initialMessageContainingOctagonVersion = try requestSession!.initialMessage() @@ -269,7 +269,6 @@ extension OctagonPairingTests { do { identityMessage = try requestCircleSession.initialMessage() XCTAssertNotNil(identityMessage, "No identity message") - } catch { XCTAssertNil(error, "error retrieving identityMessage message") } @@ -284,7 +283,6 @@ extension OctagonPairingTests { XCTAssertNotNil(voucherMessage, "No voucherMessage message") } catch { XCTAssertNil(error, "error retrieving voucherMessage message") - } var nothing: Data? @@ -293,7 +291,6 @@ extension OctagonPairingTests { XCTAssertNotNil(nothing, "No nothing message") } catch { XCTAssertNil(error, "error retrieving nothing message") - } XCTAssertTrue(requestSession!.isDone(), "requestor should be done") @@ -545,6 +542,43 @@ extension OctagonPairingTests { self.wait(for: [firstMessageWithNewJoiningConfigCallback], timeout: 10) } + func testPairingResetWithNoAccount() { + // no account + self.mockAuthKit.altDSID = nil + self.mockAuthKit.hsa2 = false + + // no cloudkit account + self.accountStatus = .noAccount + self.startCKAccountStatusMock() + + self.cuttlefishContext.startOctagonStateMachine() + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + let joining = OTJoiningConfiguration(protocolType: "OctagonPiggybacking", + uniqueDeviceID: "requester", + uniqueClientID: "client", + pairingUUID: "3B99AE99-5FEB-4AF5-9992-DF042118B5FE", + containerName: self.cuttlefishContext.containerName, + contextID: self.cuttlefishContext.contextID, + epoch: 1, + isInitiator: true) + + self.cuttlefishContext.handlePairingRestart(joining) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + + let joining2 = OTJoiningConfiguration(protocolType: "OctagonPiggybacking", + uniqueDeviceID: "requester", + uniqueClientID: "client", + pairingUUID: "3B99AE99-5FEB-4AF5-0000-DF042118B5FE", + containerName: self.cuttlefishContext.containerName, + contextID: self.cuttlefishContext.contextID, + epoch: 1, + isInitiator: true) + + self.cuttlefishContext.handlePairingRestart(joining2) + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateNoAccount, within: 10 * NSEC_PER_SEC) + } + func testVersion2ofPiggybackingWithSOS() throws { KCSetJoiningOctagonPiggybackingEnabled(true) OctagonSetPlatformSupportsSOS(true) @@ -636,7 +670,177 @@ extension OctagonPairingTests { XCTAssertNotNil(parsedMessage.firstData, "No octagon message") XCTAssertNotNil(parsedMessage.secondData, "No sos message") XCTAssertNotNil(identityMessage, "No identity message") + } catch { + XCTAssertNil(error, "error retrieving identityMessage message") + } + + // Double-check that there's an Octagon message in the packet + let initiatorIdentityMessage = try self.unpackPiggybackingInitialMessage(identityMessage: identityMessage!, session: acceptSession!.accessSession()) + XCTAssertTrue(initiatorIdentityMessage.hasPrepare, "Pairing message should contain prepared information") + + var voucherMessage: Data? + do { + voucherMessage = try acceptSession!.processMessage(identityMessage!) + let parsedMessage = try KCJoiningMessage(der: identityMessage!) + XCTAssertNotNil(parsedMessage.firstData, "No octagon message") + XCTAssertNotNil(parsedMessage.secondData, "No sos message") + XCTAssertNotNil(voucherMessage, "No voucherMessage message") + } catch { + XCTAssertNil(error, "error retrieving voucherMessage message") + } + var nothing: Data? + do { + nothing = try requestCircleSession.processMessage(voucherMessage!) + XCTAssertNotNil(nothing, "No nothing message") + } catch { + XCTAssertNil(error, "error retrieving nothing message") + } + + assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(requestSession!.isDone(), "requestor should be done") + XCTAssertTrue(acceptSession!.isDone(), "acceptor should be done") + + clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName) + + clientStateMachine.notifyContainerChange() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: self.cuttlefishContextForAcceptor, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrusted(context: self.cuttlefishContextForAcceptor) + self.verifyDatabaseMocks() + + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContextForAcceptor, sender: self.cuttlefishContext) + + let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + + initiatorDumpCallback.fulfill() + } + self.wait(for: [initiatorDumpCallback], timeout: 10) + + let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + acceptorDumpCallback.fulfill() + } + self.wait(for: [acceptorDumpCallback], timeout: 10) + XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles") + } + + func testVersion2ofPiggybackingWithAcceptorOctagonOnly() throws { + KCSetJoiningOctagonPiggybackingEnabled(true) + OctagonSetPlatformSupportsSOS(true) + self.startCKAccountStatusMock() + + self.getAcceptorInCircle() + + let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + + var clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName) + initiator1Context.startOctagonStateMachine() + + self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + // Note that in this strange situation, the join should create the CKKS TLKs + let (requestDelegate, acceptDelegate, acceptSession, requestSession) = self.setupKCJoiningSessionObjects() + var initialMessageContainingOctagonVersion: Data? + var challengeContainingEpoch: Data? + var response: Data? + var verification: Data? + var doneMessage: Data? + + XCTAssertNotNil(acceptSession, "acceptSession should not be nil") + XCTAssertNotNil(requestSession, "requestSession should not be nil") + XCTAssertNotNil(requestDelegate, "requestDelegate should not be nil") + XCTAssertNotNil(acceptDelegate, "acceptDelegate should not be nil") + + do { + initialMessageContainingOctagonVersion = try requestSession!.initialMessage() + } catch { + XCTAssertNil(error, "error retrieving initialMessageContainingOctagonVersion message") + } + + XCTAssertNotNil(initialMessageContainingOctagonVersion, "initial message should not be nil") + + do { + OctagonSetPlatformSupportsSOS(false) + challengeContainingEpoch = try acceptSession!.processMessage(initialMessageContainingOctagonVersion!) + XCTAssertNotNil(challengeContainingEpoch, "challengeContainingEpoch should not be nil") + } catch { + XCTAssertNil(error, "error retrieving challengeContainingEpoch message") + } + + do { + OctagonSetPlatformSupportsSOS(true) + response = try requestSession!.processMessage(challengeContainingEpoch!) + XCTAssertNotNil(response, "response message should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + do { + OctagonSetPlatformSupportsSOS(false) + verification = try acceptSession!.processMessage(response!) + XCTAssertNotNil(verification, "verification should not be nil") + } catch { + XCTAssertNil(error, "error retrieving verification message") + } + + do { + OctagonSetPlatformSupportsSOS(true) + doneMessage = try requestSession!.processMessage(verification!) + XCTAssertNotNil(doneMessage, "doneMessage should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + let signInCallback = self.expectation(description: "trigger sign in") + self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in + XCTAssertNil(error, "error should be nil") + signInCallback.fulfill() + } + self.wait(for: [signInCallback], timeout: 10) + + XCTAssertTrue(requestSession!.isDone(), "SecretSession done") + XCTAssertFalse(acceptSession!.isDone(), "Unexpected accept session done") + + let aesSession = requestSession!.session + + let requestCircleSession = KCJoiningRequestCircleSession(circleDelegate: requestDelegate!, + session: aesSession!, + otcontrol: self.otControl, + error: nil) + XCTAssertNotNil(requestCircleSession, "No request secret session") + + requestCircleSession.setContextIDOnJoiningConfiguration(self.initiatorPiggybackingConfig.contextID) + requestCircleSession.setControlObject(self.otControl) + + var identityMessage: Data? + do { + identityMessage = try requestCircleSession.initialMessage() + let parsedMessage = try KCJoiningMessage(der: identityMessage!) + XCTAssertNotNil(parsedMessage.firstData, "No octagon message") + XCTAssertNotNil(parsedMessage.secondData, "No sos message") + XCTAssertNotNil(identityMessage, "No identity message") } catch { XCTAssertNil(error, "error retrieving identityMessage message") } @@ -647,6 +851,7 @@ extension OctagonPairingTests { var voucherMessage: Data? do { + OctagonSetPlatformSupportsSOS(false) voucherMessage = try acceptSession!.processMessage(identityMessage!) let parsedMessage = try KCJoiningMessage(der: identityMessage!) XCTAssertNotNil(parsedMessage.firstData, "No octagon message") @@ -658,6 +863,181 @@ extension OctagonPairingTests { var nothing: Data? do { + OctagonSetPlatformSupportsSOS(true) + nothing = try requestCircleSession.processMessage(voucherMessage!) + XCTAssertNotNil(nothing, "No nothing message") + } catch { + XCTAssertNil(error, "error retrieving nothing message") + } + + assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC) + + XCTAssertTrue(requestSession!.isDone(), "requestor should be done") + XCTAssertTrue(acceptSession!.isDone(), "acceptor should be done") + + clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName) + + clientStateMachine.notifyContainerChange() + + self.assertEnters(context: self.cuttlefishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertEnters(context: self.cuttlefishContextForAcceptor, state: OctagonStateReady, within: 10 * NSEC_PER_SEC) + self.assertConsidersSelfTrusted(context: self.cuttlefishContext) + self.assertConsidersSelfTrusted(context: self.cuttlefishContextForAcceptor) + self.verifyDatabaseMocks() + + self.assertSelfTLKSharesInCloudKit(context: self.cuttlefishContext) + self.assertTLKSharesInCloudKit(receiver: self.cuttlefishContextForAcceptor, sender: self.cuttlefishContext) + + let initiatorDumpCallback = self.expectation(description: "initiatorDumpCallback callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + + initiatorDumpCallback.fulfill() + } + self.wait(for: [initiatorDumpCallback], timeout: 10) + + let acceptorDumpCallback = self.expectation(description: "acceptorDumpCallback callback occurs") + self.tphClient.dump(withContainer: self.cuttlefishContext.containerName, context: self.contextForAcceptor) { dump, _ in + XCTAssertNotNil(dump, "dump should not be nil") + let egoSelf = dump!["self"] as? [String: AnyObject] + XCTAssertNotNil(egoSelf, "egoSelf should not be nil") + let dynamicInfo = egoSelf!["dynamicInfo"] as? [String: AnyObject] + XCTAssertNotNil(dynamicInfo, "dynamicInfo should not be nil") + let included = dynamicInfo!["included"] as? [String] + XCTAssertNotNil(included, "included should not be nil") + XCTAssertEqual(included!.count, 2, "should be 2 peer ids") + acceptorDumpCallback.fulfill() + } + self.wait(for: [acceptorDumpCallback], timeout: 10) + XCTAssertEqual(self.fakeCuttlefishServer.state.bottles.count, 2, "should be 2 bottles") + } + + func testVersion2ofPiggybackingWithRequesterOctagonOnly() throws { + KCSetJoiningOctagonPiggybackingEnabled(true) + OctagonSetPlatformSupportsSOS(true) + self.startCKAccountStatusMock() + + self.getAcceptorInCircle() + + let initiator1Context = self.manager.context(forContainerName: OTCKContainerName, contextID: OTDefaultContext) + + var clientStateMachine = self.manager.clientStateMachine(forContainerName: OTCKContainerName, contextID: self.contextForAcceptor, clientName: self.initiatorName) + initiator1Context.startOctagonStateMachine() + + self.assertEnters(context: initiator1Context, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC) + + // Note that in this strange situation, the join should create the CKKS TLKs + let (requestDelegate, acceptDelegate, acceptSession, requestSession) = self.setupKCJoiningSessionObjects() + var initialMessageContainingOctagonVersion: Data? + var challengeContainingEpoch: Data? + var response: Data? + var verification: Data? + var doneMessage: Data? + + XCTAssertNotNil(acceptSession, "acceptSession should not be nil") + XCTAssertNotNil(requestSession, "requestSession should not be nil") + XCTAssertNotNil(requestDelegate, "requestDelegate should not be nil") + XCTAssertNotNil(acceptDelegate, "acceptDelegate should not be nil") + + do { + initialMessageContainingOctagonVersion = try requestSession!.initialMessage() + } catch { + XCTAssertNil(error, "error retrieving initialMessageContainingOctagonVersion message") + } + + XCTAssertNotNil(initialMessageContainingOctagonVersion, "initial message should not be nil") + + do { + OctagonSetPlatformSupportsSOS(true) + challengeContainingEpoch = try acceptSession!.processMessage(initialMessageContainingOctagonVersion!) + XCTAssertNotNil(challengeContainingEpoch, "challengeContainingEpoch should not be nil") + } catch { + XCTAssertNil(error, "error retrieving challengeContainingEpoch message") + } + + do { + OctagonSetPlatformSupportsSOS(false) + response = try requestSession!.processMessage(challengeContainingEpoch!) + XCTAssertNotNil(response, "response message should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + do { + OctagonSetPlatformSupportsSOS(true) + verification = try acceptSession!.processMessage(response!) + XCTAssertNotNil(verification, "verification should not be nil") + } catch { + XCTAssertNil(error, "error retrieving verification message") + } + + do { + OctagonSetPlatformSupportsSOS(false) + doneMessage = try requestSession!.processMessage(verification!) + XCTAssertNotNil(doneMessage, "doneMessage should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + let signInCallback = self.expectation(description: "trigger sign in") + self.otControl.sign(in: "348576349857", container: OTCKContainerName, context: OTDefaultContext) { error in + XCTAssertNil(error, "error should be nil") + signInCallback.fulfill() + } + self.wait(for: [signInCallback], timeout: 10) + + XCTAssertTrue(requestSession!.isDone(), "SecretSession done") + XCTAssertFalse(acceptSession!.isDone(), "Unexpected accept session done") + + let aesSession = requestSession!.session + + let requestCircleSession = KCJoiningRequestCircleSession(circleDelegate: requestDelegate!, + session: aesSession!, + otcontrol: self.otControl, + error: nil) + XCTAssertNotNil(requestCircleSession, "No request secret session") + + requestCircleSession.setContextIDOnJoiningConfiguration(self.initiatorPiggybackingConfig.contextID) + requestCircleSession.setControlObject(self.otControl) + + var identityMessage: Data? + do { + OctagonSetPlatformSupportsSOS(false) + identityMessage = try requestCircleSession.initialMessage() + let parsedMessage = try KCJoiningMessage(der: identityMessage!) + XCTAssertNotNil(parsedMessage.firstData, "No octagon message") + XCTAssertNil(parsedMessage.secondData, "sos message is populated") + XCTAssertNotNil(identityMessage, "No identity message") + } catch { + XCTAssertNil(error, "error retrieving identityMessage message") + } + + // Double-check that there's an Octagon message in the packet + let initiatorIdentityMessage = try self.unpackPiggybackingInitialMessage(identityMessage: identityMessage!, session: acceptSession!.accessSession()) + XCTAssertTrue(initiatorIdentityMessage.hasPrepare, "Pairing message should contain prepared information") + + var voucherMessage: Data? + do { + OctagonSetPlatformSupportsSOS(true) + voucherMessage = try acceptSession!.processMessage(identityMessage!) + let parsedMessage = try KCJoiningMessage(der: identityMessage!) + XCTAssertNotNil(parsedMessage.firstData, "No octagon message") + XCTAssertNil(parsedMessage.secondData, "sos message is populated") + XCTAssertNotNil(voucherMessage, "No voucherMessage message") + } catch { + XCTAssertNil(error, "error retrieving voucherMessage message") + } + + var nothing: Data? + do { + OctagonSetPlatformSupportsSOS(false) nothing = try requestCircleSession.processMessage(voucherMessage!) XCTAssertNotNil(nothing, "No nothing message") } catch { @@ -799,7 +1179,6 @@ extension OctagonPairingTests { do { identityMessage = try requestCircleSession.initialMessage() XCTAssertNotNil(identityMessage, "No identity message") - } catch { XCTAssertNil(error, "error retrieving identityMessage message") } @@ -810,7 +1189,6 @@ extension OctagonPairingTests { XCTAssertNotNil(voucherMessage, "No voucherMessage message") } catch { XCTAssertNil(error, "error retrieving voucherMessage message") - } var nothing: Data? @@ -819,13 +1197,125 @@ extension OctagonPairingTests { XCTAssertNotNil(nothing, "No nothing message") } catch { XCTAssertNil(error, "error retrieving nothing message") - } XCTAssertTrue(requestSession!.isDone(), "requestor should be done") XCTAssertTrue(acceptSession!.isDone(), "acceptor should be done") } + func testPiggybackingForTLKRequest() throws { + KCSetJoiningOctagonPiggybackingEnabled(true) + OctagonSetIsEnabled(true) + self.startCKAccountStatusMock() + + self.assertResetAndBecomeTrustedInDefaultContext() + + let (requestDelegate, acceptDelegate, acceptSession, requestSession) = self.setupKCJoiningSessionObjects() + var initialMessageContainingOctagonVersion: Data? + var challengeContainingEpoch: Data? + var response: Data? + var verification: Data? + var doneMessage: Data? + + XCTAssertNotNil(acceptSession, "acceptSession should not be nil") + XCTAssertNotNil(requestSession, "requestSession should not be nil") + XCTAssertNotNil(requestDelegate, "requestDelegate should not be nil") + XCTAssertNotNil(acceptDelegate, "acceptDelegate should not be nil") + + do { + initialMessageContainingOctagonVersion = try requestSession!.initialMessage() + } catch { + XCTAssertNil(error, "error retrieving initialMessageContainingOctagonVersion message") + } + + XCTAssertNotNil(initialMessageContainingOctagonVersion, "initial message should not be nil") + + do { + challengeContainingEpoch = try acceptSession!.processMessage(initialMessageContainingOctagonVersion!) + XCTAssertNotNil(challengeContainingEpoch, "challengeContainingEpoch should not be nil") + } catch { + XCTAssertNil(error, "error retrieving challengeContainingEpoch message") + } + + do { + response = try requestSession!.processMessage(challengeContainingEpoch!) + XCTAssertNotNil(response, "response message should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + do { + verification = try acceptSession!.processMessage(response!) + XCTAssertNotNil(verification, "verification should not be nil") + } catch { + XCTAssertNil(error, "error retrieving verification message") + } + + do { + doneMessage = try requestSession!.processMessage(verification!) + XCTAssertNotNil(doneMessage, "doneMessage should not be nil") + } catch { + XCTAssertNil(error, "error retrieving response message") + } + + XCTAssertTrue(requestSession!.isDone(), "SecretSession should be done") + XCTAssertFalse(acceptSession!.isDone(), "Accept session should not be done") + + let aesSession = requestSession!.session + + let requestCircleSession = KCJoiningRequestCircleSession(circleDelegate: requestDelegate!, + session: aesSession!, + otcontrol: self.otControl, + error: nil) + XCTAssertNotNil(requestCircleSession, "Should have a request secret session") + + var tlkResponseMessage: Data? + do { + let tlkRequestMessage = try KCJoiningMessage(type: kTLKRequest, data: Data()) + tlkResponseMessage = try acceptSession!.processMessage(tlkRequestMessage.der) + XCTAssertNotNil(tlkResponseMessage, "Should have a TLK response") + } catch { + XCTAssertNil(error, "error retrieving voucherMessage message") + } + + XCTAssertTrue(acceptSession!.isDone(), "Accept session should be done after responding to a TLK request") + // Note that we no longer care about the joiningSession, because this software stack doesn't receive tlkrequest messages. + + let tlkResponseMessageCiphertext = try KCJoiningMessage(der: tlkResponseMessage!) + let tlkResponseMessageDER = try requestCircleSession.accessSession().decryptAndVerify(tlkResponseMessageCiphertext.firstData) + + let piggybackedPlist = TestsObjectiveC.copyPiggybackingInitialSyncData(tlkResponseMessageDER) + XCTAssertNotNil(piggybackedPlist, "Should have something piggybacked across the channel") + + let tlks = piggybackedPlist?["tlks"] as? [Any] + XCTAssertNotNil(tlks, "Should have some tlk contents") + #if !os(tvOS) + // TVs don't have the Passwords view, and so won't send it via piggybacking + XCTAssertEqual(tlks?.count, 1, "Should have one tlk transferred") + + if let tlk = tlks?.first as? [AnyHashable: Any] { + let view = tlk["srvr"] as? String + XCTAssertEqual(view, "Passwords", "Should have the TLK for the passwords view") + + let uuid = tlk["acct"] as? String + if let keyset = self.keys?[self.passwordsZoneID!] as? ZoneKeys { + XCTAssertEqual(uuid, keyset.currentTLKPointer?.currentKeyUUID, "Piggybacked TLK should match zone's TLK") + } else { + XCTFail("CKKS should have made keys for the passwords view") + } + print(tlk) + } else { + XCTFail("Unable to extract TLK as plist") + } + #else + XCTAssertEqual(tlks?.count, 0, "Should have zero tlks transferred (from a TV)") + #endif + + // The plist might also have some idents. Check that there aren't any + let idents = piggybackedPlist?["idents"] as? [Any] + XCTAssertNotNil(idents, "Should have some idents array") + XCTAssertEqual(idents?.count, 0, "Should have no idents contents") + } } #endif diff --git a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProxMultiClients.swift b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProxMultiClients.swift index 142b3410..53a656af 100644 --- a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProxMultiClients.swift +++ b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProxMultiClients.swift @@ -1,9 +1,7 @@ #if OCTAGON extension OctagonPairingTests { - func test2ClientsBothOctagonAndSOS() { - OctagonSetPlatformSupportsSOS(true) self.startCKAccountStatusMock() @@ -578,7 +576,6 @@ extension OctagonPairingTests { } func test2ClientsSOSOnly() { - OctagonSetPlatformSupportsSOS(true) OctagonSetIsEnabled(false) self.startCKAccountStatusMock() diff --git a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProximitySetup.swift b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProximitySetup.swift index 47786d25..b2910fa8 100644 --- a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProximitySetup.swift +++ b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests+ProximitySetup.swift @@ -1,7 +1,6 @@ #if OCTAGON extension OctagonPairingTests { - func assertSOSSuccess() { XCTAssertNotNil(self.fcInitiator?.accountPrivateKey, "no accountPrivateKey in fcInitiator") XCTAssertNotNil(self.fcAcceptor?.accountPrivateKey, "no accountPrivateKey in fcAcceptor") @@ -1398,7 +1397,6 @@ extension OctagonPairingTests { self.assertConsidersSelfTrusted(context: initiatorContext) */ } - } #endif diff --git a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests.swift b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests.swift index 5eda3686..0345fac2 100644 --- a/keychain/ot/tests/octagon/Pairing/OctagonPairingTests.swift +++ b/keychain/ot/tests/octagon/Pairing/OctagonPairingTests.swift @@ -1,7 +1,6 @@ #if OCTAGON func GenerateFullECKey(keySize: Int) -> (SecKey) { - let keyPair = _SFECKeyPair.init(randomKeyPairWith: _SFECKeySpecifier.init(curve: SFEllipticCurve.nistp384))! var keyAttributes: [String: String] = [:] @@ -38,7 +37,7 @@ class KCJoiningRequestTestDelegate: NSObject, KCJoiningRequestSecretDelegate, KC var gestalt: [String: String] = [:] gestalt[kPIUserDefinedDeviceNameKey as String] = "Fakey" - let newPeerInfo = SOSPeerInfoCreate(nil, gestalt as CFDictionary, nil, signingKey, octagonSigningKey, octagonEncryptionKey, nil) + let newPeerInfo = SOSPeerInfoCreate(nil, gestalt as CFDictionary, nil, signingKey, octagonSigningKey, octagonEncryptionKey, true, nil) self.peerInfo = newPeerInfo self.sharedSecret = secret @@ -78,7 +77,6 @@ class KCJoiningRequestTestDelegate: NSObject, KCJoiningRequestSecretDelegate, KC } class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJoiningAcceptCircleDelegate { - var secrets: [String] = [] var currentSecret: Int = 0 var retriesLeft: Int = 0 @@ -102,7 +100,6 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo } init(withSecrets secrets: [String], retries: Int, code: String) { - self.secrets = secrets self.currentSecret = 0 self.retriesPerSecret = retries @@ -159,7 +156,10 @@ class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJo } func circleGetInitialSyncViews(_ flags: SOSInitialSyncFlags, error: NSErrorPointer) -> Data { - return Data() + + // Skip the XPC and just call the server method + let possibleData = try? TestsObjectiveC.copyInitialSyncData(flags) + return possibleData ?? Data() } } @@ -253,7 +253,7 @@ extension OctagonTestsBase { let acceptSession = try KCJoiningAcceptSession(secretDelegate: acceptDelegate as KCJoiningAcceptSecretDelegate, circleDelegate: acceptDelegate as KCJoiningAcceptCircleDelegate, dsid: dsid, - rng: ccDRBGGetRngState()) + rng: ccrng(nil)) requestSession.setControlObject(self.otControl) acceptSession.setControlObject(self.otControl) @@ -360,7 +360,6 @@ extension OctagonTestsBase { @objcMembers class OctagonPairingTests: OctagonTestsBase { - var sosAdapterForAcceptor: CKKSMockSOSPresentAdapter! var cuttlefishContextForAcceptor: OTCuttlefishContext! var contextForAcceptor = "defaultContextForAcceptor" @@ -377,6 +376,27 @@ class OctagonPairingTests: OctagonTestsBase { var fcAcceptor: FCPairingFakeSOSControl! override func setUp() { + // We want the Passwords view to exist, so that we can check the piggybacking TLK channel + if self.mockDeviceInfo == nil { + let actualDeviceAdapter = OTDeviceInformationActualAdapter() + self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: actualDeviceAdapter.modelID(), + deviceName: actualDeviceAdapter.deviceName(), + serialNumber: NSUUID().uuidString, + osVersion: actualDeviceAdapter.osVersion()) + } + + if self.mockDeviceInfo.mockModelID.contains("AppleTV") { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + ]) + } else { + self.intendedCKKSZones = Set([ + CKRecordZone.ID(zoneName: "LimitedPeersAllowed"), + CKRecordZone.ID(zoneName: "Manatee"), + CKRecordZone.ID(zoneName: "Passwords"), + ]) + } + super.setUp() // The acceptor should have its own SOS state @@ -386,12 +406,12 @@ class OctagonPairingTests: OctagonTestsBase { self.sosAdapterForAcceptor.circleStatus = SOSCCStatus(kSOSCCInCircle) self.cuttlefishContextForAcceptor = self.manager.context(forContainerName: OTCKContainerName, - contextID: self.contextForAcceptor, - sosAdapter: self.sosAdapterForAcceptor, - authKitAdapter: self.mockAuthKit3, - lockStateTracker: self.lockStateTracker, - accountStateTracker: self.accountStateTracker, - deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iPhone9,1", deviceName: "test-SOS-iphone", serialNumber: "456", osVersion: "iOS (fake version)")) + contextID: self.contextForAcceptor, + sosAdapter: self.sosAdapterForAcceptor, + authKitAdapter: self.mockAuthKit3, + lockStateTracker: self.lockStateTracker, + accountStateTracker: self.accountStateTracker, + deviceInformationAdapter: OTMockDeviceInfoAdapter(modelID: "iPhone9,1", deviceName: "test-SOS-iphone", serialNumber: "456", osVersion: "iOS (fake version)")) self.acceptorPiggybackingConfig = OTJoiningConfiguration(protocolType: OTProtocolPiggybacking, uniqueDeviceID: "acceptor", @@ -444,7 +464,6 @@ class OctagonPairingTests: OctagonTestsBase { } func setupPairingEndpoints(withPairNumber pairNumber: String, initiatorContextID: String, acceptorContextID: String, initiatorUniqueID: String, acceptorUniqueID: String) -> (KCPairingChannel, KCPairingChannel) { - let (acceptorClique, initiatorClique) = self.setupOTCliquePair(withNumber: pairNumber) XCTAssertNotNil(acceptorClique, "acceptorClique should not be nil") XCTAssertNotNil(initiatorClique, "initiatorClique should not be nil") @@ -505,16 +524,11 @@ class OctagonPairingTests: OctagonTestsBase { } func setupOTCliquePair(withNumber count: String) -> (OTClique?, OTClique?) { - let secondAcceptorData = OTConfigurationContext() secondAcceptorData.context = "secondAcceptor" secondAcceptorData.dsid = "a-"+count secondAcceptorData.altDSID = "alt-a-"+count - let acceptorAnalytics = SFSignInAnalytics(signInUUID: "uuid", category: "com.apple.cdp", eventName: "signed in") - XCTAssertNotNil(acceptorAnalytics, "acceptorAnalytics should not be nil") - secondAcceptorData.analytics = acceptorAnalytics - let acceptor = OTClique(contextData: secondAcceptorData) XCTAssertNotNil(acceptor, "Clique should not be nil") acceptor.setPairingDefault(true) @@ -524,9 +538,6 @@ class OctagonPairingTests: OctagonTestsBase { secondInitiatorData.dsid = "i-"+count secondInitiatorData.altDSID = "alt-i-"+count - let initiatorAnalytics = SFSignInAnalytics(signInUUID: "uuid", category: "com.apple.cdp", eventName: "signed in") - XCTAssertNotNil(initiatorAnalytics, "initiatorAnalytics should not be nil") - secondInitiatorData.analytics = initiatorAnalytics let initiator = OTClique(contextData: secondInitiatorData) XCTAssertNotNil(initiator, "Clique should not be nil") initiator.setPairingDefault(true) diff --git a/keychain/ot/tests/octagon/TestsObjcTranslation.h b/keychain/ot/tests/octagon/TestsObjcTranslation.h index 413ad8e3..9a2901c9 100644 --- a/keychain/ot/tests/octagon/TestsObjcTranslation.h +++ b/keychain/ot/tests/octagon/TestsObjcTranslation.h @@ -5,6 +5,8 @@ #import #import #import +#include +#include "keychain/ckks/CKKSPeer.h" NS_ASSUME_NONNULL_BEGIN @@ -23,6 +25,12 @@ NS_ASSUME_NONNULL_BEGIN + (BOOL)saveCoruptDataToKeychainForContainer:(NSString*)containerName contextID:(NSString*)contextID error:(NSError**)error; + ++ (NSData* _Nullable)copyInitialSyncData:(SOSInitialSyncFlags)flags error:(NSError**)error; + ++ (NSDictionary* _Nullable)copyPiggybackingInitialSyncData:(NSData*)data; + ++ (BOOL)testSecKey:(CKKSSelves*)octagonSelf error:(NSError**)error; @end NS_ASSUME_NONNULL_END diff --git a/keychain/ot/tests/octagon/TestsObjcTranslation.m b/keychain/ot/tests/octagon/TestsObjcTranslation.m index 51021194..d89c6741 100644 --- a/keychain/ot/tests/octagon/TestsObjcTranslation.m +++ b/keychain/ot/tests/octagon/TestsObjcTranslation.m @@ -2,10 +2,12 @@ #import #import -#import #import "keychain/ot/OTCuttlefishContext.h" #import +#import #import "keychain/categories/NSError+UsefulConstructors.h" +#import "keychain/securityd/SOSCloudCircleServer.h" +#import "keychain/SecureObjectSync/SOSAccountPriv.h" static const uint8_t signingKey_384[] = { 0x04, 0xe4, 0x1b, 0x3e, 0x88, 0x81, 0x9f, 0x3b, 0x80, 0xd0, 0x28, 0x1c, @@ -106,4 +108,115 @@ static const uint8_t signingKey_384[] = { } } ++ (NSData* _Nullable)copyInitialSyncData:(SOSInitialSyncFlags)flags error:(NSError**)error +{ + CFErrorRef cferror = NULL; + NSData* result = CFBridgingRelease(SOSCCCopyInitialSyncData_Server(flags, &cferror)); + + if(cferror && error) { + *error = CFBridgingRelease(cferror); + } + + return result; +} + ++ (NSDictionary* _Nullable)copyPiggybackingInitialSyncData:(NSData*)data +{ + const uint8_t* der = [data bytes]; + const uint8_t *der_end = der + [data length]; + + NSDictionary* results = SOSPiggyCopyInitialSyncData(&der, der_end); + return results; +} + ++ (BOOL)testSecKey:(CKKSSelves*)octagonSelf error:(NSError**)error +{ + id currentSelfPeer = octagonSelf.currentSelf; + + NSData* signingFullKey = currentSelfPeer.signingKey.keyData; + + SecKeyRef octagonSigningPubSecKey = CFRetainSafe(currentSelfPeer.publicSigningKey.secKey); + SecKeyRef octagonEncryptionPubSecKey = CFRetainSafe(currentSelfPeer.publicEncryptionKey.secKey); + + NSError* localerror = nil; + + bool savedSigningKey = SOSCCSaveOctagonKeysToKeychain(@"Octagon Peer Signing ID for Test-ak", + signingFullKey, + 384, + octagonSigningPubSecKey, + &localerror); + if(!savedSigningKey) { + if(error) { + *error = localerror; + } + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + return NO; + } + + // Okay, can we load this key pair? + + // Try the SPI route first + CFErrorRef cferror = NULL; + SecKeyRef signingPrivateKey = SecKeyCopyMatchingPrivateKey(octagonSigningPubSecKey, &cferror); + if(!signingPrivateKey) { + if(error) { + *error = CFBridgingRelease(cferror); + } else { + CFReleaseNull(cferror); + } + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + return NO; + } + + // and can you get the persistent ref from that private key? + CFDataRef pref = NULL; + OSStatus status = SecKeyCopyPersistentRef(signingPrivateKey, &pref); + if(status != errSecSuccess) { + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + description:@"Failed to copy persistent ref"]; + } + CFReleaseNull(pref); + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + return NO; + } + + + SFECKeyPair *signingFullKeyPair = [[SFECKeyPair alloc] initWithData:signingFullKey + specifier:[[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384] + error:&localerror]; + if(!signingFullKey) { + if(error) { + *error = localerror; + } + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + return NO; + } + + CFDataRef prefFromSF = NULL; + OSStatus statusFromSF = SecKeyCopyPersistentRef(signingFullKeyPair.secKey, &prefFromSF); + if(statusFromSF != errSecSuccess) { + if(error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain + code:statusFromSF + description:@"Failed to copy persistent ref"]; + } + CFReleaseNull(pref); + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + return NO; + } + + CFReleaseNull(pref); + CFReleaseNull(octagonSigningPubSecKey); + CFReleaseNull(octagonEncryptionPubSecKey); + + return YES; +} + @end diff --git a/keychain/otctl/OTControlCLI.h b/keychain/otctl/OTControlCLI.h index 38293335..9e7cf6a8 100644 --- a/keychain/otctl/OTControlCLI.h +++ b/keychain/otctl/OTControlCLI.h @@ -11,37 +11,55 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithOTControl:(OTControl*)control; -- (long)startOctagonStateMachine:(NSString*)container context:(NSString*)contextID; +- (long)startOctagonStateMachine:(NSString *)container context:(NSString *)contextID; -- (long)signIn:(NSString*)altDSID container:(NSString* _Nullable)container context:(NSString*)contextID; +- (long)signIn:(NSString *)altDSID container:(NSString * _Nullable)container context:(NSString *)contextID; -- (long)signOut:(NSString* _Nullable)container context:(NSString*)contextID; +- (long)signOut:(NSString * _Nullable)container context:(NSString *)contextID; -- (long)depart:(NSString* _Nullable)container context:(NSString*)contextID; +- (long)depart:(NSString * _Nullable)container context:(NSString *)contextID; -- (long)resetOctagon:(NSString*)container context:(NSString*)contextID altDSID:(NSString*)altDSID; +- (long)resetOctagon:(NSString *)container context:(NSString *)contextID altDSID:(NSString *)altDSID; -- (long)resetProtectedData:(NSString*)container context:(NSString*)contextID altDSID:(NSString*)altDSID appleID:(NSString*)appleID dsid:(NSString*)dsid; +- (long)resetProtectedData:(NSString *)container context:(NSString *)contextID altDSID:(NSString *)altDSID appleID:(NSString *)appleID dsid:(NSString *)dsid; -- (long)status:(NSString* _Nullable)container context:(NSString*)contextID json:(bool)json; +- (long)status:(NSString * _Nullable)container context:(NSString *)contextID json:(bool)json; -- (long)recoverUsingBottleID:(NSString*)bottleID - entropy:(NSData*)entropy - altDSID:(NSString*)altDSID - containerName:(NSString*)containerName - context:(NSString*)context - control:(OTControl*)control; +- (long)recoverUsingBottleID:(NSString *)bottleID + entropy:(NSData *)entropy + altDSID:(NSString *)altDSID + containerName:(NSString *)containerName + context:(NSString *)context + control:(OTControl *)control; -- (long)fetchAllBottles:(NSString*)altDSID - containerName:(NSString*)containerName - context:(NSString*)context - control:(OTControl*)control; +- (long)fetchAllBottles:(NSString *)altDSID + containerName:(NSString *)containerName + context:(NSString *)context + control:(OTControl *)control; -- (long)healthCheck:(NSString* _Nullable)container context:(NSString*)contextID skipRateLimitingCheck:(BOOL)skipRateLimitingCheck; -- (long)refetchCKKSPolicy:(NSString*)container context:(NSString*)contextID; +- (long)fetchEscrowRecords:(NSString * _Nullable)container context:(NSString *)contextID; +- (long)fetchAllEscrowRecords:(NSString* _Nullable)container context:(NSString*)contextID; + +- (long)healthCheck:(NSString * _Nullable)container context:(NSString *)contextID skipRateLimitingCheck:(BOOL)skipRateLimitingCheck; +- (long)refetchCKKSPolicy:(NSString *)container context:(NSString *)contextID; - (long)tapToRadar:(NSString *)action description:(NSString *)description radar:(NSString *)radar; +- (long)performEscrowRecovery:(NSString * _Nullable)container + context:(NSString *)contextID + recordID:(NSString *)recordID + appleID:(NSString *)appleID + secret:(NSString *)secret; + +- (long)performSilentEscrowRecovery:(NSString * _Nullable)container context:(NSString *)contextID appleID:(NSString *)appleID secret:(NSString *)secret; + +- (long)setUserControllableViewsSyncStatus:(NSString * _Nullable)containerName + contextID:(NSString *)contextID + enabled:(BOOL)enabled; + +- (long)fetchUserControllableViewsSyncStatus:(NSString * _Nullable)containerName + contextID:(NSString *)contextID; + @end NS_ASSUME_NONNULL_END diff --git a/keychain/otctl/OTControlCLI.m b/keychain/otctl/OTControlCLI.m index 5637dec9..a9f56ff2 100644 --- a/keychain/otctl/OTControlCLI.m +++ b/keychain/otctl/OTControlCLI.m @@ -14,14 +14,16 @@ #import "keychain/ot/OT.h" #import "keychain/ot/OTConstants.h" #import "keychain/ot/OTControl.h" + #import "keychain/otctl/OTControlCLI.h" +#import "keychain/OctagonTrust/OctagonTrust.h" #import #import #import -static NSString* fetch_pet(NSString* appleID, NSString* dsid) +static NSString * fetch_pet(NSString * appleID, NSString * dsid) { if(!appleID && !dsid) { NSLog(@"Must provide either an AppleID or a DSID to fetch a PET"); @@ -34,7 +36,7 @@ static NSString* fetch_pet(NSString* appleID, NSString* dsid) authContext.authenticationType = AKAppleIDAuthenticationTypeSilent; authContext.isUsernameEditable = NO; - __block NSString* pet = nil; + __block NSString * pet = nil; dispatch_semaphore_t s = dispatch_semaphore_create(0); @@ -130,7 +132,7 @@ static void print_json(NSDictionary* dict) return self; } -- (long)startOctagonStateMachine:(NSString*)container context:(NSString*)contextID { +- (long)startOctagonStateMachine:(NSString *)container context:(NSString *)contextID { #if OCTAGON __block long ret = -1; @@ -152,7 +154,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)signIn:(NSString*)altDSID container:(NSString* _Nullable)container context:(NSString*)contextID { +- (long)signIn:(NSString *)altDSID container:(NSString * _Nullable)container context:(NSString *)contextID { #if OCTAGON __block long ret = -1; @@ -175,7 +177,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)signOut:(NSString* _Nullable)container context:(NSString*)contextID { +- (long)signOut:(NSString * _Nullable)container context:(NSString *)contextID { #if OCTAGON __block long ret = -1; [self.control signOut:container @@ -195,7 +197,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)depart:(NSString* _Nullable)container context:(NSString*)contextID { +- (long)depart:(NSString * _Nullable)container context:(NSString *)contextID { #if OCTAGON __block long ret = -1; @@ -216,7 +218,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)resetOctagon:(NSString*)container context:(NSString*)contextID altDSID:(NSString*)altDSID { +- (long)resetOctagon:(NSString *)container context:(NSString *)contextID altDSID:(NSString *)altDSID { #if OCTAGON __block long ret = -1; @@ -241,7 +243,7 @@ static void print_json(NSDictionary* dict) } -- (long)resetProtectedData:(NSString*)container context:(NSString*)contextID altDSID:(NSString*)altDSID appleID:(NSString*)appleID dsid:(NSString*)dsid +- (long)resetProtectedData:(NSString *)container context:(NSString *)contextID altDSID:(NSString *)altDSID appleID:(NSString *)appleID dsid:(NSString *)dsid { #if OCTAGON __block long ret = -1; @@ -252,6 +254,7 @@ static void print_json(NSDictionary* dict) data.authenticationAppleID = appleID; data.altDSID = altDSID; data.context = contextID; + data.containerName = container; OTClique* clique = [OTClique resetProtectedData:data error:&error]; if(clique != nil && error == nil) { @@ -264,13 +267,13 @@ static void print_json(NSDictionary* dict) #endif } -- (void)printPeer:(NSDictionary*)peerInformation prefix:(NSString* _Nullable)prefix { - NSString* peerID = peerInformation[@"peerID"]; - NSString* model = peerInformation[@"permanentInfo"][@"model_id"]; +- (void)printPeer:(NSDictionary*)peerInformation prefix:(NSString * _Nullable)prefix { + NSString * peerID = peerInformation[@"peerID"]; + NSString * model = peerInformation[@"permanentInfo"][@"model_id"]; NSNumber* epoch = peerInformation[@"permanentInfo"][@"epoch"]; - NSString* deviceName = peerInformation[@"stableInfo"][@"device_name"]; - NSString* serialNumber = peerInformation[@"stableInfo"][@"serial_number"]; - NSString* os = peerInformation[@"stableInfo"][@"os_version"]; + NSString * deviceName = peerInformation[@"stableInfo"][@"device_name"]; + NSString * serialNumber = peerInformation[@"stableInfo"][@"serial_number"]; + NSString * os = peerInformation[@"stableInfo"][@"os_version"]; printf("%s%s hw:'%s' name:'%s' serial: '%s' os:'%s' epoch:%d\n", (prefix ? [prefix UTF8String] : ""), @@ -282,10 +285,10 @@ static void print_json(NSDictionary* dict) [epoch intValue]); } -- (void)printPeers:(NSArray*)peerIDs - egoPeerID:(NSString* _Nullable)egoPeerID - informationOnPeers:(NSDictionary*)informationOnPeers { - for(NSString* peerID in peerIDs) { +- (void)printPeers:(NSArray*)peerIDs + egoPeerID:(NSString * _Nullable)egoPeerID + informationOnPeers:(NSDictionary*)informationOnPeers { + for(NSString * peerID in peerIDs) { NSDictionary* peerInformation = informationOnPeers[peerID]; if(!peerInformation) { @@ -301,7 +304,156 @@ static void print_json(NSDictionary* dict) } } -- (long)status:(NSString* _Nullable)container context:(NSString*)contextID json:(bool)json { +- (long)fetchEscrowRecords:(NSString * _Nullable)container context:(NSString *)contextID { +#if OCTAGON + __block long ret = -1; + + NSError* error = nil; + OTConfigurationContext *data = [[OTConfigurationContext alloc] init]; + data.context = contextID; + data.containerName = container; + + NSArray* records = [OTClique fetchEscrowRecords:data error:&error]; + if(records != nil && error == nil) { + printf("Successfully fetched %lu records.\n", (unsigned long)records.count); + ret = 0; + for(OTEscrowRecord* record in records){ + CFErrorRef* localError = NULL; + SOSPeerInfoRef peer = SOSPeerInfoCreateFromData(kCFAllocatorDefault, localError, (__bridge CFDataRef)record.escrowInformationMetadata.peerInfo); + CFStringRef peerID = SOSPeerInfoGetPeerID(peer); + printf("fetched record id: %s\n", [(__bridge NSString *)peerID UTF8String]); + } + } + return ret; +#else + printf("Unimplemented.\n"); + return -1; +#endif +} + +- (long)fetchAllEscrowRecords:(NSString* _Nullable)container context:(NSString*)contextID { +#if OCTAGON + __block long ret = -1; + + NSError* error = nil; + OTConfigurationContext *data = [[OTConfigurationContext alloc] init]; + data.context = contextID; + data.containerName = container; + + NSArray* records = [OTClique fetchAllEscrowRecords:data error:&error]; + if(records != nil && error == nil) { + printf("Successfully fetched %lu records.\n", (unsigned long)records.count); + ret = 0; + for(OTEscrowRecord* record in records){ + CFErrorRef* localError = NULL; + SOSPeerInfoRef peer = SOSPeerInfoCreateFromData(kCFAllocatorDefault, localError, (__bridge CFDataRef)record.escrowInformationMetadata.peerInfo); + CFStringRef peerID = SOSPeerInfoGetPeerID(peer); + printf("fetched record id: %s\n", [(__bridge NSString*)peerID UTF8String]); + } + } + return ret; +#else + printf("Unimplemented.\n"); + return -1; +#endif +} + +- (long)performEscrowRecovery:(NSString * _Nullable)container context:(NSString *)contextID recordID:(NSString *)recordID appleID:(NSString *)appleID secret:(NSString *)secret +{ +#if OCTAGON + __block long ret = -1; + + NSError* error = nil; + OTConfigurationContext *data = [[OTConfigurationContext alloc] init]; + data.context = contextID; + + OTICDPRecordContext* cdpContext = [[OTICDPRecordContext alloc] init]; + cdpContext.cdpInfo = [[OTCDPRecoveryInformation alloc] init]; + cdpContext.cdpInfo.recoverySecret = secret; + cdpContext.cdpInfo.containsIcdpData = true; + cdpContext.cdpInfo.usesMultipleIcsc = true; + cdpContext.authInfo = [[OTEscrowAuthenticationInformation alloc] init]; + cdpContext.authInfo.authenticationAppleid = appleID; + cdpContext.authInfo.authenticationPassword = fetch_pet(appleID, nil); + + NSArray* escrowRecords = [OTClique fetchEscrowRecords:data error:&error]; + if (escrowRecords == nil || error != nil) { + printf("Failed to fetch escrow records.\n"); + ret = -1; + } + OTEscrowRecord* record = nil; + + for (OTEscrowRecord* r in escrowRecords) { + CFErrorRef* localError = NULL; + SOSPeerInfoRef peer = SOSPeerInfoCreateFromData(kCFAllocatorDefault, localError, (__bridge CFDataRef)r.escrowInformationMetadata.peerInfo); + CFStringRef peerID = SOSPeerInfoGetPeerID(peer); + + if ([(__bridge NSString *)peerID isEqualToString:recordID]) { + record = r; + break; + } + } + if (record == nil){ + printf("Failed to find escrow record to restore. \n"); + return -1; + } + + OTClique* clique = [OTClique performEscrowRecovery:data cdpContext:cdpContext escrowRecord:record error:&error]; + if (clique != nil && error == nil) { + printf("Successfully performed escrow recovery.\n"); + ret = 0; + } else { + fprintf(stderr, "Escrow recovery failed: %s\n", error.description.UTF8String); + } + return ret; +#else + printf("Unimplemented.\n"); + return -1; +#endif +} + +- (long)performSilentEscrowRecovery:(NSString * _Nullable)container context:(NSString *)contextID appleID:(NSString *)appleID secret:(NSString *)secret { +#if OCTAGON + __block long ret = -1; + + NSError* error = nil; + OTConfigurationContext *data = [[OTConfigurationContext alloc] init]; + data.context = contextID; + + OTICDPRecordContext* cdpContext = [[OTICDPRecordContext alloc] init]; + cdpContext.cdpInfo = [[OTCDPRecoveryInformation alloc] init]; + + cdpContext.cdpInfo.recoverySecret = secret; + cdpContext.cdpInfo.containsIcdpData = true; + cdpContext.cdpInfo.silentRecoveryAttempt = true; + cdpContext.cdpInfo.usesMultipleIcsc = true; + + cdpContext.authInfo = [[OTEscrowAuthenticationInformation alloc] init]; + cdpContext.authInfo.authenticationAppleid = appleID; + cdpContext.authInfo.authenticationPassword = fetch_pet(appleID, nil); + + + NSArray* records = [OTClique fetchEscrowRecords:data error:&error]; + if (records == nil || error != nil) { + printf("Failed to fetch escrow records.\n"); + ret = -1; + } + OTClique* clique = [OTClique performSilentEscrowRecovery:data cdpContext:cdpContext allRecords:records error:&error]; + if (clique != nil && error == nil) { + printf("Successfully performed escrow recovery.\n"); + ret = 0; + } else { + fprintf(stderr, "Escrow recovery failed: %s\n", error.description.UTF8String); + } + return ret; +#else + printf("Unimplemented.\n"); + return -1; +#endif +} + + +- (long)status:(NSString * _Nullable)container context:(NSString *)contextID json:(bool)json { #if OCTAGON __block long ret = 0; @@ -330,10 +482,10 @@ static void print_json(NSDictionary* dict) NSDictionary* contextDump = result[@"contextDump"]; // Make it easy to find peer information - NSMutableDictionary* peers = [NSMutableDictionary dictionary]; - NSMutableArray* allPeerIDs = [NSMutableArray array]; + NSMutableDictionary* peers = [NSMutableDictionary dictionary]; + NSMutableArray* allPeerIDs = [NSMutableArray array]; for(NSDictionary* peerInformation in contextDump[@"peers"]) { - NSString* peerID = peerInformation[@"peerID"]; + NSString * peerID = peerInformation[@"peerID"]; if(peerID) { peers[peerID] = peerInformation; [allPeerIDs addObject:peerID]; @@ -341,7 +493,7 @@ static void print_json(NSDictionary* dict) } NSDictionary* egoInformation = contextDump[@"self"]; - NSString* egoPeerID = egoInformation[@"peerID"]; + NSString * egoPeerID = egoInformation[@"peerID"]; NSDictionary* egoDynamicInfo = egoInformation[@"dynamicInfo"]; if(egoPeerID) { @@ -352,7 +504,7 @@ static void print_json(NSDictionary* dict) // The self peer is technically a peer, so, shove it on in there peers[egoPeerID] = egoInformation; - NSArray* includedPeers = egoDynamicInfo[@"included"]; + NSArray* includedPeers = egoDynamicInfo[@"included"]; printf("Trusted peers (by me):\n"); if(includedPeers && includedPeers.count > 0) { [self printPeers:includedPeers egoPeerID:egoPeerID informationOnPeers:peers]; @@ -362,7 +514,7 @@ static void print_json(NSDictionary* dict) } printf("\n"); - NSArray* excludedPeers = egoDynamicInfo[@"excluded"]; + NSArray* excludedPeers = egoDynamicInfo[@"excluded"]; printf("Excluded peers (by me):\n"); if(excludedPeers && excludedPeers.count > 0) { [self printPeers:excludedPeers egoPeerID:egoPeerID informationOnPeers:peers]; @@ -403,11 +555,11 @@ static void print_json(NSDictionary* dict) #endif } -- (long)recoverUsingBottleID:(NSString*)bottleID +- (long)recoverUsingBottleID:(NSString *)bottleID entropy:(NSData*)entropy - altDSID:(NSString*)altDSID - containerName:(NSString*)containerName - context:(NSString*)context + altDSID:(NSString *)altDSID + containerName:(NSString *)containerName + context:(NSString *)context control:(OTControl*)control { __block long ret = 0; @@ -441,24 +593,24 @@ static void print_json(NSDictionary* dict) #endif } -- (long)fetchAllBottles:(NSString*)altDSID - containerName:(NSString*)containerName - context:(NSString*)context +- (long)fetchAllBottles:(NSString *)altDSID + containerName:(NSString *)containerName + context:(NSString *)context control:(OTControl*)control { __block long ret = 0; #if OCTAGON __block NSError* localError = nil; - __block NSArray* localViableBottleIDs = nil; - __block NSArray* localPartiallyViableBottleIDs = nil; + __block NSArray* localViableBottleIDs = nil; + __block NSArray* localPartiallyViableBottleIDs = nil; dispatch_semaphore_t sema = dispatch_semaphore_create(0); [control fetchAllViableBottles:containerName context:context - reply:^(NSArray* _Nullable sortedBottleIDs, - NSArray* _Nullable sortedPartialBottleIDs, + reply:^(NSArray* _Nullable sortedBottleIDs, + NSArray* _Nullable sortedPartialBottleIDs, NSError* _Nullable controlError) { if(controlError) { secnotice("clique", "findOptimalBottleIDsWithContextData errored: %@\n", controlError); @@ -476,11 +628,11 @@ static void print_json(NSDictionary* dict) return -1; } - [localViableBottleIDs enumerateObjectsUsingBlock:^(NSString* obj, NSUInteger idx, BOOL* stop) { + [localViableBottleIDs enumerateObjectsUsingBlock:^(NSString * obj, NSUInteger idx, BOOL* stop) { printf("preferred bottleID: %s\n", [obj UTF8String]); }]; - [localPartiallyViableBottleIDs enumerateObjectsUsingBlock:^(NSString* obj, NSUInteger idx, BOOL* stop) { + [localPartiallyViableBottleIDs enumerateObjectsUsingBlock:^(NSString * obj, NSUInteger idx, BOOL* stop) { printf("partial recovery bottleID: %s\n", [obj UTF8String]); }]; @@ -491,7 +643,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)healthCheck:(NSString* _Nullable)container context:(NSString*)contextID skipRateLimitingCheck:(BOOL)skipRateLimitingCheck +- (long)healthCheck:(NSString * _Nullable)container context:(NSString *)contextID skipRateLimitingCheck:(BOOL)skipRateLimitingCheck { #if OCTAGON __block long ret = -1; @@ -514,7 +666,7 @@ static void print_json(NSDictionary* dict) #endif } -- (long)refetchCKKSPolicy:(NSString*)container context:(NSString*)contextID +- (long)refetchCKKSPolicy:(NSString *)container context:(NSString *)contextID { #if OCTAGON __block long ret = 1; @@ -559,4 +711,53 @@ static void print_json(NSDictionary* dict) #endif } +- (long)setUserControllableViewsSyncStatus:(NSString * _Nullable)containerName + contextID:(NSString *)contextID + enabled:(BOOL)enabled +{ + #if OCTAGON + __block long ret = 1; + + [self.control setUserControllableViewsSyncStatus:containerName + contextID:contextID + enabled:enabled + reply:^(BOOL nowSyncing, NSError * _Nullable error) { + if(error) { + printf("Error setting user controllable views: %s\n", [[error description] UTF8String]); + } else { + printf("User controllable views are now %s.", [(nowSyncing ? @"enabled" : @"paused") UTF8String]); + ret = 0; + } + }]; + return ret; + #else + printf("Unimplemented.\n"); + return 1; + #endif +} + +- (long)fetchUserControllableViewsSyncStatus:(NSString * _Nullable)containerName + contextID:(NSString *)contextID +{ + #if OCTAGON + __block long ret = 1; + + [self.control fetchUserControllableViewsSyncStatus:containerName + contextID:contextID + reply:^(BOOL nowSyncing, NSError * _Nullable error) { + if(error) { + printf("Error setting user controllable views: %s\n", [[error description] UTF8String]); + } else { + printf("User controllable views are currently %s.", [(nowSyncing ? @"enabled" : @"paused") UTF8String]); + ret = 0; + } + }]; + return ret; + #else + printf("Unimplemented.\n"); + return 1; + #endif +} + + @end diff --git a/keychain/otctl/otctl.m b/keychain/otctl/otctl.m index dd0cb2cb..3086aa66 100644 --- a/keychain/otctl/otctl.m +++ b/keychain/otctl/otctl.m @@ -7,6 +7,7 @@ #import #import #import +#import #import "keychain/otctl/OTControlCLI.h" #import "keychain/otctl/EscrowRequestCLI.h" @@ -23,6 +24,7 @@ static int signIn = false; static int signOut = false; static int resetoctagon = false; static int resetProtectedData = false; +static int userControllableViewsSyncStatus = false; static int fetchAllBottles = false; static int recover = false; @@ -38,6 +40,12 @@ static int ckks_policy_flag = false; static int ttr_flag = false; +static int fetch_escrow_records = false; +static int fetch_all_escrow_records = false; + +static int recoverRecord = false; +static int recoverSilentRecord = false; + static int health = false; #if TARGET_OS_WATCH @@ -48,6 +56,11 @@ static char* bottleIDArg = NULL; static char* contextNameArg = NULL; static char* secretArg = NULL; static char* skipRateLimitingCheckArg = NULL; +static char* recordID = NULL; + +static int argEnable = false; +static int argPause = false; + static int json = false; static char* altDSIDArg = NULL; @@ -71,6 +84,10 @@ int main(int argc, char** argv) {.shortname = 'e', .longname = "bottleID", .argument = &bottleIDArg, .description = "bottle record id"}, {.shortname = 'r', .longname = "skipRateLimiting", .argument = &skipRateLimitingCheckArg, .description = " enter values YES or NO, option defaults to NO, This gives you the opportunity to skip the rate limiting check when performing the cuttlefish health check"}, {.shortname = 'j', .longname = "json", .flag = &json, .flagval = true, .description = "Output in JSON"}, + {.shortname = 'i', .longname = "recordID", .argument = &recordID, .flagval = true, .description = "recordID"}, + + {.shortname = 'E', .longname = "enable", .flag = &argEnable, .flagval = true, .description = "Enable something (pair with a modification command)"}, + {.shortname = 'P', .longname = "pause", .flag = &argPause, .flagval = true, .description = "Pause something (pair with a modification command)"}, {.longname = "altDSID", .argument = &altDSIDArg, .description = "altDSID (for sign-in/out)"}, {.longname = "entropy", .argument = &secretArg, .description = "escrowed entropy in JSON"}, @@ -89,6 +106,8 @@ int main(int argc, char** argv) {.command = "resetoctagon", .flag = &resetoctagon, .flagval = true, .description = "Reset and establish new Octagon trust"}, {.command = "resetProtectedData", .flag = &resetProtectedData, .flagval = true, .description = "Reset ProtectedData"}, + {.command = "user-controllable-views", .flag = &userControllableViewsSyncStatus, .flagval = true, .description = "Modify or view user-controllable views status (If one of --enable or --pause is passed, will modify status)"}, + {.command = "allBottles", .flag = &fetchAllBottles, .flagval = true, .description = "Fetch all viable bottles"}, {.command = "recover", .flag = &recover, .flagval = true, .description = "Recover using this bottle"}, {.command = "depart", .flag = &depart, .flagval = true, .description = "Depart from Octagon Trust"}, @@ -103,6 +122,13 @@ int main(int argc, char** argv) {.command = "taptoradar", .flag = &ttr_flag, .flagval = true, .description = "Trigger a TapToRadar"}, + {.command = "fetchEscrowRecords", .flag = &fetch_escrow_records, .flagval = true, .description = "Fetch Escrow Records"}, + {.command = "fetchAllEscrowRecords", .flag = &fetch_all_escrow_records, .flagval = true, .description = "Fetch All Escrow Records"}, + + {.command = "recover-record", .flag = &recoverRecord, .flagval = true, .description = "Recover record"}, + {.command = "recover-record-silent", .flag = &recoverSilentRecord, .flagval = true, .description = "Silent record recovery"}, + + #if TARGET_OS_WATCH {.command = "pairme", .flag = &pairme, .flagval = true, .description = "Perform pairing (watchOS only)"}, @@ -154,6 +180,22 @@ int main(int argc, char** argv) long ret = [ctl resetProtectedData:container context:context altDSID:altDSID appleID:appleID dsid:dsid]; return (int)ret; } + if(userControllableViewsSyncStatus) { + internalOnly(); + + if(argEnable && argPause) { + print_usage(&args); + return -1; + } + + if(argEnable == false && argPause == false) { + return (int)[ctl fetchUserControllableViewsSyncStatus:container contextID:context]; + } + + // At this point, we're sure that either argEnabled or argPause is set; so the value of argEnabled captures the user's intention + return (int)[ctl setUserControllableViewsSyncStatus:container contextID:context enabled:argEnable]; + } + if(fetchAllBottles) { return (int)[ctl fetchAllBottles:altDSID containerName:container context:context control:rpc]; } @@ -198,7 +240,33 @@ int main(int argc, char** argv) if(status) { return (int)[ctl status:container context:context json:json]; } + if(fetch_escrow_records) { + return (int)[ctl fetchEscrowRecords:container context:context]; + } + if(fetch_all_escrow_records) { + return (int)[ctl fetchAllEscrowRecords:container context:context]; + } + if(recoverRecord) { + NSString* recordIDString = recordID ? [NSString stringWithCString:recordID encoding:NSUTF8StringEncoding] : nil; + NSString* secret = secretArg ? [NSString stringWithCString:secretArg encoding:NSUTF8StringEncoding] : nil; + + if(!recordIDString || !secret || !appleID) { + print_usage(&args); + return -1; + } + + return (int)[ctl performEscrowRecovery:container context:context recordID:recordIDString appleID:appleID secret:secret]; + } + if(recoverSilentRecord){ + NSString* secret = secretArg ? [NSString stringWithCString:secretArg encoding:NSUTF8StringEncoding] : nil; + + if(!secret || !appleID) { + print_usage(&args); + return -1; + } + return (int)[ctl performSilentEscrowRecovery:container context:context appleID:appleID secret:secret]; + } if(health) { BOOL skip = NO; if([skipRateLimitingCheck isEqualToString:@"YES"]) { diff --git a/keychain/otpaird/OTPairingConstants.h b/keychain/otpaird/OTPairingConstants.h index 309ee32a..71f20133 100644 --- a/keychain/otpaird/OTPairingConstants.h +++ b/keychain/otpaird/OTPairingConstants.h @@ -3,10 +3,9 @@ #define OTPairingIDSServiceName @"com.apple.private.alloy.octagon" #define OTPairingIDSKeyMessageType @"m" -#define OTPairingIDSKeyError @"e" #define OTPairingIDSKeySession @"session" #define OTPairingIDSKeyPacket @"packet" -#define OTPairingIDSKeyErrorDeprecated @"error" +#define OTPairingIDSKeyErrorDescription @"error" enum OTPairingIDSMessageType { OTPairingIDSMessageTypePacket = 1, diff --git a/keychain/otpaird/OTPairingPacketContext.m b/keychain/otpaird/OTPairingPacketContext.m index 7fbbef9a..e8854f26 100644 --- a/keychain/otpaird/OTPairingPacketContext.m +++ b/keychain/otpaird/OTPairingPacketContext.m @@ -1,7 +1,6 @@ #import #import #import -#import #import "keychain/categories/NSError+UsefulConstructors.h" @@ -23,8 +22,7 @@ - (instancetype)initWithMessage:(NSDictionary *)message fromID:(NSString *)fromID context:(IDSMessageContext *)context { - self = [super init]; - if (self != nil) { + if ((self = [super init])) { self.message = message; self.fromID = fromID; self.context = context; @@ -69,15 +67,8 @@ } if (!self->_error) { - NSData *errorData = self.message[OTPairingIDSKeyError]; - if (errorData != NULL) { - self->_error = [SecXPCHelper errorFromEncodedData:errorData]; - } else { - // Key from older iOS builds; remove soon - // When this is removed, it will still be useful to have a fallback in case errorData is missing or errorFromEncodedData fails - NSString *errorString = self.message[OTPairingIDSKeyErrorDeprecated]; - self->_error = [NSError errorWithDomain:OTPairingErrorDomain code:OTPairingErrorTypeRemote description:errorString]; - } + NSString *errorString = self.message[OTPairingIDSKeyErrorDescription]; + self->_error = [NSError errorWithDomain:OTPairingErrorDomain code:OTPairingErrorTypeRemote description:errorString]; } return self->_error; diff --git a/keychain/otpaird/OTPairingService.m b/keychain/otpaird/OTPairingService.m index c1b70852..826230c0 100644 --- a/keychain/otpaird/OTPairingService.m +++ b/keychain/otpaird/OTPairingService.m @@ -3,7 +3,6 @@ #import #import #import -#import #import #if TARGET_OS_WATCH @@ -49,8 +48,7 @@ - (instancetype)init { - self = [super init]; - if (self != nil) { + if ((self = [super init])) { self.queue = dispatch_queue_create("com.apple.security.otpaird", DISPATCH_QUEUE_SERIAL); self.service = [[IDSService alloc] initWithService:OTPairingIDSServiceName]; [self.service addDelegate:self queue:self.queue]; @@ -159,8 +157,7 @@ NSMutableDictionary *message = [[NSMutableDictionary alloc] init]; message[OTPairingIDSKeyMessageType] = @(OTPairingIDSMessageTypeError); message[OTPairingIDSKeySession] = self.session.identifier; - message[OTPairingIDSKeyError] = [SecXPCHelper encodedDataFromError:unlockError]; - message[OTPairingIDSKeyErrorDeprecated] = unlockError.localizedDescription; // For older watchOS builds; remove soon + message[OTPairingIDSKeyErrorDescription] = unlockError.description; NSString *toID = packet.fromID; NSString *responseIdentifier = packet.outgoingResponseIdentifier; [self _sendMessage:message to:toID identifier:responseIdentifier]; @@ -194,12 +191,10 @@ if (channelError != nil) { #if TARGET_OS_IOS - NSError *cleansedError = [SecXPCHelper cleanseErrorForXPC:channelError]; NSMutableDictionary *message = [[NSMutableDictionary alloc] init]; message[OTPairingIDSKeyMessageType] = @(OTPairingIDSMessageTypeError); message[OTPairingIDSKeySession] = self.session.identifier; - message[OTPairingIDSKeyError] = cleansedError ? [SecXPCHelper encodedDataFromError:cleansedError] : nil; - message[OTPairingIDSKeyErrorDeprecated] = channelError.description; + message[OTPairingIDSKeyErrorDescription] = channelError.description; os_assert(packet != nil); // the acceptor always responds to a request packet, it's never initiating toID = packet.fromID; responseIdentifier = packet.outgoingResponseIdentifier; @@ -260,7 +255,10 @@ identifier:&identifier error:&error]; if (sendResult) { - self.session.sentMessageIdentifier = identifier; + /* sentMessageIdentifier is used to validate the next reply; do not set if no reply is expected. */ + if (expectReply) { + self.session.sentMessageIdentifier = identifier; + } } else { os_log(OS_LOG_DEFAULT, "send message failed (%@): %@", identifier, error); // On iOS, do nothing; watch will time out waiting for response. diff --git a/keychain/otpaird/OTPairingSession.m b/keychain/otpaird/OTPairingSession.m index 9444f1ca..3d4cf579 100644 --- a/keychain/otpaird/OTPairingSession.m +++ b/keychain/otpaird/OTPairingSession.m @@ -22,8 +22,7 @@ { KCPairingChannelContext *channelContext = nil; - self = [super init]; - if (self != nil) { + if ((self = [super init])) { self.identifier = identifier; channelContext = [KCPairingChannelContext new]; diff --git a/keychain/otpaird/otpaird.iphoneos.entitlements b/keychain/otpaird/otpaird.iphoneos.entitlements index 687c9a25..55994f03 100644 --- a/keychain/otpaird/otpaird.iphoneos.entitlements +++ b/keychain/otpaird/otpaird.iphoneos.entitlements @@ -10,28 +10,13 @@ com.apple.private.octagon - com.apple.security.exception.files.absolute-path.read-only - - /usr/libexec - - com.apple.security.exception.iokit-user-client-class - - AppleKeyStoreUserClient - - com.apple.security.exception.mach-lookup.global-name - - com.apple.security.octagon - com.apple.securityd.sos - - com.apple.security.ts.identity-services-client - keychain-cloud-circle platform-application seatbelt-profiles - temporary-sandbox + otpaird diff --git a/keychain/otpaird/otpaird.watchos.entitlements b/keychain/otpaird/otpaird.watchos.entitlements index 32082d1c..4749b51b 100644 --- a/keychain/otpaird/otpaird.watchos.entitlements +++ b/keychain/otpaird/otpaird.watchos.entitlements @@ -10,25 +10,11 @@ com.apple.private.octagon - com.apple.security.exception.files.absolute-path.read-only - - /usr/libexec - - com.apple.security.exception.iokit-user-client-class - - AppleKeyStoreUserClient - - com.apple.security.exception.mach-lookup.global-name - - com.apple.security.octagon - - com.apple.security.ts.identity-services-client - platform-application seatbelt-profiles - temporary-sandbox + otpaird diff --git a/keychain/securityd/PolicyReporter.m b/keychain/securityd/PolicyReporter.m index c5b42c66..69aecb43 100644 --- a/keychain/securityd/PolicyReporter.m +++ b/keychain/securityd/PolicyReporter.m @@ -172,6 +172,13 @@ static void oneReport(void) { NSLog(@"policy is nil"); return; } + TPSyncingPolicy* syncingPolicy = [policy syncingPolicyForModel:@"iPhone" + syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_UNKNOWN + error:&error]; + if(syncingPolicy == nil || error != nil) { + NSLog(@"syncing policy is nil: %@", error); + return; + } unsigned real_mismatches = 0; unsigned expected_mismatches = 0; @@ -219,7 +226,7 @@ static void oneReport(void) { NSMutableDictionary* mutA = [a mutableCopy]; mutA[(id)kSecClass] = (id)itemClass; - NSString* newView = [policy mapKeyToView:mutA]; + NSString* newView = [syncingPolicy mapDictionaryToView:mutA]; if (newView != nil) { NSLog(@"new: %@", newView); } diff --git a/keychain/securityd/Regressions/SOSAccountTesting.h b/keychain/securityd/Regressions/SOSAccountTesting.h index d3f6fd16..413b75cb 100644 --- a/keychain/securityd/Regressions/SOSAccountTesting.h +++ b/keychain/securityd/Regressions/SOSAccountTesting.h @@ -62,7 +62,7 @@ static inline bool SOSAccountJoinCirclesAfterRestore_wTxn(SOSAccount* acct, CFEr { __block bool result = false; [acct performTransaction:^(SOSAccountTransaction * _Nonnull txn) { - result = SOSAccountJoinCirclesAfterRestore(txn, nil, error); + result = SOSAccountJoinCirclesAfterRestore(txn, error); }]; return result; } @@ -71,7 +71,7 @@ static inline bool SOSAccountJoinCircles_wTxn(SOSAccount* acct, CFErrorRef* erro { __block bool result = false; [acct performTransaction:^(SOSAccountTransaction * _Nonnull txn) { - result = SOSAccountJoinCircles(txn, nil, error); + result = SOSAccountJoinCircles(txn, error); }]; return result; } diff --git a/keychain/securityd/Regressions/SOSTransportTestTransports.m b/keychain/securityd/Regressions/SOSTransportTestTransports.m index e354c55f..24b0050f 100644 --- a/keychain/securityd/Regressions/SOSTransportTestTransports.m +++ b/keychain/securityd/Regressions/SOSTransportTestTransports.m @@ -29,8 +29,7 @@ CFMutableArrayRef message_transports = NULL; -(id) initWithAccount:(SOSAccount*) acct andName:(CFStringRef) n andCircleName:(CFStringRef) cN { - self = [super init]; - if(self){ + if ((self = [super init])) { self.name = CFRetainSafe(n); self.changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); self.account = acct; @@ -142,8 +141,7 @@ void SOSTransportCircleTestClearChanges(SOSCircleStorageTransportTest* transport -(id) initWithAccount:(SOSAccount *)acct andWithAccountName:(CFStringRef)acctName andCircleName:(CFStringRef)cName { - self = [super init]; - if(self){ + if ((self = [super init])) { self.account = acct; self.accountName = (__bridge NSString *)(acctName); self.circleName = (__bridge NSString*)cName; @@ -313,8 +311,7 @@ SOSAccount* SOSTransportCircleTestGetAccount(SOSCircleStorageTransportTest* tran -(id) initWithAccount:(SOSAccount*)acct andName:(CFStringRef)n andCircleName:(CFStringRef) cN { - self = [super init]; - if(self){ + if ((self = [super init])) { self.engine = SOSDataSourceFactoryGetEngineForDataSourceName(acct.factory, cN, NULL); self.account = acct; self.changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); @@ -513,12 +510,12 @@ void SOSAccountUpdateTestTransports(SOSAccount* account, CFDictionaryRef gestalt SOSTransportMessageKVSTestSetName((SOSMessageKVSTest*)account.kvs_message_transport, new_name); } -static CF_RETURNS_RETAINED SOSCircleRef SOSAccountEnsureCircleTest(SOSAccount* a, CFStringRef name, CFStringRef accountName) +static CF_RETURNS_RETAINED SOSCircleRef SOSAccountEnsureCircleTest(SOSAccount* account, CFStringRef name, CFStringRef accountName) { CFErrorRef localError = NULL; - SOSAccountTrustClassic *trust = a.trust; + SOSAccountTrustClassic *trust = account.trust; - SOSCircleRef circle = CFRetainSafe([a.trust getCircle:&localError]); + SOSCircleRef circle = CFRetainSafe([account.trust getCircle:&localError]); if(!circle || isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle)){ secnotice("circle", "Error retrieving the circle: %@", localError); CFReleaseNull(localError); @@ -534,7 +531,7 @@ static CF_RETURNS_RETAINED SOSCircleRef SOSAccountEnsureCircleTest(SOSAccount* a CFReleaseNull(localError); } - if(![trust ensureFullPeerAvailable:(__bridge CFDictionaryRef)(a.gestalt) deviceID:(__bridge CFStringRef)(a.deviceID) backupKey:(__bridge CFDataRef)(a.backup_key) err:&localError]) + if(![trust ensureFullPeerAvailable:account err:&localError]) { secnotice("circle", "had an error building full peer: %@", localError); CFReleaseNull(localError); diff --git a/keychain/securityd/Regressions/SecdTestKeychainUtilities.c b/keychain/securityd/Regressions/SecdTestKeychainUtilities.c index b5700649..b239deb7 100644 --- a/keychain/securityd/Regressions/SecdTestKeychainUtilities.c +++ b/keychain/securityd/Regressions/SecdTestKeychainUtilities.c @@ -42,6 +42,7 @@ void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_ { CFStringRef tmp_dir = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("/tmp/%s.%X/"), test_prefix, arc4random()); CFStringRef keychain_dir = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@Library/Keychains"), tmp_dir); + secnotice("secdtest", "Keychain path: %@", keychain_dir); CFStringPerformWithCString(keychain_dir, ^(const char *keychain_dir_string) { errno_t err = mkpath_np(keychain_dir_string, 0755); diff --git a/keychain/securityd/Regressions/secd-100-initialsync.m b/keychain/securityd/Regressions/secd-100-initialsync.m index b2391098..fb62c13a 100644 --- a/keychain/securityd/Regressions/secd-100-initialsync.m +++ b/keychain/securityd/Regressions/secd-100-initialsync.m @@ -51,6 +51,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void tests(void) { @@ -150,14 +151,16 @@ static void tests(void) SOSTestCleanup(); } +#endif int secd_100_initialsync(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(33); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-130-other-peer-views.m b/keychain/securityd/Regressions/secd-130-other-peer-views.m index 8fe1cb2c..b2ba0f57 100644 --- a/keychain/securityd/Regressions/secd-130-other-peer-views.m +++ b/keychain/securityd/Regressions/secd-130-other-peer-views.m @@ -20,6 +20,7 @@ #include "SOSAccountTesting.h" #include "keychain/SecureObjectSync/SOSAccount.h" +#if SOS_ENABLED #define kAccountPasswordString ((uint8_t*) "FooFooFoo") #define kAccountPasswordStringLen 10 @@ -165,14 +166,17 @@ static void tests(void) { SOSTestCleanup(); } +#endif int secd_130_other_peer_views(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(72); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); secd_test_clear_testviews(); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-154-engine-backoff.m b/keychain/securityd/Regressions/secd-154-engine-backoff.m index e75660d4..78010ff5 100644 --- a/keychain/securityd/Regressions/secd-154-engine-backoff.m +++ b/keychain/securityd/Regressions/secd-154-engine-backoff.m @@ -28,6 +28,9 @@ #include "SOSTestDataSource.h" #include "SOSRegressionUtilities.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED static int kTestTestCount = 10; static int MAX_PENALTY_TIME = 32; @@ -268,12 +271,15 @@ static void tests(void) ok(successful_writes == 12, "successfull writes should have only reached 10"); ok(monitor->penalty_box == 0, "penalty box should reset back to 0"); } +#endif int secd_154_engine_backoff(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-155-otr-negotiation-monitor.m b/keychain/securityd/Regressions/secd-155-otr-negotiation-monitor.m index 446afdce..69419ef4 100644 --- a/keychain/securityd/Regressions/secd-155-otr-negotiation-monitor.m +++ b/keychain/securityd/Regressions/secd-155-otr-negotiation-monitor.m @@ -38,6 +38,7 @@ #include "SOSTestDevice.h" #include "SOSTestDataSource.h" #include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" +#if SOS_ENABLED static void tests(void) @@ -158,14 +159,16 @@ static void tests(void) // ids_test_sync(alice_account, bob_account); } +#endif int secd_155_otr_negotiation_monitor(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(44); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-200-logstate.m b/keychain/securityd/Regressions/secd-200-logstate.m index 55d926f9..9bd5ceff 100644 --- a/keychain/securityd/Regressions/secd-200-logstate.m +++ b/keychain/securityd/Regressions/secd-200-logstate.m @@ -56,6 +56,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED #define HOW_MANY_MINIONS 4 @@ -223,14 +224,16 @@ static void tests(void) SOSTestCleanup(); } +#endif int secd_200_logstate(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(((HOW_MANY_MINIONS+1)*10 + 1)); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-201-coders.m b/keychain/securityd/Regressions/secd-201-coders.m index d851ca17..d4f26ce6 100644 --- a/keychain/securityd/Regressions/secd-201-coders.m +++ b/keychain/securityd/Regressions/secd-201-coders.m @@ -58,6 +58,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void tests(void) { @@ -164,14 +165,16 @@ static void tests(void) CFReleaseNull(changes); } +#endif int secd_201_coders(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(38); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-202-recoverykey.m b/keychain/securityd/Regressions/secd-202-recoverykey.m index e00d57af..0d60804a 100644 --- a/keychain/securityd/Regressions/secd-202-recoverykey.m +++ b/keychain/securityd/Regressions/secd-202-recoverykey.m @@ -22,6 +22,9 @@ #import #import "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED const int kTestRecoveryKeyCount = 3; @@ -52,16 +55,17 @@ static void testRecoveryKeyBasic(void) } } +#endif int secd_202_recoverykey(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestRecoveryKeyCount + kTestRecoveryKeyBasicCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - testRecoveryKeyBasic(); - testRecoveryKey(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-210-keyinterest.m b/keychain/securityd/Regressions/secd-210-keyinterest.m index 82e7c890..13d14f80 100644 --- a/keychain/securityd/Regressions/secd-210-keyinterest.m +++ b/keychain/securityd/Regressions/secd-210-keyinterest.m @@ -15,8 +15,11 @@ #import "CKDSimulatedStore.h" #import "CKDSimulatedAccount.h" #import "CKDAKSLockMonitor.h" - #include "SOSCloudKeychainConstants.h" +#include "SOSAccountTesting.h" + + +#if SOS_ENABLED @interface CKDSimulatedLockMonitor : NSObject @@ -47,8 +50,7 @@ } - (instancetype) init { - self = [super init]; - if (self) { + if ((self = [super init])) { _locked = true; _unlockedSinceBoot = false; } @@ -189,12 +191,15 @@ static void tests(void) { } +#endif int secd_210_keyinterest(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(12); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-33-keychain-ctk.m b/keychain/securityd/Regressions/secd-33-keychain-ctk.m index 4aa765e0..3a2573fd 100644 --- a/keychain/securityd/Regressions/secd-33-keychain-ctk.m +++ b/keychain/securityd/Regressions/secd-33-keychain-ctk.m @@ -39,8 +39,11 @@ #include #include #include +#include #include +#include + #include #include @@ -216,7 +219,7 @@ static void test_item_query() { (id)kSecReturnPersistentRef : @YES }, &result)); is(phase, 0); NSData *persistentRef = (__bridge NSData *)result; - is(CFDataCompare((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), kCFCompareEqualTo); + is(CFEqual((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), TRUE); CFReleaseSafe(result); phase = 0; @@ -226,7 +229,7 @@ static void test_item_query() { (id)kSecReturnPersistentRef : @YES }, &result)); is(phase, 2); persistentRef = ((__bridge NSDictionary *)result)[(id)kSecValuePersistentRef]; - is(CFDataCompare((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), kCFCompareEqualTo); + is(CFEqual((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), TRUE); CFReleaseSafe(result); phase = 0; @@ -236,7 +239,7 @@ static void test_item_query() { (id)kSecReturnPersistentRef : @YES }, &result)); is(phase, 0); persistentRef = ((__bridge NSDictionary *)result)[(id)kSecValuePersistentRef]; - is(CFDataCompare((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), kCFCompareEqualTo); + is(CFEqual((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), TRUE); CFReleaseSafe(result); phase = 0; @@ -247,7 +250,7 @@ static void test_item_query() { (id)kSecReturnPersistentRef : @YES }, &result)); is(phase, 2); persistentRef = ((__bridge NSDictionary *)result)[(id)kSecValuePersistentRef]; - is(CFDataCompare((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), kCFCompareEqualTo); + is(CFEqual((__bridge CFDataRef)persistentRefId, (__bridge CFDataRef)[persistentRef subdataWithRange:NSMakeRange(0, 4)]), TRUE); CFReleaseSafe(result); CFRelease(query); @@ -775,37 +778,44 @@ static CFMutableDictionaryRef copy_certificate_attributes(const char *base64Cert return result; } -static CFDictionaryRef copy_certificate_query(const char *base64cert, CFStringRef label, CFStringRef oid, CFStringRef tokenID) +static CFDictionaryRef copy_certificate_query(const char *base64cert, CFStringRef label, CFDataRef oid, CFStringRef tokenID) { CFMutableDictionaryRef certAttributes = copy_certificate_attributes(base64cert); CFDictionarySetValue(certAttributes, kSecAttrLabel, label); CFDictionarySetValue(certAttributes, kSecAttrAccessible, kSecAttrAccessibleAlwaysPrivate); - CFDictionarySetValue(certAttributes, kSecAttrTokenOID, oid); + if (oid != NULL) { + CFDictionarySetValue(certAttributes, kSecAttrTokenOID, oid); + } CFDictionaryRemoveValue(certAttributes, kSecValueData); - SecAccessControlRef acl = SecAccessControlCreate(kCFAllocatorDefault, NULL); - ok(acl); - CFTypeRef key[] = { kSecAttrTokenID }; - CFTypeRef value[] = { tokenID }; - CFDictionaryRef protection = CFDictionaryCreate(kCFAllocatorDefault, key, value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - ok(SecAccessControlSetProtection(acl, protection, NULL)); - CFRelease(protection); - ok(SecAccessControlAddConstraintForOperation(acl, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL)); - CFDataRef aclData = SecAccessControlCopyData(acl); - ok(aclData); - if (aclData) { - CFDictionarySetValue(certAttributes, kSecAttrAccessControl, aclData); - CFRelease(aclData); - } + if (tokenID != NULL) { + SecAccessControlRef acl = SecAccessControlCreate(kCFAllocatorDefault, NULL); + ok(acl); + CFTypeRef key[] = { kSecAttrTokenID }; + CFTypeRef value[] = { tokenID }; + CFDictionaryRef protection = CFDictionaryCreate(kCFAllocatorDefault, key, value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + ok(SecAccessControlSetProtection(acl, protection, NULL)); + CFRelease(protection); + ok(SecAccessControlAddConstraintForOperation(acl, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL)); + CFDataRef aclData = SecAccessControlCopyData(acl); + ok(aclData); + if (aclData) { + CFDictionarySetValue(certAttributes, kSecAttrAccessControl, aclData); + CFRelease(aclData); + } - if (acl) - CFRelease(acl); + if (acl) + CFRelease(acl); + } else { + NSData *certData = CFBridgingRelease(copy_certificate_data(base64cert)); + CFDictionarySetValue(certAttributes, kSecValueData, (__bridge CFDataRef)certData); + } return certAttributes; } -static CFDictionaryRef copy_key_query(CFDictionaryRef certAttributes, CFStringRef label, CFStringRef oid, CFStringRef tokenID) +static CFDictionaryRef copy_key_query(CFDictionaryRef certAttributes, CFStringRef label, CFDataRef oid, CFStringRef tokenID) { CFMutableDictionaryRef keyAttributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) ; @@ -859,20 +869,25 @@ static void check_array_for_type_id(CFArrayRef array, CFTypeID typeID) static void test_propagate_token_items() { - CFStringRef cert1OID = CFSTR("oid1"); - CFStringRef cert2OID = CFSTR("oid2"); - CFStringRef key1OID = CFSTR("oid3"); - CFStringRef key2OID = CFSTR("oid4"); + if (!os_feature_enabled(CryptoTokenKit, UseTokens)) { + // This test does not work if tokens cannot be used by keychain. + return; + } + + NSData *cert1OID = [@"oid1" dataUsingEncoding:NSUTF8StringEncoding]; + NSData *cert2OID = [@"oid2" dataUsingEncoding:NSUTF8StringEncoding]; + NSData *key1OID = [@"oid3" dataUsingEncoding:NSUTF8StringEncoding]; + NSData *key2OID = [@"oid4" dataUsingEncoding:NSUTF8StringEncoding]; TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) { blocks->copyObjectData = ^CFTypeRef(CFDataRef oid, CFErrorRef *error) { - if (CFEqual(oid, cert1OID)) { + if (CFEqual(oid, (__bridge CFDataRef)cert1OID)) { return copy_certificate_data(cert1); } - else if (CFEqual(oid, cert2OID)) { + else if (CFEqual(oid, (__bridge CFDataRef)cert2OID)) { return copy_certificate_data(cert2); } - else if (CFEqual(oid, key1OID) || CFEqual(oid, key2OID)) { + else if (CFEqual(oid, (__bridge CFDataRef)key1OID) || CFEqual(oid, (__bridge CFDataRef)key2OID)) { return kCFNull; } else { @@ -885,9 +900,9 @@ static void test_propagate_token_items() CFMutableArrayRef items = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFDictionaryRef certQuery = copy_certificate_query(cert1, CFSTR("test_cert1"), cert1OID, tokenID); + CFDictionaryRef certQuery = copy_certificate_query(cert1, CFSTR("test_cert1"), (__bridge CFDataRef)cert1OID, tokenID); ok(certQuery); - CFDictionaryRef keyQuery = copy_key_query(certQuery, CFSTR("test_key1"), key1OID, tokenID); + CFDictionaryRef keyQuery = copy_key_query(certQuery, CFSTR("test_key1"), (__bridge CFDataRef)key1OID, tokenID); ok(keyQuery); CFArrayAppendValue(items, certQuery); @@ -895,9 +910,9 @@ static void test_propagate_token_items() CFReleaseSafe(certQuery); CFReleaseSafe(keyQuery); - certQuery = copy_certificate_query(cert2, CFSTR("test_cert2"), cert2OID, tokenID); + certQuery = copy_certificate_query(cert2, CFSTR("test_cert2"), (__bridge CFDataRef)cert2OID, tokenID); ok(certQuery); - keyQuery = copy_key_query(certQuery, CFSTR("test_key2"), key2OID, tokenID); + keyQuery = copy_key_query(certQuery, CFSTR("test_key2"), (__bridge CFDataRef)key2OID, tokenID); ok(keyQuery); CFArrayAppendValue(items, certQuery); @@ -906,9 +921,9 @@ static void test_propagate_token_items() CFReleaseSafe(keyQuery); OSStatus result; - ok_status(result = SecItemUpdateTokenItems(tokenID, NULL), "Failed to delete items."); + ok_status(result = SecItemUpdateTokenItemsForAccessGroups(tokenID, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], NULL), "Failed to delete items."); - ok_status(result = SecItemUpdateTokenItems(tokenID, items), "Failed to propagate items."); + ok_status(result = SecItemUpdateTokenItemsForAccessGroups(tokenID, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], items), "Failed to propagate items."); CFRelease(items); CFMutableDictionaryRef query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -957,7 +972,7 @@ static void test_propagate_token_items() ok(queryResult && CFGetTypeID(queryResult) == CFArrayGetTypeID() && CFArrayGetCount(queryResult) == 0, "Expect empty array"); CFReleaseNull(queryResult); - ok_status(result = SecItemUpdateTokenItems(tokenID, NULL), "Failed to delete items."); + ok_status(result = SecItemUpdateTokenItemsForAccessGroups(tokenID, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], NULL), "Failed to delete items."); CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); CFDictionarySetValue(query, kSecReturnData, kCFBooleanFalse); @@ -967,17 +982,10 @@ static void test_propagate_token_items() } static void test_identity_on_two_tokens() { - CFStringRef cert3OID = CFSTR("oid1"); - TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) { - - blocks->copyObjectData = ^CFTypeRef(CFDataRef oid, CFErrorRef *error) { - if (CFEqual(oid, cert3OID)) - return copy_certificate_data(cert3); - else - return kCFNull; - }; - - }); + if (!os_feature_enabled(CryptoTokenKit, UseTokens)) { + // This test does not work if tokens cannot be used by keychains. + return; + } @autoreleasepool { NSString *tokenID1 = @"com.apple.secdtest:identity_test_token1"; @@ -989,6 +997,25 @@ static void test_identity_on_two_tokens() { id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((__bridge SecKeyRef)privKey)); NSData *pubKeyHash = CFBridgingRelease(SecKeyCopyPublicKeyHash((__bridge SecKeyRef)publicKey)); + NSData *cert3OID = [@"oid1" dataUsingEncoding:NSUTF8StringEncoding]; + TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) { + + blocks->copyObjectData = ^CFTypeRef(CFDataRef oid, CFErrorRef *error) { + if (CFEqual(oid, (__bridge CFDataRef)cert3OID)) + return copy_certificate_data(cert3); + else + return kCFNull; + }; + + blocks->copyPublicKeyData = ^CFDataRef(CFDataRef oid, CFErrorRef *error) { + if ([privKeyData isEqualToData:(__bridge NSData *)oid]) { + return SecKeyCopyExternalRepresentation((SecKeyRef)publicKey, error); + } + return NULL; + }; + + }); + id ac = CFBridgingRelease(SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlocked, 0, NULL)); id acData = CFBridgingRelease(SecAccessControlCopyData((__bridge SecAccessControlRef)ac)); NSDictionary *keyQuery = @{ (id)kSecClass: (id)kSecClassKey, @@ -1002,15 +1029,15 @@ static void test_identity_on_two_tokens() { (id)kSecAttrApplicationLabel : pubKeyHash, }; OSStatus result; - ok_status(result = SecItemUpdateTokenItems((__bridge CFStringRef)tokenID1, (__bridge CFArrayRef)@[keyQuery]), "Failed to propagate key item."); + ok_status(result = SecItemUpdateTokenItemsForAccessGroups((__bridge CFStringRef)tokenID1, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], (__bridge CFArrayRef)@[keyQuery]), "Failed to propagate key item."); id privateKey; ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)@{(id)kSecClass: (id)kSecClassKey, (id)kSecAttrTokenID: tokenID1, (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken, (id)kSecReturnRef: @YES}, (void *)&privateKey)); - NSDictionary *certQuery = CFBridgingRelease(copy_certificate_query(cert3, CFSTR("test_cert3"), cert3OID, (__bridge CFStringRef)tokenID2)); + NSDictionary *certQuery = CFBridgingRelease(copy_certificate_query(cert3, CFSTR("test_cert3"), (__bridge CFDataRef)cert3OID, (__bridge CFStringRef)tokenID2)); ok(certQuery); - ok_status(result = SecItemUpdateTokenItems((__bridge CFStringRef)tokenID2, (__bridge CFArrayRef)@[certQuery]), "Failed to propagate cert item."); + ok_status(result = SecItemUpdateTokenItemsForAccessGroups((__bridge CFStringRef)tokenID2, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], (__bridge CFArrayRef)@[certQuery]), "Failed to propagate cert item."); CFTypeRef resultRef; NSDictionary *query = @{ (id)kSecClass : (id)kSecClassKey, (id)kSecAttrApplicationLabel : pubKeyHash, (id)kSecReturnRef : @YES, (id)kSecReturnAttributes : @YES, (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken }; @@ -1024,6 +1051,97 @@ static void test_identity_on_two_tokens() { query = @{ (id)kSecClass : (id)kSecClassIdentity, (id)kSecAttrApplicationLabel : pubKeyHash, (id)kSecReturnRef : @YES, (id)kSecReturnAttributes : @YES, (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken }; ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef*)&resultRef)); CFReleaseNull(resultRef); + + NSData *persRef, *persRef2; + id newRef; + + // Query persistent reference for key and verify that we can get key back using it. + query = @{ (id)kSecValueRef: privateKey, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef)); + query = @{ (id)kSecClass: (id)kSecClassKey, (id)kSecAttrApplicationLabel: pubKeyHash, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef2)); + eq_cf((__bridge CFTypeRef)persRef, (__bridge CFTypeRef)persRef2); + query = @{ (id)kSecValuePersistentRef: persRef, (id)kSecReturnRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&newRef)); + eq_cf((__bridge CFTypeRef)privateKey, (__bridge CFTypeRef)newRef); + + // Query persistent reference for certificate and verify that we can get certificate back using it. + id certRef; + query = @{ (id)kSecClass: (id)kSecClassCertificate, (id)kSecAttrPublicKeyHash: pubKeyHash, (id)kSecReturnRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&certRef)); + + persRef = nil; + persRef2 = nil; + newRef = nil; + query = @{ (id)kSecValueRef: certRef, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef)); + query = @{ (id)kSecClass: (id)kSecClassCertificate, (id)kSecAttrPublicKeyHash: pubKeyHash, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef2)); + eq_cf((__bridge CFTypeRef)persRef, (__bridge CFTypeRef)persRef2); + query = @{ (id)kSecValuePersistentRef: persRef, (id)kSecReturnRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&newRef)); + eq_cf((__bridge CFTypeRef)certRef, (__bridge CFTypeRef)newRef); + + // Query persistent reference for identity and verify that we can get identity back using it. + id identityRef; + NSDictionary *attrs; + query = @{ (id)kSecClass: (id)kSecClassIdentity, (id)kSecAttrApplicationLabel: pubKeyHash, (id)kSecReturnRef: @YES, (id)kSecReturnAttributes: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&attrs)); + identityRef = attrs[(id)kSecValueRef]; + eq_cf((__bridge CFTypeRef)attrs[(id)kSecAttrTokenID], (__bridge CFTypeRef)tokenID1); + + persRef = nil; + persRef2 = nil; + attrs = nil; + query = @{ (id)kSecValueRef: identityRef, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef)); + query = @{ (id)kSecClass: (id)kSecClassIdentity, (id)kSecAttrApplicationLabel: pubKeyHash, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef2)); + eq_cf((__bridge CFTypeRef)persRef, (__bridge CFTypeRef)persRef2); + query = @{ (id)kSecValuePersistentRef: persRef2, (id)kSecReturnRef: @YES, (id)kSecReturnAttributes: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&attrs)); + eq_cf((__bridge CFTypeRef)identityRef, (__bridge CFTypeRef)attrs[(id)kSecValueRef]); + eq_cf((__bridge CFTypeRef)attrs[(id)kSecAttrTokenID], (__bridge CFTypeRef)tokenID1); + + // Remove certificate from token and add it as regular keychain item (non-token) one. Following tests + // repeat identity test for key-on-token, certificate-non-token hybrid identities. + ok_status(result = SecItemUpdateTokenItemsForAccessGroups((__bridge CFStringRef)tokenID2, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], NULL)); + certQuery = CFBridgingRelease(copy_certificate_query(cert3, CFSTR("reg_cert3"), NULL, NULL)); + ok_status(result = SecItemAdd((__bridge CFDictionaryRef)certQuery, NULL)); + + query = @{ (id)kSecClass: (id)kSecClassIdentity, (id)kSecAttrApplicationLabel: pubKeyHash, (id)kSecReturnRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&identityRef)); + isnt(identityRef, NULL); + + persRef = nil; + persRef2 = nil; + attrs = nil; + query = @{ (id)kSecValueRef: identityRef, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef)); + query = @{ (id)kSecClass: (id)kSecClassIdentity, (id)kSecAttrApplicationLabel: pubKeyHash, (id)kSecReturnPersistentRef: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&persRef2)); + eq_cf((__bridge CFTypeRef)persRef, (__bridge CFTypeRef)persRef2); + query = @{ (id)kSecValuePersistentRef: persRef, (id)kSecReturnRef: @YES, (id)kSecReturnAttributes: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&attrs)); + eq_cf((__bridge CFTypeRef)identityRef, (__bridge CFTypeRef)attrs[(id)kSecValueRef]); + eq_cf((__bridge CFTypeRef)attrs[(id)kSecAttrTokenID], (__bridge CFTypeRef)tokenID1); + + // After removing token with key, getting identity from persistent reference must fail gracefully. + ok_status(result = SecItemUpdateTokenItemsForAccessGroups((__bridge CFStringRef)tokenID1, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], NULL)); + query = @{ (id)kSecValuePersistentRef: persRef, (id)kSecReturnRef: @YES }; + is_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&newRef), errSecItemNotFound); + + // Getting persistent reference to non-token item with token-like (but malformed) data must not crash. + NSData *data = CFBridgingRelease(CFPropertyListCreateDERData(kCFAllocatorDefault, (__bridge CFPropertyListRef)@[], NULL)); + query = @{ (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrLabel: @"probe", (id)kSecValueData: data}; + ok_status(result = SecItemAdd((__bridge CFDictionaryRef)query, NULL)); + NSDictionary *dict; + query = @{ (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrLabel: @"probe", (id)kSecReturnPersistentRef: @YES, (id)kSecReturnData: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&dict)); + NSData *newData; + query = @{ (id)kSecValuePersistentRef: dict[(id)kSecValuePersistentRef], (id)kSecReturnData: @YES }; + ok_status(result = SecItemCopyMatching((__bridge CFDictionaryRef)query, (void *)&newData)); + eq_cf((__bridge CFTypeRef)data, (__bridge CFTypeRef)newData); } } @@ -1093,7 +1211,7 @@ static void test_ies(SecKeyRef privateKey, SecKeyAlgorithm algorithm) { NSDictionary *params = @{ (id)kSecAttrKeyType : privateParams[(id)kSecAttrKeyType], (id)kSecAttrKeySizeInBits : privateParams[(id)kSecAttrKeySizeInBits], (id)kSecAttrTokenID : @"tid-ies", - (id)kSecPrivateKeyAttrs : @{ (id)kSecAttrIsPermanent : @YES } + (id)kSecPrivateKeyAttrs : @{ (id)kSecAttrIsPermanent : @NO } }; NSError *error; SecKeyRef tokenKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)params, (void *)&error); @@ -1165,7 +1283,12 @@ static void tests(void) { } int secd_33_keychain_ctk(int argc, char *const *argv) { - plan_tests(491); + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + plan_tests(539); + } else { + plan_tests(403); + } + tests(); return 0; diff --git a/keychain/securityd/Regressions/secd-36-ks-encrypt.m b/keychain/securityd/Regressions/secd-36-ks-encrypt.m index ff85cb8f..a6ef85be 100644 --- a/keychain/securityd/Regressions/secd-36-ks-encrypt.m +++ b/keychain/securityd/Regressions/secd-36-ks-encrypt.m @@ -24,6 +24,7 @@ #include "secd_regressions.h" +#import #include #include @@ -66,7 +67,8 @@ int secd_36_ks_encrypt(int argc, char *const *argv) ok(ac = SecAccessControlCreate(NULL, &error), "SecAccessControlCreate: %@", error); ok(SecAccessControlSetProtection(ac, kSecAttrAccessibleWhenUnlocked, &error), "SecAccessControlSetProtection: %@", error); - ret = ks_encrypt_data(keybag, ac, NULL, data, (__bridge CFDictionaryRef)@{@"persistref" : @"aaa-bbb-ccc"}, NULL, &enc, true, &error); + CFDictionaryRef empty = (__bridge CFDictionaryRef)@{}; + ret = ks_encrypt_data(keybag, ac, NULL, data, (__bridge CFDictionaryRef)@{@"persistref" : @"aaa-bbb-ccc"}, empty, &enc, true, &error); is(true, ret); CFReleaseNull(ac); @@ -75,7 +77,11 @@ int secd_36_ks_encrypt(int argc, char *const *argv) CFMutableDictionaryRef attributes = NULL; uint32_t version = 0; - ret = ks_decrypt_data(keybag, kAKSKeyOpDecrypt, &ac, NULL, enc, NULL, NULL, &attributes, &version, true, NULL, &error); + NSData* dummyACM = [NSData dataWithBytes:"dummy" length:5]; + const SecDbClass* class = kc_class_with_name(kSecClassGenericPassword); + NSArray* dummyArray = [NSArray array]; + + ret = ks_decrypt_data(keybag, kAKSKeyOpDecrypt, &ac, (__bridge CFDataRef _Nonnull)dummyACM, enc, class, (__bridge CFArrayRef)dummyArray, &attributes, &version, true, NULL, &error); is(true, ret, "ks_decrypt_data: %@", error); CFTypeRef aclProtection = ac ? SecAccessControlGetProtection(ac) : NULL; diff --git a/keychain/securityd/Regressions/secd-50-account.m b/keychain/securityd/Regressions/secd-50-account.m index 70ff2f44..fb815ea8 100644 --- a/keychain/securityd/Regressions/secd-50-account.m +++ b/keychain/securityd/Regressions/secd-50-account.m @@ -45,6 +45,8 @@ #include "SecdTestKeychainUtilities.h" #include "SOSAccountTesting.h" +#if SOS_ENABLED + static int kTestTestCount = 9 + kSecdTestSetupTestCount; static void tests(void) { @@ -96,6 +98,15 @@ static void tests(void) is([account getCircleStatus:&cfError], kSOSCCInCircle, "Still in Circle (%@)", error); CFReleaseNull(cfError); + SecKeyRef userKey = SOSAccountCopyStashedUserPrivateKey(account, &cfError); + ok(userKey, "retrieved userKey"); + CFReleaseNull(userKey); + + SecKeyRef deviceKey = SOSAccountCopyDevicePrivateKey(account, &cfError); + ok(deviceKey, "retrieved deviceKey"); + CFReleaseNull(deviceKey); + + CFReleaseNull(new_gestalt); SOSDataSourceFactoryRelease(test_factory); @@ -107,13 +118,16 @@ static void tests(void) SOSTestCleanup(); } +#endif + int secd_50_account(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-50-message.m b/keychain/securityd/Regressions/secd-50-message.m index 67f198c1..826b302d 100644 --- a/keychain/securityd/Regressions/secd-50-message.m +++ b/keychain/securityd/Regressions/secd-50-message.m @@ -31,6 +31,9 @@ #include #include "keychain/SecureObjectSync/SOSDigestVector.h" #include "keychain/securityd/SecDbItem.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED static void testNullMessage(uint64_t msgid) { @@ -241,12 +244,15 @@ static void tests(void) testFlaggedMessage(test_directive, test_reason, ++msgid, 0x865); testFlaggedMessage(test_directive, test_reason, ++msgid, 0xdeadbeef); } +#endif int secd_50_message(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(26); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-51-account-inflate.m b/keychain/securityd/Regressions/secd-51-account-inflate.m index 08ee55e8..272c93f0 100644 --- a/keychain/securityd/Regressions/secd-51-account-inflate.m +++ b/keychain/securityd/Regressions/secd-51-account-inflate.m @@ -46,158 +46,7 @@ #include "SOSAccountTesting.h" #include "SOSTransportTestTransports.h" -#if 0 -const uint8_t v6_der[] = { - 0x30, 0x82, 0x06, 0xee, 0x02, 0x01, 0x06, 0x31, 0x4e, 0x30, 0x11, 0x0c, - 0x09, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x0c, 0x04, - 0x69, 0x50, 0x61, 0x64, 0x30, 0x1b, 0x0c, 0x16, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x0c, - 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, - 0x65, 0x0c, 0x0c, 0x4d, 0x69, 0x74, 0x63, 0x68, 0x27, 0x73, 0x20, 0x69, - 0x50, 0x61, 0x64, 0x30, 0x82, 0x05, 0xe0, 0x30, 0x82, 0x05, 0xdc, 0x04, - 0x82, 0x04, 0x1c, 0x30, 0x82, 0x04, 0x18, 0x02, 0x01, 0x01, 0x0c, 0x02, - 0x61, 0x6b, 0x02, 0x08, 0x0d, 0x4f, 0xc4, 0x65, 0x00, 0x00, 0x00, 0x03, - 0x30, 0x82, 0x03, 0x2c, 0x30, 0x82, 0x01, 0xa2, 0x31, 0x82, 0x01, 0x56, - 0x30, 0x14, 0x0c, 0x0f, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x02, 0x01, 0x00, 0x30, 0x2b, - 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x44, 0x61, 0x74, 0x65, 0x04, 0x18, 0x18, 0x16, 0x32, 0x30, 0x31, - 0x35, 0x30, 0x32, 0x32, 0x36, 0x31, 0x37, 0x30, 0x30, 0x35, 0x39, 0x2e, - 0x39, 0x31, 0x35, 0x33, 0x35, 0x38, 0x5a, 0x30, 0x55, 0x0c, 0x10, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, - 0x4b, 0x65, 0x79, 0x04, 0x41, 0x04, 0xd9, 0x02, 0x0e, 0x16, 0x03, 0x13, - 0xfb, 0xf8, 0x29, 0xbf, 0x83, 0xbd, 0x6b, 0x5a, 0xc4, 0xf0, 0x47, 0x52, - 0xc7, 0x87, 0x81, 0xe9, 0xda, 0xe0, 0xb4, 0x8b, 0x06, 0x73, 0x23, 0x72, - 0xba, 0xba, 0xc4, 0x1a, 0x35, 0xa2, 0xc6, 0x46, 0x61, 0xc9, 0x08, 0x43, - 0x4f, 0x89, 0x08, 0x9d, 0xe1, 0xd5, 0x3d, 0x83, 0x49, 0xe3, 0x0c, 0x8e, - 0xfb, 0x33, 0x37, 0xd7, 0x6d, 0x03, 0xe0, 0x39, 0x11, 0xe1, 0x30, 0x59, - 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x55, 0x73, 0x69, 0x67, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x66, - 0x9e, 0xd0, 0x80, 0x11, 0xa4, 0x17, 0x94, 0x66, 0x5f, 0x75, 0xee, 0x65, - 0xbf, 0xd0, 0x49, 0x8f, 0xe6, 0x22, 0xf6, 0x3c, 0x2c, 0xdb, 0x46, 0xe5, - 0x3f, 0x4f, 0x85, 0xb9, 0x8a, 0x6c, 0x8a, 0x02, 0x20, 0x0a, 0x37, 0xf0, - 0xf1, 0x9f, 0x13, 0xfd, 0xae, 0x5f, 0xb7, 0xd0, 0xb4, 0x4a, 0x45, 0x02, - 0x8a, 0x2f, 0xdc, 0x8b, 0xd3, 0xfb, 0x09, 0xeb, 0xcf, 0x6b, 0x0b, 0x6b, - 0x18, 0x9c, 0xcf, 0x6c, 0x55, 0x30, 0x5f, 0x0c, 0x0d, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x47, 0x65, 0x73, 0x74, 0x61, 0x6c, 0x74, 0x31, 0x4e, - 0x30, 0x11, 0x0c, 0x09, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x61, 0x6d, - 0x65, 0x0c, 0x04, 0x69, 0x50, 0x61, 0x64, 0x30, 0x1b, 0x0c, 0x16, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x02, 0x01, 0x00, - 0x30, 0x1c, 0x0c, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x0c, 0x0c, 0x4d, 0x69, 0x74, 0x63, 0x68, 0x27, - 0x73, 0x20, 0x69, 0x50, 0x61, 0x64, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, - 0x72, 0x06, 0xdb, 0xf8, 0x06, 0xff, 0x7f, 0xac, 0xcf, 0xd2, 0xfb, 0x1e, - 0x86, 0x0d, 0x87, 0x4e, 0xb9, 0x1b, 0x26, 0x1e, 0x47, 0x4b, 0xfe, 0xd0, - 0x54, 0x0c, 0xdf, 0x88, 0x5a, 0x27, 0x92, 0x1d, 0x02, 0x20, 0x6b, 0xcf, - 0x7f, 0xb5, 0xfe, 0x19, 0x16, 0xd2, 0x7f, 0xb1, 0x7b, 0xad, 0xf5, 0xb9, - 0xea, 0x23, 0x69, 0x37, 0x19, 0x5e, 0xd3, 0x8c, 0x9e, 0x80, 0xef, 0xb5, - 0x65, 0x9a, 0xd5, 0x42, 0x51, 0x13, 0x30, 0x82, 0x01, 0x82, 0x31, 0x82, - 0x01, 0x35, 0x30, 0x12, 0x0c, 0x0d, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x01, 0x01, 0x01, 0x30, 0x14, - 0x0c, 0x0f, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x02, 0x01, 0x00, 0x30, 0x29, 0x0c, 0x0d, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x73, 0x74, 0x61, 0x6c, - 0x74, 0x31, 0x18, 0x30, 0x16, 0x0c, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x0c, 0x06, 0x69, 0x43, 0x6c, - 0x6f, 0x75, 0x64, 0x30, 0x2b, 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x65, 0x04, 0x18, - 0x18, 0x16, 0x32, 0x30, 0x31, 0x35, 0x30, 0x32, 0x32, 0x36, 0x31, 0x37, - 0x30, 0x30, 0x35, 0x39, 0x2e, 0x39, 0x36, 0x30, 0x38, 0x33, 0x35, 0x5a, - 0x30, 0x55, 0x0c, 0x10, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x53, 0x69, - 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x04, 0x41, 0x04, 0x53, - 0x1d, 0x77, 0x7c, 0x1b, 0x8a, 0x53, 0xad, 0x88, 0xdf, 0x56, 0xf9, 0x11, - 0xfd, 0x40, 0x69, 0x7c, 0x0b, 0xbb, 0x2a, 0xf7, 0x48, 0x7e, 0x69, 0x3d, - 0x0c, 0xfb, 0xc8, 0x90, 0x27, 0xb5, 0x18, 0x88, 0x09, 0x3f, 0x06, 0x37, - 0xca, 0x5d, 0x9c, 0x64, 0x34, 0x13, 0x89, 0x09, 0xe9, 0x0e, 0x99, 0xa3, - 0xc8, 0xc1, 0x86, 0xb3, 0x6e, 0x30, 0xf1, 0x20, 0x38, 0x78, 0x56, 0x40, - 0xf4, 0xd7, 0x36, 0x30, 0x5a, 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x69, 0x67, 0x04, 0x47, - 0x30, 0x45, 0x02, 0x20, 0x45, 0x47, 0xbf, 0x5b, 0x4d, 0x57, 0x77, 0x90, - 0x7b, 0x74, 0x90, 0x2f, 0x5d, 0x7b, 0x02, 0x3c, 0x21, 0xe8, 0x5c, 0x24, - 0x0c, 0x77, 0xd8, 0x19, 0xff, 0xce, 0x28, 0x45, 0x76, 0x50, 0xb1, 0xee, - 0x02, 0x21, 0x00, 0xe3, 0xea, 0x0f, 0xcb, 0x72, 0xd7, 0x88, 0x15, 0xa4, - 0x71, 0xbe, 0x9e, 0xa6, 0xf2, 0x9c, 0xa8, 0x9b, 0x93, 0xec, 0x31, 0x7a, - 0xe3, 0x92, 0x8a, 0xf2, 0x2f, 0xfd, 0x98, 0xc9, 0xe1, 0xc4, 0x7c, 0x04, - 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xce, 0x5f, 0x67, 0x9d, 0x78, 0x9f, - 0xc6, 0x3b, 0xb3, 0x51, 0xde, 0x6d, 0x9e, 0xff, 0xf5, 0xab, 0xda, 0xf4, - 0x7e, 0xb2, 0xe9, 0x1a, 0xf2, 0xd9, 0x0d, 0x48, 0x30, 0x07, 0xbc, 0x06, - 0xf5, 0x42, 0x02, 0x20, 0x64, 0x1d, 0x7d, 0x43, 0xc1, 0x3b, 0x50, 0xd6, - 0x7b, 0x3b, 0xce, 0x6f, 0xec, 0x23, 0x21, 0x8a, 0x9b, 0x06, 0x3f, 0x64, - 0xfe, 0xd6, 0x29, 0xaf, 0x5b, 0x0c, 0x69, 0x8f, 0x48, 0x88, 0x08, 0x1e, - 0x30, 0x00, 0x30, 0x00, 0x31, 0x81, 0xd0, 0x30, 0x66, 0x0c, 0x1a, 0x30, - 0x56, 0x4f, 0x73, 0x47, 0x76, 0x56, 0x72, 0x51, 0x46, 0x4e, 0x46, 0x6b, - 0x52, 0x35, 0x37, 0x71, 0x59, 0x73, 0x4c, 0x47, 0x6f, 0x33, 0x49, 0x50, - 0x51, 0x04, 0x48, 0x30, 0x46, 0x02, 0x21, 0x00, 0xf9, 0xc9, 0x69, 0xda, - 0x69, 0xe7, 0x32, 0xeb, 0x14, 0xc1, 0xbd, 0x56, 0xb7, 0x3e, 0xab, 0x08, - 0x6d, 0xe2, 0x16, 0xd9, 0x0a, 0xa8, 0x67, 0x7a, 0x56, 0xdc, 0x64, 0xf2, - 0x2f, 0x2e, 0xe8, 0xb9, 0x02, 0x21, 0x00, 0xac, 0x5c, 0x29, 0x80, 0x60, - 0x57, 0xd7, 0x51, 0x23, 0x1f, 0x00, 0x09, 0x70, 0xf3, 0xd5, 0x1a, 0x49, - 0xad, 0xaf, 0x35, 0x77, 0x07, 0xf4, 0x85, 0x1f, 0x63, 0xe0, 0xea, 0x67, - 0x36, 0xb5, 0x3b, 0x30, 0x66, 0x0c, 0x1a, 0x6e, 0x6b, 0x62, 0x77, 0x33, - 0x2f, 0x57, 0x72, 0x39, 0x4f, 0x33, 0x6a, 0x45, 0x68, 0x4f, 0x48, 0x46, - 0x67, 0x32, 0x34, 0x67, 0x62, 0x4d, 0x61, 0x6a, 0x76, 0x04, 0x48, 0x30, - 0x46, 0x02, 0x21, 0x00, 0x9f, 0x4f, 0x60, 0x2f, 0x54, 0x5e, 0x9f, 0x6a, - 0x7d, 0x37, 0xd9, 0x9f, 0x62, 0x69, 0xd7, 0x8c, 0xfc, 0xf5, 0x78, 0x54, - 0x7d, 0xb6, 0x91, 0x4b, 0x48, 0x88, 0x3d, 0x59, 0x05, 0x70, 0x09, 0xbf, - 0x02, 0x21, 0x00, 0xe2, 0xaf, 0xc9, 0x27, 0x12, 0xfa, 0x64, 0x51, 0x19, - 0x13, 0x1d, 0x57, 0x56, 0x6b, 0x93, 0xa3, 0xc6, 0x31, 0xf8, 0x70, 0x97, - 0x9e, 0x79, 0xf5, 0xc0, 0x2d, 0xf3, 0x3c, 0x8b, 0x86, 0x92, 0x28, 0x04, - 0x82, 0x01, 0xb8, 0x30, 0x82, 0x01, 0xb4, 0x30, 0x82, 0x01, 0xa2, 0x31, - 0x82, 0x01, 0x56, 0x30, 0x14, 0x0c, 0x0f, 0x43, 0x6f, 0x6e, 0x66, 0x6c, - 0x69, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x02, 0x01, - 0x00, 0x30, 0x2b, 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x65, 0x04, 0x18, 0x18, 0x16, - 0x32, 0x30, 0x31, 0x35, 0x30, 0x32, 0x32, 0x36, 0x31, 0x37, 0x30, 0x30, - 0x35, 0x39, 0x2e, 0x39, 0x31, 0x35, 0x33, 0x35, 0x38, 0x5a, 0x30, 0x55, - 0x0c, 0x10, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x53, 0x69, 0x67, 0x6e, - 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x04, 0x41, 0x04, 0xd9, 0x02, 0x0e, - 0x16, 0x03, 0x13, 0xfb, 0xf8, 0x29, 0xbf, 0x83, 0xbd, 0x6b, 0x5a, 0xc4, - 0xf0, 0x47, 0x52, 0xc7, 0x87, 0x81, 0xe9, 0xda, 0xe0, 0xb4, 0x8b, 0x06, - 0x73, 0x23, 0x72, 0xba, 0xba, 0xc4, 0x1a, 0x35, 0xa2, 0xc6, 0x46, 0x61, - 0xc9, 0x08, 0x43, 0x4f, 0x89, 0x08, 0x9d, 0xe1, 0xd5, 0x3d, 0x83, 0x49, - 0xe3, 0x0c, 0x8e, 0xfb, 0x33, 0x37, 0xd7, 0x6d, 0x03, 0xe0, 0x39, 0x11, - 0xe1, 0x30, 0x59, 0x0c, 0x0f, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x69, 0x67, 0x04, 0x46, 0x30, 0x44, - 0x02, 0x20, 0x66, 0x9e, 0xd0, 0x80, 0x11, 0xa4, 0x17, 0x94, 0x66, 0x5f, - 0x75, 0xee, 0x65, 0xbf, 0xd0, 0x49, 0x8f, 0xe6, 0x22, 0xf6, 0x3c, 0x2c, - 0xdb, 0x46, 0xe5, 0x3f, 0x4f, 0x85, 0xb9, 0x8a, 0x6c, 0x8a, 0x02, 0x20, - 0x0a, 0x37, 0xf0, 0xf1, 0x9f, 0x13, 0xfd, 0xae, 0x5f, 0xb7, 0xd0, 0xb4, - 0x4a, 0x45, 0x02, 0x8a, 0x2f, 0xdc, 0x8b, 0xd3, 0xfb, 0x09, 0xeb, 0xcf, - 0x6b, 0x0b, 0x6b, 0x18, 0x9c, 0xcf, 0x6c, 0x55, 0x30, 0x5f, 0x0c, 0x0d, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x73, 0x74, 0x61, 0x6c, - 0x74, 0x31, 0x4e, 0x30, 0x11, 0x0c, 0x09, 0x4d, 0x6f, 0x64, 0x65, 0x6c, - 0x4e, 0x61, 0x6d, 0x65, 0x0c, 0x04, 0x69, 0x50, 0x61, 0x64, 0x30, 0x1b, - 0x0c, 0x16, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x02, 0x01, 0x00, 0x30, 0x1c, 0x0c, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x0c, 0x0c, 0x4d, 0x69, 0x74, - 0x63, 0x68, 0x27, 0x73, 0x20, 0x69, 0x50, 0x61, 0x64, 0x04, 0x46, 0x30, - 0x44, 0x02, 0x20, 0x72, 0x06, 0xdb, 0xf8, 0x06, 0xff, 0x7f, 0xac, 0xcf, - 0xd2, 0xfb, 0x1e, 0x86, 0x0d, 0x87, 0x4e, 0xb9, 0x1b, 0x26, 0x1e, 0x47, - 0x4b, 0xfe, 0xd0, 0x54, 0x0c, 0xdf, 0x88, 0x5a, 0x27, 0x92, 0x1d, 0x02, - 0x20, 0x6b, 0xcf, 0x7f, 0xb5, 0xfe, 0x19, 0x16, 0xd2, 0x7f, 0xb1, 0x7b, - 0xad, 0xf5, 0xb9, 0xea, 0x23, 0x69, 0x37, 0x19, 0x5e, 0xd3, 0x8c, 0x9e, - 0x80, 0xef, 0xb5, 0x65, 0x9a, 0xd5, 0x42, 0x51, 0x13, 0x04, 0x0c, 0x6b, - 0x65, 0x79, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x41, 0x04, 0x78, 0xea, 0x03, 0x41, - 0x94, 0x6d, 0x46, 0x38, 0xde, 0x37, 0xe0, 0xb6, 0xc8, 0xfa, 0x94, 0x86, - 0xbe, 0xd5, 0x78, 0x08, 0x2f, 0x1f, 0x5e, 0xa4, 0x0c, 0x93, 0xc2, 0x5f, - 0x1e, 0xca, 0x05, 0x21, 0x51, 0xc2, 0xce, 0x7c, 0xcf, 0x58, 0x2f, 0x46, - 0x53, 0x7e, 0x49, 0x97, 0xb8, 0x06, 0x98, 0x9b, 0xe2, 0x12, 0xa9, 0x92, - 0xdd, 0x30, 0xe2, 0x4d, 0xd4, 0x32, 0x09, 0x62, 0x5f, 0xea, 0x0c, 0x0c, - 0x04, 0x41, 0x04, 0x78, 0xea, 0x03, 0x41, 0x94, 0x6d, 0x46, 0x38, 0xde, - 0x37, 0xe0, 0xb6, 0xc8, 0xfa, 0x94, 0x86, 0xbe, 0xd5, 0x78, 0x08, 0x2f, - 0x1f, 0x5e, 0xa4, 0x0c, 0x93, 0xc2, 0x5f, 0x1e, 0xca, 0x05, 0x21, 0x51, - 0xc2, 0xce, 0x7c, 0xcf, 0x58, 0x2f, 0x46, 0x53, 0x7e, 0x49, 0x97, 0xb8, - 0x06, 0x98, 0x9b, 0xe2, 0x12, 0xa9, 0x92, 0xdd, 0x30, 0xe2, 0x4d, 0xd4, - 0x32, 0x09, 0x62, 0x5f, 0xea, 0x0c, 0x0c, 0x04, 0x27, 0x30, 0x25, 0x04, - 0x10, 0x48, 0xd4, 0x7b, 0x6a, 0x50, 0xfb, 0x84, 0xf8, 0xb5, 0x8d, 0x13, - 0x62, 0xcc, 0x42, 0xa5, 0x42, 0x02, 0x03, 0x00, 0xc3, 0x50, 0x02, 0x02, - 0x01, 0x00, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x07, - 0x31, 0x00 }; -#endif +#if SOS_ENABLED #define kCompatibilityTestCount 0 #if 0 @@ -252,16 +101,18 @@ static void tests(void) SOSDataSourceRelease(test_source, NULL); } +#endif + int secd_51_account_inflate(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount + kCompatibilityTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); secd_test_clear_testviews(); tests(); - - /* we can't re-inflate the v6 DER since we don't have a viable private key for it. */ - // test_v6(); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-52-account-changed.m b/keychain/securityd/Regressions/secd-52-account-changed.m index 37b1cf8b..418d208b 100644 --- a/keychain/securityd/Regressions/secd-52-account-changed.m +++ b/keychain/securityd/Regressions/secd-52-account-changed.m @@ -46,6 +46,7 @@ #include "SecdTestKeychainUtilities.h" #include "SOSAccountTesting.h" +#if SOS_ENABLED static void tests(void) { @@ -201,15 +202,16 @@ static void tests(void) SOSTestCleanup(); } - +#endif int secd_52_account_changed(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(113); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-52-offering-gencount-reset.m b/keychain/securityd/Regressions/secd-52-offering-gencount-reset.m index bb2f6a74..a33f138c 100644 --- a/keychain/securityd/Regressions/secd-52-offering-gencount-reset.m +++ b/keychain/securityd/Regressions/secd-52-offering-gencount-reset.m @@ -52,6 +52,7 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void tests(void) { @@ -128,7 +129,7 @@ static void tests(void) SOSCircleSetGeneration(carolTrust.trustedCircle, gencount); - SecKeyRef user_privkey = SOSUserKeygen(cfpassword, (__bridge CFDataRef)(carol_account.accountKeyDerivationParamters), &error); + SecKeyRef user_privkey = SOSUserKeygen(cfpassword, (__bridge CFDataRef)(carol_account.accountKeyDerivationParameters), &error); CFNumberRef genCountTest = SOSCircleGetGeneration(carolTrust.trustedCircle); CFIndex testPtr; CFNumberGetValue(genCountTest, kCFNumberCFIndexType, &testPtr); @@ -158,7 +159,11 @@ static void tests(void) is([alice_account getCircleStatus:&error],kSOSCCNotInCircle,"alice is not in the account (%@)", error); is([bob_account getCircleStatus:&error], kSOSCCNotInCircle,"bob is not in the account (%@)", error); is([carol_account getCircleStatus:&error], kSOSCCInCircle,"carol is in the account (%@)", error); - + secLogEnable(); + [carol_account iCloudIdentityStatus:^(NSData *json, NSError *error) { + diag("icloud identity JSON\n%s\n", [[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding] UTF8String]); + }]; + secLogDisable(); CFReleaseNull(gencount); CFReleaseNull(cfpassword); CFReleaseNull(user_privkey); @@ -168,14 +173,16 @@ static void tests(void) SOSTestCleanup(); } +#endif int secd_52_offering_gencount_reset(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(63); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-55-account-circle.m b/keychain/securityd/Regressions/secd-55-account-circle.m index b11e1d31..aed491b3 100644 --- a/keychain/securityd/Regressions/secd-55-account-circle.m +++ b/keychain/securityd/Regressions/secd-55-account-circle.m @@ -53,6 +53,8 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + static int kTestTestCount = 257; static void tests(void) @@ -325,7 +327,7 @@ static void tests(void) carol_account.peerInfo, NULL); - ok(SOSAccountRemovePeersFromCircle(bob_account, peers_to_remove_array, nil, NULL)); + ok(SOSAccountRemovePeersFromCircle(bob_account, peers_to_remove_array, NULL)); is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 4, "Remove peers"); @@ -343,14 +345,16 @@ static void tests(void) SOSTestCleanup(); } +#endif int secd_55_account_circle(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-55-account-incompatibility.m b/keychain/securityd/Regressions/secd-55-account-incompatibility.m index da6aabca..1d32bfe9 100644 --- a/keychain/securityd/Regressions/secd-55-account-incompatibility.m +++ b/keychain/securityd/Regressions/secd-55-account-incompatibility.m @@ -53,6 +53,8 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + static int kTestTestCount = 10; static void tests(void) @@ -101,14 +103,16 @@ static void tests(void) carol_account = nil; SOSTestCleanup(); } +#endif int secd_55_account_incompatibility(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-56-account-apply.m b/keychain/securityd/Regressions/secd-56-account-apply.m index 50748a08..28a6caa9 100644 --- a/keychain/securityd/Regressions/secd-56-account-apply.m +++ b/keychain/securityd/Regressions/secd-56-account-apply.m @@ -51,6 +51,8 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + #define kAccountPasswordString ((uint8_t*) "FooFooFoo") #define kAccountPasswordStringLen 10 @@ -209,14 +211,16 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_56_account_apply(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(181); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-57-1-account-last-standing.m b/keychain/securityd/Regressions/secd-57-1-account-last-standing.m index d455b327..f4193371 100644 --- a/keychain/securityd/Regressions/secd-57-1-account-last-standing.m +++ b/keychain/securityd/Regressions/secd-57-1-account-last-standing.m @@ -55,7 +55,9 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" +#if SOS_ENABLED static bool acceptApplicants(SOSAccount* account, CFIndex count) { bool retval = false; @@ -148,14 +150,16 @@ static void tests(void) alice_account = nil; SOSTestCleanup(); } +#endif int secd_57_1_account_last_standing(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(45); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-57-account-leave.m b/keychain/securityd/Regressions/secd-57-account-leave.m index 6e1710d1..f21450ed 100644 --- a/keychain/securityd/Regressions/secd-57-account-leave.m +++ b/keychain/securityd/Regressions/secd-57-account-leave.m @@ -52,6 +52,8 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + /* static void trim_retirements_from_circle(SOSAccount* account) { @@ -250,14 +252,17 @@ static void tests(void) SOSTestCleanup(); } +#endif + int secd_57_account_leave(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(191); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); secd_test_clear_testviews(); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-58-password-change.m b/keychain/securityd/Regressions/secd-58-password-change.m index db6ff25c..a915156a 100644 --- a/keychain/securityd/Regressions/secd-58-password-change.m +++ b/keychain/securityd/Regressions/secd-58-password-change.m @@ -50,6 +50,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static bool AssertCreds(SOSAccount* account,CFStringRef acct_name, CFDataRef password) { CFErrorRef error = NULL; @@ -59,15 +60,6 @@ static bool AssertCreds(SOSAccount* account,CFStringRef acct_name, CFDataRef pas return retval; } -static inline bool SOSAccountEvaluateKeysAndCircle_wTxn(SOSAccount* acct, CFErrorRef* error) -{ - __block bool result = false; - [acct performTransaction:^(SOSAccountTransaction * _Nonnull txn) { - result = SOSAccountEvaluateKeysAndCircle(txn, NULL); - }]; - return result; -} - static bool ResetToOffering(SOSAccount* account) { CFErrorRef error = NULL; bool retval; @@ -245,14 +237,16 @@ static void tests(void) david_account = nil; SOSTestCleanup(); } +#endif int secd_58_password_change(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(211); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-59-account-cleanup.m b/keychain/securityd/Regressions/secd-59-account-cleanup.m index dcdb0699..29192cf2 100644 --- a/keychain/securityd/Regressions/secd-59-account-cleanup.m +++ b/keychain/securityd/Regressions/secd-59-account-cleanup.m @@ -52,6 +52,7 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void tests(void) { @@ -146,14 +147,16 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_59_account_cleanup(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(91); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-60-account-cloud-identity.m b/keychain/securityd/Regressions/secd-60-account-cloud-identity.m index 3fbb31d2..d39069c6 100644 --- a/keychain/securityd/Regressions/secd-60-account-cloud-identity.m +++ b/keychain/securityd/Regressions/secd-60-account-cloud-identity.m @@ -51,6 +51,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static bool purgeICloudIdentity(SOSAccount* account) { @@ -283,14 +284,16 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_60_account_cloud_identity(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(159); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.m b/keychain/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.m index ac6b75c1..75f33af0 100644 --- a/keychain/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.m +++ b/keychain/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.m @@ -51,6 +51,8 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + /* static void trim_retirements_from_circle(SOSAccount* account) { SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { @@ -178,13 +180,16 @@ static void tests(void) SOSTestCleanup(); } +#endif + int secd_61_account_leave_not_in_kansas_anymore(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(82); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-62-account-backup.m b/keychain/securityd/Regressions/secd-62-account-backup.m index 41934fda..9f685164 100644 --- a/keychain/securityd/Regressions/secd-62-account-backup.m +++ b/keychain/securityd/Regressions/secd-62-account-backup.m @@ -53,12 +53,10 @@ #include "keychain/securityd/SOSCloudCircleServer.h" -#if !TARGET_OS_SIMULATOR + #include "SOSAccountTesting.h" -#endif #include "SecdTestKeychainUtilities.h" - -#if !TARGET_OS_SIMULATOR +#if SOS_ENABLED static CFDataRef CopyBackupKeyForString(CFStringRef string, CFErrorRef *error) { @@ -68,12 +66,9 @@ static CFDataRef CopyBackupKeyForString(CFStringRef string, CFErrorRef *error) }); return result; } -#endif static void tests(void) { -#if !TARGET_OS_SIMULATOR - __block CFErrorRef error = NULL; CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); CFStringRef cfaccount = CFSTR("test@test.org"); @@ -156,7 +151,7 @@ static void tests(void) ok([bob_account.trust checkForRings:&error], "Alice_account is good"); CFReleaseNull(error); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 5, "updates"); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 4, "updates"); ok([alice_account.trust checkForRings:&error], "Alice_account is good"); @@ -248,22 +243,18 @@ static void tests(void) alice_account = nil; bob_account = nil; SOSTestCleanup(); -#endif - } +#endif int secd_62_account_backup(int argc, char *const *argv) { -#if !TARGET_OS_SIMULATOR +#if SOS_ENABLED plan_tests(98); -#else - plan_tests(1); -#endif - secd_test_setup_temp_keychain(__FUNCTION__, NULL); secd_test_setup_testviews(); // for running this test solo - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-63-account-resurrection.m b/keychain/securityd/Regressions/secd-63-account-resurrection.m index 5e0ef6d0..5aa3b963 100644 --- a/keychain/securityd/Regressions/secd-63-account-resurrection.m +++ b/keychain/securityd/Regressions/secd-63-account-resurrection.m @@ -51,6 +51,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED typedef void (^stir_block)(int expected_iterations); @@ -198,14 +199,16 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_63_account_resurrection(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(73); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-64-circlereset.m b/keychain/securityd/Regressions/secd-64-circlereset.m index 6c905c29..ecee45c0 100644 --- a/keychain/securityd/Regressions/secd-64-circlereset.m +++ b/keychain/securityd/Regressions/secd-64-circlereset.m @@ -35,6 +35,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static int64_t getCurrentGenCount(SOSAccount* account) { SOSAccountTrustClassic* trust = account.trust; @@ -131,14 +132,16 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_64_circlereset(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(35); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-65-account-retirement-reset.m b/keychain/securityd/Regressions/secd-65-account-retirement-reset.m index 5db81a50..6a2f4a4c 100644 --- a/keychain/securityd/Regressions/secd-65-account-retirement-reset.m +++ b/keychain/securityd/Regressions/secd-65-account-retirement-reset.m @@ -52,6 +52,7 @@ #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED typedef void (^stir_block)(int expected_iterations); typedef int (^execute_block)(void); @@ -171,14 +172,16 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_65_account_retirement_reset(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(28); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-66-account-recovery.m b/keychain/securityd/Regressions/secd-66-account-recovery.m index 57ffd281..2d7a5ad5 100644 --- a/keychain/securityd/Regressions/secd-66-account-recovery.m +++ b/keychain/securityd/Regressions/secd-66-account-recovery.m @@ -62,15 +62,7 @@ #include "keychain/securityd/SOSCloudCircleServer.h" #include "SecdTestKeychainUtilities.h" -#if TARGET_OS_SIMULATOR - -int secd_66_account_recovery(int argc, char *const *argv) { - plan_tests(1); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - return 0; -} - -#else +#if SOS_ENABLED #include "SOSAccountTesting.h" @@ -346,16 +338,16 @@ static void tests(bool recKeyFirst) SOSTestCleanup(); } +#endif int secd_66_account_recovery(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(281); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(true); tests(false); - +#else + plan_tests(0); +#endif return 0; } - -#endif diff --git a/keychain/securityd/Regressions/secd-668-ghosts.m b/keychain/securityd/Regressions/secd-668-ghosts.m deleted file mode 100644 index 957c30ae..00000000 --- a/keychain/securityd/Regressions/secd-668-ghosts.m +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2012-2016 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@ - */ - -// -// secd-668-ghosts.c -// sec -// - -#include -#include - -#include "keychain/SecureObjectSync/SOSAccount.h" -#include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" - -#include "secd_regressions.h" -#include "SOSAccountTesting.h" -#include "SecdTestKeychainUtilities.h" - -/* - Make a circle with two peers - alice and bob(bob is iOS and serial#"abababababab") - have alice leave the circle - release bob, make a new bob - iOS and same serial number - try to join the circle - it should resetToOffering with ghost fix - - For phase 1 we expect the ghostfix to work with iOS devices, but not with MacOSX devices. - */ - -#if 0 -static void hauntedCircle(SOSPeerInfoDeviceClass devClass, bool expectGhostBusted) -{ - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - CFStringRef ghostSerialID = CFSTR("abababababab"); - CFStringRef ghostIdsID = CFSTR("targetIDS"); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - SOSAccount* alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), CFSTR("TestSource")); - SOSAccount* bob_account = SOSTestCreateAccountAsSerialClone(CFSTR("Bob"), devClass, ghostSerialID, ghostIdsID); - - // Start Circle - ok(SOSTestStartCircleWithAccount(alice_account, changes, cfaccount, cfpassword), "Have Alice start a circle"); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); - ok(SOSTestJoinWithApproval(cfpassword, cfaccount, changes, alice_account, bob_account, KEEP_USERKEY, 2, false), "Bob Joins"); - - // Alice Leaves - ok( [alice_account.trust leaveCircle:alice_account err:&error], "Alice Leaves (%@)", error); - CFReleaseNull(error); - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); - accounts_agree("Alice bails", bob_account, alice_account); - is(countPeers(bob_account), 1, "There should only be 1 valid peer"); - // We're dropping all peers that are in the circle - leaving a circle with only one peer - and that's a ghost - - // Make new bob - same as the old bob except peerID - - SOSAccount* bobFinal = SOSTestCreateAccountAsSerialClone(CFSTR("BobFinal"), devClass, ghostSerialID, ghostIdsID); - is(ProcessChangesUntilNoChange(changes, bobFinal, NULL), 1, "updates"); - - ok(SOSTestJoinWith(cfpassword, cfaccount, changes, bobFinal), "Application Made"); - CFReleaseNull(cfpassword); - - // Did ghostbuster work? - is(ProcessChangesUntilNoChange(changes, bobFinal, NULL), 2, "updates"); - if(expectGhostBusted) { // ghostbusting is currently disabled for MacOSX Peers - ok([bobFinal isInCircle:NULL], "Bob is in"); - } else { - ok(![bobFinal isInCircle:NULL], "Bob is not in"); - } - - is(countPeers(bobFinal), 1, "There should only be 1 valid peer"); - - CFReleaseNull(changes); - - bob_account = nil; - alice_account = nil; - bobFinal = nil; - SOSTestCleanup(); -} - -static void multiBob(SOSPeerInfoDeviceClass devClass, bool expectGhostBusted, bool delayedPrivKey, bool pairJoin) { - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - CFStringRef ghostSerialID = CFSTR("abababababab"); - CFStringRef ghostIdsID = CFSTR("targetIDS"); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - SOSAccount* alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), CFSTR("TestSource")); - - // Start Circle - ok(SOSAccountAssertUserCredentialsAndUpdate(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - is(ProcessChangesUntilNoChange(changes, alice_account, NULL), 1, "updates"); - - ok(SOSAccountResetToOffering_wTxn(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - is(ProcessChangesUntilNoChange(changes, alice_account, NULL), 1, "updates"); - - SOSTestMakeGhostInCircle(CFSTR("Bob1"), devClass, ghostSerialID, ghostIdsID, cfpassword, cfaccount, changes, alice_account, 2); - SOSTestMakeGhostInCircle(CFSTR("Bob2"), devClass, ghostSerialID, ghostIdsID, cfpassword, cfaccount, changes, alice_account, 3); - SOSTestMakeGhostInCircle(CFSTR("Bob3"), devClass, ghostSerialID, ghostIdsID, cfpassword, cfaccount, changes, alice_account, 4); - SOSTestMakeGhostInCircle(CFSTR("Bob4"), devClass, ghostSerialID, ghostIdsID, cfpassword, cfaccount, changes, alice_account, 5); - - SOSAccount* bobFinal_account = SOSTestCreateAccountAsSerialClone(CFSTR("BobFinal"), devClass, ghostSerialID, ghostIdsID); - - if(pairJoin) { - SOSTestJoinThroughPiggyBack(cfpassword, cfaccount, changes, alice_account, bobFinal_account, KEEP_USERKEY, 6, true); - is(countPeers(bobFinal_account), 6, "Expect ghosts still in circle"); - } else if(delayedPrivKey) { - SOSTestJoinWithApproval(cfpassword, cfaccount, changes, alice_account, bobFinal_account, DROP_USERKEY, 6, true); - is(countPeers(bobFinal_account), 6, "Expect ghosts still in circle"); - } else { - SOSTestJoinWithApproval(cfpassword, cfaccount, changes, alice_account, bobFinal_account, KEEP_USERKEY, 2, true); - } - - if(pairJoin || delayedPrivKey) { // this allows the ghostbusting to be done in a delayed fashion for the instances where that is proper - SOSAccountTryUserCredentials(bobFinal_account, cfaccount, cfpassword, &error); - ok(SOSTestChangeAccountDeviceName(bobFinal_account, CFSTR("ThereCanBeOnlyOneBob")), "force an unrelated circle change"); - is(ProcessChangesUntilNoChange(changes, alice_account, bobFinal_account, NULL), 3, "updates"); - } - - CFReleaseNull(cfpassword); - - - ok([bobFinal_account isInCircle:NULL], "bobFinal_account is in"); - - is(countPeers(bobFinal_account), 2, "Expect ghostBobs to be gone"); - is(countPeers(alice_account), 2, "Expect ghostBobs to be gone"); - accounts_agree_internal("Alice and ThereCanBeOnlyOneBob are the only circle peers and they agree", alice_account, bobFinal_account, false); - - CFReleaseNull(changes); - - alice_account = nil; - bobFinal_account = nil; - - SOSTestCleanup(); -} - -static void iosICloudIdentity() { - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - CFStringRef ghostIdsID = CFSTR("targetIDS"); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - SOSAccount* alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), CFSTR("TestSource")); - - // Start Circle - ok(SOSTestStartCircleWithAccount(alice_account, changes, cfaccount, cfpassword), "Have Alice start a circle"); - - SOSCircleRef circle = [alice_account.trust getCircle:NULL]; - __block CFStringRef serial = NULL; - SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { - if(SOSPeerInfoIsCloudIdentity(peer)) { - serial = SOSPeerInfoCopySerialNumber(peer); - } - }); - - SOSAccount* bob_account = SOSTestCreateAccountAsSerialClone(CFSTR("Bob"), SOSPeerInfo_iOS, serial, ghostIdsID); - - is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); - ok(SOSTestJoinWithApproval(cfpassword, cfaccount, changes, alice_account, bob_account, KEEP_USERKEY, 2, false), "Bob Joins"); - CFReleaseNull(cfpassword); - - circle = [alice_account.trust getCircle:&error]; - __block bool hasiCloudIdentity = false; - SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { - if(SOSPeerInfoIsCloudIdentity(peer)) { - hasiCloudIdentity = true; - } - }); - - ok(hasiCloudIdentity, "GhostBusting didn't mess with the iCloud Identity"); - - CFReleaseNull(changes); - alice_account = nil; - SOSTestCleanup(); -} -#endif // 0 - -int secd_68_ghosts(int argc, char *const *argv) -{ - plan_tests(1); - - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - -#if 0 - // changing ghostbusting. handleUpdateCircle version is going away. - hauntedCircle(SOSPeerInfo_iOS, true); - hauntedCircle(SOSPeerInfo_macOS, false); - multiBob(SOSPeerInfo_iOS, true, false, false); - multiBob(SOSPeerInfo_iOS, false, true, false); - multiBob(SOSPeerInfo_iOS, false, false, true); // piggyback join case - - iosICloudIdentity(); -#endif - return 0; -} diff --git a/keychain/securityd/Regressions/secd-67-prefixedKeyIDs.m b/keychain/securityd/Regressions/secd-67-prefixedKeyIDs.m index 93809dfd..b4de05d8 100644 --- a/keychain/securityd/Regressions/secd-67-prefixedKeyIDs.m +++ b/keychain/securityd/Regressions/secd-67-prefixedKeyIDs.m @@ -61,6 +61,8 @@ #include "SOSAccountTesting.h" +#if SOS_ENABLED + static void tests() { CFErrorRef error = NULL; int keySizeInBits = 256; @@ -119,11 +121,15 @@ static void tests() { } +#endif int secd_67_prefixedKeyIDs(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(12); - tests(); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-68-fullPeerInfoIntegrity.m b/keychain/securityd/Regressions/secd-68-fullPeerInfoIntegrity.m new file mode 100644 index 00000000..542307c9 --- /dev/null +++ b/keychain/securityd/Regressions/secd-68-fullPeerInfoIntegrity.m @@ -0,0 +1,121 @@ +// +// secd-68-fullPeerInfoIntegrity.m +// secdRegressions +// +// Created by Richard Murphy on 4/30/20. +// + +#import + +#include +#include + +#include + +#include "keychain/SecureObjectSync/SOSAccount.h" +#include +#include "keychain/SecureObjectSync/SOSInternal.h" +#include "keychain/SecureObjectSync/SOSUserKeygen.h" +#include "keychain/SecureObjectSync/SOSTransport.h" +#include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include "keychain/securityd/SOSCloudCircleServer.h" + +#include "SOSAccountTesting.h" + +#include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED + +static NSString *makeCircle(SOSAccount* testaccount, CFMutableDictionaryRef changes) { + CFErrorRef error = NULL; + + // Every time we resetToOffering should result in a new fpi + NSString *lastPeerID = testaccount.peerID; + ok(SOSAccountResetToOffering_wTxn(testaccount, &error), "Reset to offering (%@)", error); + CFReleaseNull(error); + is(ProcessChangesUntilNoChange(changes, testaccount, NULL), 1, "updates"); + NSString *currentPeerID = testaccount.peerID; + ok(![lastPeerID isEqualToString:currentPeerID], "peerID changed on circle reset"); + return currentPeerID; +} + +static void tests(void) { + CFErrorRef error = NULL; + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + CFStringRef cfaccount = CFSTR("test@test.org"); + + CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + SOSAccount* testaccount = CreateAccountForLocalChanges(CFSTR("TestDev"), CFSTR("TestSource")); + + // Just making an account object to mess with + ok(SOSAccountAssertUserCredentialsAndUpdate(testaccount, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + is(ProcessChangesUntilNoChange(changes, testaccount, NULL), 1, "updates"); + CFReleaseNull(error); + + // make a circle then make sure fpi isn't reset just for a normal ensureFullPeerAvailable + NSString *lastPeerID = makeCircle(testaccount, changes); + ok([testaccount.trust ensureFullPeerAvailable:testaccount err:&error], "fullPeer is available"); + NSString *currentPeerID = testaccount.peerID; + ok([lastPeerID isEqualToString: currentPeerID], "peerID did not alter in trip through ensureFullPeerAvailable"); + + + // leaving a circle should reset the fpi + lastPeerID = makeCircle(testaccount, changes); + ok([testaccount.trust leaveCircle:testaccount err:&error], "leave the circle %@", error); + CFReleaseNull(error); + is(ProcessChangesUntilNoChange(changes, testaccount, NULL), 1, "updates"); + currentPeerID = testaccount.peerID; + ok(![lastPeerID isEqualToString:currentPeerID], "peerID changed on leaving circle"); + + // break the fullpeerinfo by purging the private key - then fix in ensureFullPeerAvailable + lastPeerID = makeCircle(testaccount, changes); + ok(SOSFullPeerInfoPurgePersistentKey(testaccount.fullPeerInfo, &error), "purging persistent key %@", error); + currentPeerID = testaccount.peerID; + ok([lastPeerID isEqualToString:currentPeerID], "pre-ensuring peerID remains the same"); + lastPeerID = currentPeerID; + ok([testaccount.trust ensureFullPeerAvailable:testaccount err:&error], "fullPeer is available"); + currentPeerID = testaccount.peerID; + ok(![lastPeerID isEqualToString: currentPeerID], "peerID changed because fullPeerInfo fixed in ensureFullPeerAvailable"); + lastPeerID = currentPeerID; + + // If that last thing worked this peer won't be in the circle any more - changing fpi changes "me" + ok(SOSAccountAssertUserCredentialsAndUpdate(testaccount, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + is(ProcessChangesUntilNoChange(changes, testaccount, NULL), 1, "updates"); + CFReleaseNull(error); + ok(![testaccount isInCircle: &error], "No longer in circle"); + + // This join should work because the peer we left in the circle will be a ghost and there are no other peers + ok(SOSAccountJoinCircles_wTxn(testaccount, &error), "Apply to circle (%@)", error); + CFReleaseNull(error); + is(ProcessChangesUntilNoChange(changes, testaccount, NULL), 1, "updates"); + ok([testaccount isInCircle: &error], "Is in circle"); + currentPeerID = testaccount.peerID; + ok(![lastPeerID isEqualToString: currentPeerID], "peerID changed because fullPeerInfo changed during join"); + + CFReleaseNull(cfpassword); + testaccount = nil; + SOSTestCleanup(); +} +#endif + +int secd_68_fullPeerInfoIntegrity(int argc, char *const *argv) +{ +#if SOS_ENABLED + plan_tests(29); + secd_test_setup_temp_keychain(__FUNCTION__, NULL); + tests(); +#else + plan_tests(0); +#endif + return 0; +} diff --git a/keychain/securityd/Regressions/secd-70-engine-corrupt.m b/keychain/securityd/Regressions/secd-70-engine-corrupt.m index a229bcaa..6a84024c 100644 --- a/keychain/securityd/Regressions/secd-70-engine-corrupt.m +++ b/keychain/securityd/Regressions/secd-70-engine-corrupt.m @@ -42,9 +42,11 @@ #include #include #include +#include "SOSAccountTesting.h" #include #include +#if SOS_ENABLED static int kTestTestCount = 121; @@ -242,23 +244,23 @@ TODO: { }, CFSTR("Alice"), CFSTR("Bob"), NULL); } } +#endif int secd_70_engine_corrupt(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - __security_simulatecrash_enable(false); - /* custom keychain dir */ secd_test_setup_temp_keychain(__FUNCTION__, NULL); - nosha1(); drop_item(); drop_manifest(); add_sha1(); change_sha1(); - __security_simulatecrash_enable(true); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-70-engine-smash.m b/keychain/securityd/Regressions/secd-70-engine-smash.m index 62be20d5..f7287f1c 100644 --- a/keychain/securityd/Regressions/secd-70-engine-smash.m +++ b/keychain/securityd/Regressions/secd-70-engine-smash.m @@ -25,6 +25,9 @@ #include "keychain/SecureObjectSync/Regressions/SOSTestDevice.h" #include "secd_regressions.h" #include "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED static int kTestTestCount = 581; @@ -48,15 +51,17 @@ static void smash(void) { return false; }, CFSTR("alice"), CFSTR("bob"), NULL); } +#endif int secd_70_engine_smash(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - /* custom keychain dir */ secd_test_setup_temp_keychain(__FUNCTION__, NULL); - smash(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-70-engine.m b/keychain/securityd/Regressions/secd-70-engine.m index 87ac71fd..e3c9d658 100644 --- a/keychain/securityd/Regressions/secd-70-engine.m +++ b/keychain/securityd/Regressions/secd-70-engine.m @@ -43,43 +43,9 @@ #include #include +#include "SOSAccountTesting.h" -__unused static bool SOSCircleHandleCircleWithLock(SOSEngineRef engine, CFStringRef myID, CFDataRef message, CFErrorRef *error) { - - CFMutableArrayRef trustedPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - CFMutableArrayRef untrustedPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - CFStringRef peerID = NULL; - const uint8_t expected[20] = { 0xea, 0x6c, 0x01, 0x4d, - 0xc7, 0x2d, 0x6f, 0x8c, - 0xcd, 0x1e, 0xd9, 0x2a, - 0xce, 0x1d, 0x41, 0xf0, - 0xd8, 0xde, 0x89, 0x57 }; - - const char resultSize = sizeof(expected); - - CFDataRef coder = CFDataCreate(kCFAllocatorDefault, expected, resultSize); - CFArrayForEachC(SOSEngineGetPeerIDs(engine), peerID){ - CFArrayAppendValue(trustedPeers, peerID); - }; - CFReleaseNull(coder); - - CFShow(trustedPeers); - // all trusted - SOSEngineCircleChanged(engine, myID,trustedPeers, untrustedPeers); - - // make first peer untrusted - peerID = (CFStringRef)CFArrayGetValueAtIndex(trustedPeers, 0); - CFArrayAppendValue(untrustedPeers, peerID); - CFArrayRemoveAllValue(trustedPeers, peerID); - //we should see peerState cleared out except for the coder! - SOSEngineCircleChanged(engine, myID, trustedPeers, untrustedPeers); - - CFArrayAppendValue(trustedPeers, peerID); - CFArrayRemoveAllValue(untrustedPeers, peerID); - - - return true; -} +#if SOS_ENABLED static void testsync3(const char *name, const char *test_directive, const char *test_reason) { __block int iteration=0; @@ -163,8 +129,6 @@ static void testsync(const char *name, const char *test_directive, const char * } } CFReleaseSafe(messageDigestStr); - //SOSCircleHandleCircleWithLock(source->ds->engine, SOSEngineGetMyID(source->ds->engine), CFDataCreate(kCFAllocatorDefault, 0, 0), NULL); - } return false; }, CFSTR("alice"), CFSTR("bob"), NULL); @@ -503,15 +467,17 @@ SKIP: testsyncmany("v2syncmany", test_directive, test_reason, 9, 10, 2, syncmany_add); testsync2p(); } +#endif int secd_70_engine(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(1172); - /* custom keychain dir */ secd_test_setup_temp_keychain(__FUNCTION__, NULL); - synctests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-70-otr-remote.m b/keychain/securityd/Regressions/secd-70-otr-remote.m index 88735ab4..d391742c 100644 --- a/keychain/securityd/Regressions/secd-70-otr-remote.m +++ b/keychain/securityd/Regressions/secd-70-otr-remote.m @@ -48,6 +48,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void RegressionsLogError(CFErrorRef error) { @@ -180,14 +181,16 @@ static void tests(void) CFReleaseNull(bobSideSession); CFReleaseNull(testError); } +#endif int secd_70_otr_remote(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-71-engine-save.m b/keychain/securityd/Regressions/secd-71-engine-save.m index 1f9eabf1..5c7f8efa 100644 --- a/keychain/securityd/Regressions/secd-71-engine-save.m +++ b/keychain/securityd/Regressions/secd-71-engine-save.m @@ -40,9 +40,11 @@ #include #include #include +#include "SOSAccountTesting.h" #include #include +#if SOS_ENABLED static int kTestTestCount = 8; @@ -180,12 +182,15 @@ static void testSaveRestore(void) { CFReleaseSafe(testDevices); CFReleaseSafe(error); } - +#endif + int secd_71_engine_save(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - testSaveRestore(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-74-engine-beer-servers.m b/keychain/securityd/Regressions/secd-74-engine-beer-servers.m index d814afdf..8ed3a5a6 100644 --- a/keychain/securityd/Regressions/secd-74-engine-beer-servers.m +++ b/keychain/securityd/Regressions/secd-74-engine-beer-servers.m @@ -25,6 +25,9 @@ #include "keychain/SecureObjectSync/Regressions/SOSTestDevice.h" #include "secd_regressions.h" #include "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED static int kTestTestCount = 646; @@ -79,15 +82,17 @@ static void beer_servers(void) { CFRelease(objectNames); CFRelease(itemData); } +#endif int secd_74_engine_beer_servers(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - /* custom keychain dir */ secd_test_setup_temp_keychain(__FUNCTION__, NULL); - beer_servers(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-75-engine-views.m b/keychain/securityd/Regressions/secd-75-engine-views.m index 6e65d3c3..10c50ff1 100644 --- a/keychain/securityd/Regressions/secd-75-engine-views.m +++ b/keychain/securityd/Regressions/secd-75-engine-views.m @@ -27,6 +27,9 @@ #include "SecdTestKeychainUtilities.h" #include #include "keychain/SecureObjectSync/SOSPeer.h" +#include "SOSAccountTesting.h" + +#if SOS_ENABLED static int kTestTestCount = 53; @@ -115,15 +118,16 @@ static void test_engine_views(void) { CFReleaseNull(objectNames); CFReleaseNull(itemData); } +#endif int secd_75_engine_views(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - - /* custom keychain dir */ secd_test_setup_temp_keychain(__FUNCTION__, NULL); - test_engine_views(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-80-views-alwayson.m b/keychain/securityd/Regressions/secd-80-views-alwayson.m index 57bc8d44..0f73e0ff 100644 --- a/keychain/securityd/Regressions/secd-80-views-alwayson.m +++ b/keychain/securityd/Regressions/secd-80-views-alwayson.m @@ -37,6 +37,7 @@ #include "secd_regressions.h" #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static void testView(SOSAccount* account, SOSViewResultCode expected, CFStringRef view, SOSViewActionCode action, char *label) { CFErrorRef error = NULL; @@ -94,12 +95,17 @@ static void alwaysOnTest() SOSTestCleanup(); } +#endif int secd_80_views_alwayson(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(35); secd_test_clear_testviews(); secd_test_setup_temp_keychain(__FUNCTION__, NULL); alwaysOnTest(); +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-80-views-basic.m b/keychain/securityd/Regressions/secd-80-views-basic.m index db10961b..a1e38ca1 100644 --- a/keychain/securityd/Regressions/secd-80-views-basic.m +++ b/keychain/securityd/Regressions/secd-80-views-basic.m @@ -54,6 +54,7 @@ #include "keychain/securityd/SOSCloudCircleServer.h" #include "SecdTestKeychainUtilities.h" #include "SOSAccountTesting.h" +#if SOS_ENABLED static void testView(SOSAccount* account, SOSViewResultCode expected, CFStringRef view, SOSViewActionCode action, char *label) { @@ -143,10 +144,10 @@ static void tests(void) testView(account, kSOSCCViewNotMember, kSOSViewKeychainV0, kSOSCCViewQuery, "Expected view capability for kSOSViewKeychainV0"); testView(account, kSOSCCViewMember, kSOSViewAppleTV, kSOSCCViewQuery, "Expected view capability for kSOSViewAppleTV"); - ok([account.trust updateViewSetsWithAnalytics:account enabled:SOSViewsGetV0ViewSet() disabled:nullSet parentEvent: NULL], "Expect not accepting kSOSKeychainV0"); + ok([account.trust updateViewSets:account enabled:SOSViewsGetV0ViewSet() disabled:nullSet], "Expect not accepting kSOSKeychainV0"); testView(account, kSOSCCViewNotMember, kSOSViewKeychainV0, kSOSCCViewQuery, "Expected no addition of kSOSKeychainV0"); - ok([account.trust updateViewSetsWithAnalytics:account enabled:SOSViewsGetV0ViewSet() disabled:nullSet parentEvent: NULL], "Expect not accepting kSOSKeychainV0"); + ok([account.trust updateViewSets:account enabled:SOSViewsGetV0ViewSet() disabled:nullSet], "Expect not accepting kSOSKeychainV0"); testView(account, kSOSCCViewNotMember, kSOSViewKeychainV0, kSOSCCViewQuery, "Expected no addition of kSOSKeychainV0"); SOSPeerInfoRef pi = account.peerInfo; @@ -155,10 +156,10 @@ static void tests(void) ok(vr == kSOSCCViewMember, "Set Virtual View manually"); - ok(![account.trust updateViewSetsWithAnalytics:account enabled:nullSet disabled:SOSViewsGetV0ViewSet() parentEvent: NULL], "Expect not removing kSOSKeychainV0"); + ok(![account.trust updateViewSets:account enabled:nullSet disabled:SOSViewsGetV0ViewSet()], "Expect not removing kSOSKeychainV0"); testView(account, kSOSCCViewMember, kSOSViewKeychainV0, kSOSCCViewQuery, "Expected kSOSKeychainV0 is still there"); - ok(![account.trust updateViewSetsWithAnalytics:account enabled:nullSet disabled:SOSViewsGetV0ViewSet() parentEvent: NULL], "Expect not removing kSOSKeychainV0"); + ok(![account.trust updateViewSets:account enabled:nullSet disabled:SOSViewsGetV0ViewSet()], "Expect not removing kSOSKeychainV0"); testView(account, kSOSCCViewMember, kSOSViewKeychainV0, kSOSCCViewQuery, "Expected kSOSKeychainV0 is still there"); SOSDataSourceRelease(test_source, NULL); @@ -166,15 +167,18 @@ static void tests(void) SOSTestCleanup(); } +#endif int secd_80_views_basic(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(kTestTestCount); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); secd_test_clear_testviews(); testViewLists(); tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd-81-item-acl.m b/keychain/securityd/Regressions/secd-81-item-acl.m index 30eddba5..4a8aa0b9 100644 --- a/keychain/securityd/Regressions/secd-81-item-acl.m +++ b/keychain/securityd/Regressions/secd-81-item-acl.m @@ -465,6 +465,25 @@ static void item_with_skip_auth_ui(uint32_t *item_num) CFRelease(item); } +#if LA_CONTEXT_IMPLEMENTED +static void item_forbidden_delete(uint32_t *item_num) { + CFMutableDictionaryRef item = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecClass, kSecClassInternetPassword, NULL); + fillItem(item, (*item_num)++); + + SecAccessControlRef aclRef = SecAccessControlCreate(kCFAllocatorDefault, NULL); + ok(aclRef, "Create SecAccessControlRef"); + ok(SecAccessControlSetProtection(aclRef, kSecAttrAccessibleAlwaysPrivate, NULL)); + ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpEncrypt, kCFBooleanTrue, NULL)); + + CFDictionarySetValue(item, kSecAttrAccessControl, aclRef); + ok_status(SecItemAdd(item, NULL), "add undeletable"); + is_status(SecItemDelete(item), errSecAuthFailed, "delete local - authentication failed"); + + CFReleaseNull(aclRef); + CFRelease(item); +} +#endif + int secd_81_item_acl(int argc, char *const *argv) { uint32_t item_num = 1; @@ -479,15 +498,16 @@ int secd_81_item_acl(int argc, char *const *argv) SecItemServerSetKeychainKeybag(test_keybag); }); #if TARGET_OS_IPHONE - plan_tests(70); + plan_tests(75); #else - plan_tests(29); + plan_tests(34); #endif item_with_skip_auth_ui(&item_num); item_with_invalid_acl(&item_num); item_with_application_password(&item_num); item_with_acl_caused_maxauth(&item_num); item_with_akpu(&item_num); + item_forbidden_delete(&item_num); #else plan_tests(3); item_with_skip_auth_ui(&item_num); diff --git a/keychain/securityd/Regressions/secd60-account-cloud-exposure.m b/keychain/securityd/Regressions/secd60-account-cloud-exposure.m index a9979d44..bb4fe0a5 100644 --- a/keychain/securityd/Regressions/secd60-account-cloud-exposure.m +++ b/keychain/securityd/Regressions/secd60-account-cloud-exposure.m @@ -46,7 +46,7 @@ #include #include "secd_regressions.h" -#include "SOSTestDataSource.h" +#include "keychain/SecureObjectSync/Regressions/SOSTestDataSource.h" #include "SOSRegressionUtilities.h" #include @@ -57,6 +57,7 @@ #include "SOSAccountTesting.h" #include "SecdTestKeychainUtilities.h" +#if SOS_ENABLED static bool SOSAccountResetCircleToNastyOffering(SOSAccount* account, SecKeyRef userPriv, SOSPeerInfoRef pi, CFErrorRef *error) { bool result = false; @@ -66,7 +67,7 @@ static bool SOSAccountResetCircleToNastyOffering(SOSAccount* account, SecKeyRef CFReleaseNull(userPub); return result; } - if(![account.trust ensureFullPeerAvailable:(__bridge CFDictionaryRef)(account.gestalt) deviceID:(__bridge CFStringRef)(account.deviceID) backupKey:(__bridge CFDataRef)(account.backup_key) err:error]){ + if(![account.trust ensureFullPeerAvailable:account err:error]){ CFReleaseNull(userPub); return result; } @@ -219,14 +220,16 @@ static void tests(void) bob_account = nil; SOSTestCleanup(); } +#endif int secd_60_account_cloud_exposure(int argc, char *const *argv) { +#if SOS_ENABLED plan_tests(41); - secd_test_setup_temp_keychain(__FUNCTION__, NULL); - tests(); - +#else + plan_tests(0); +#endif return 0; } diff --git a/keychain/securityd/Regressions/secd_regressions.h b/keychain/securityd/Regressions/secd_regressions.h index 422b0cde..2ad4d934 100644 --- a/keychain/securityd/Regressions/secd_regressions.h +++ b/keychain/securityd/Regressions/secd_regressions.h @@ -63,11 +63,11 @@ ONE_TEST(secd_64_circlereset) ONE_TEST(secd_65_account_retirement_reset) ONE_TEST(secd_66_account_recovery) ONE_TEST(secd_67_prefixedKeyIDs) +ONE_TEST(secd_68_fullPeerInfoIntegrity) ONE_TEST(secd_70_engine) ONE_TEST(secd_70_engine_corrupt) ONE_TEST(secd_70_engine_smash) ONE_TEST(secd_71_engine_save) -ONE_TEST(secd_68_ghosts) ONE_TEST(secd_155_otr_negotiation_monitor) DISABLED_ONE_TEST(secd_70_otr_remote) diff --git a/keychain/securityd/SFKeychainControlManager.m b/keychain/securityd/SFKeychainControlManager.m index 89e1ae5c..ee4768c2 100644 --- a/keychain/securityd/SFKeychainControlManager.m +++ b/keychain/securityd/SFKeychainControlManager.m @@ -28,6 +28,7 @@ #import #import #import +#import NSString* kSecEntitlementKeychainControl = @"com.apple.private.keychain.keychaincontrol"; @@ -75,9 +76,11 @@ XPC_RETURNS_RETAINED xpc_endpoint_t SecServerCreateKeychainControlEndpoint(void) return NO; } + NSSet* errorClasses = [SecXPCHelper safeErrorClasses]; + NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(SFKeychainControl)]; - [interface setClass:[NSError class] forSelector:@selector(rpcFindCorruptedItemsWithReply:) argumentIndex:1 ofReply:YES]; - [interface setClass:[NSError class] forSelector:@selector(rpcDeleteCorruptedItemsWithReply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcFindCorruptedItemsWithReply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcDeleteCorruptedItemsWithReply:) argumentIndex:1 ofReply:YES]; newConnection.exportedInterface = interface; newConnection.exportedObject = self; [newConnection resume]; diff --git a/keychain/securityd/SFKeychainServer.m b/keychain/securityd/SFKeychainServer.m index fb9c07b2..c37085a1 100644 --- a/keychain/securityd/SFKeychainServer.m +++ b/keychain/securityd/SFKeychainServer.m @@ -37,6 +37,7 @@ #import "SecTask.h" #import "keychain/categories/NSError+UsefulConstructors.h" #import "SecEntitlements.h" +#import #import #import #import @@ -104,6 +105,16 @@ static NSString* const SFCredentialSecretPassword = @"password"; // wait a bit for shared function from SecurityFoundation to get to SDK, then addopt that NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(SFKeychainServerProtocol)]; + + NSSet *errorClasses = [SecXPCHelper safeErrorClasses]; + + [interface setClasses:errorClasses forSelector:@selector(rpcAddCredential:withAccessPolicy:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcFetchPasswordCredentialForPersistentIdentifier:reply:) argumentIndex:2 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcLookupCredentialsForServiceIdentifiers:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcRemoveCredentialWithPersistentIdentifier:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcReplaceOldCredential:withNewCredential:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:errorClasses forSelector:@selector(rpcReplaceCredential:withNewCredential:reply:) argumentIndex:1 ofReply:YES]; + [interface setClasses:[NSSet setWithObjects:[NSArray class], [SFServiceIdentifier class], nil] forSelector:@selector(rpcLookupCredentialsForServiceIdentifiers:reply:) argumentIndex:0 ofReply:NO]; [interface setClasses:[NSSet setWithObjects:[NSArray class], [SFPasswordCredential class], nil] forSelector:@selector(rpcLookupCredentialsForServiceIdentifiers:reply:) argumentIndex:0 ofReply:YES]; newConnection.exportedInterface = interface; diff --git a/keychain/securityd/SOSCloudCircleServer.h b/keychain/securityd/SOSCloudCircleServer.h index 0bb84b8b..1c249e86 100644 --- a/keychain/securityd/SOSCloudCircleServer.h +++ b/keychain/securityd/SOSCloudCircleServer.h @@ -35,24 +35,24 @@ __BEGIN_DECLS // // MARK: Server versions of our SPI // + bool SOSCCTryUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error); bool SOSCCSetUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); bool SOSCCSetUserCredentialsAndDSID_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error); -bool SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error); bool SOSCCCanAuthenticate_Server(CFErrorRef *error); bool SOSCCPurgeUserCredentials_Server(CFErrorRef *error); SOSCCStatus SOSCCThisDeviceIsInCircle_Server(CFErrorRef *error); bool SOSCCRequestToJoinCircle_Server(CFErrorRef* error); -bool SOSCCRequestToJoinCircleWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error); bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error); -bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error); bool SOSCCRemoveThisDeviceFromCircle_Server(CFErrorRef* error); -bool SOSCCRemoveThisDeviceFromCircleWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error); bool SOSCCRemovePeersFromCircle_Server(CFArrayRef peers, CFErrorRef* error); -bool SOSCCRemovePeersFromCircleWithAnalytics_Server(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error); + +// This will async off the notification, so it does not return a value. +void SOSCCNotifyLoggedIntoAccount_Server(void); + bool SOSCCLoggedOutOfAccount_Server(CFErrorRef *error); bool SOSCCBailFromCircle_Server(uint64_t limit_in_seconds, CFErrorRef* error); @@ -75,12 +75,10 @@ CFArrayRef SOSCCCopyConcurringPeerPeerInfo_Server(CFErrorRef* error); bool SOSCCAccountSetToNew_Server(CFErrorRef *error); bool SOSCCResetToOffering_Server(CFErrorRef* error); bool SOSCCResetToEmpty_Server(CFErrorRef* error); -bool SOSCCResetToEmptyWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error); CFBooleanRef SOSCCPeersHaveViewsEnabled_Server(CFArrayRef viewNames, CFErrorRef *error); SOSViewResultCode SOSCCView_Server(CFStringRef view, SOSViewActionCode action, CFErrorRef *error); -bool SOSCCViewSetWithAnalytics_Server(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent); bool SOSCCViewSet_Server(CFSetRef enabledViews, CFSetRef disabledViews); enum DepartureReason SOSCCGetLastDepartureReason_Server(CFErrorRef* error); @@ -95,7 +93,6 @@ SOSPeerInfoRef SOSCCSetNewPublicBackupKey_Server(CFDataRef newPublicBackup, CFEr bool SOSCCRegisterSingleRecoverySecret_Server(CFDataRef backupSlice, bool setupV0Only, CFErrorRef *error); bool SOSCCWaitForInitialSync_Server(CFErrorRef*); -bool SOSCCWaitForInitialSyncWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error); // // MARK: Internal kicks. @@ -172,10 +169,21 @@ void SOSCCPerformUpdateOfAllOctagonKeys(CFDataRef octagonSigningFullKey, CFDataR CFDataRef signingPublicKey, CFDataRef encryptionPublicKey, SecKeyRef octagonSigningPublicKeyRef, SecKeyRef octagonEncryptionPublicKeyRef, void (^action)(CFErrorRef error)); +void SOSCCPerformPreloadOfAllOctagonKeys(CFDataRef octagonSigningFullKey, CFDataRef octagonEncryptionFullKey, + SecKeyRef octagonSigningFullKeyRef, SecKeyRef octagonEncryptionFullKeyRef, + SecKeyRef octagonSigningPublicKeyRef, SecKeyRef octagonEncryptionPublicKeyRef, + void (^action)(CFErrorRef error)); + +bool SOSCCSetCKKS4AllStatus(bool status, CFErrorRef* error); void SOSCCResetOTRNegotiation_Server(CFStringRef peerid); void SOSCCPeerRateLimiterSendNextMessage_Server(CFStringRef peerid, CFStringRef accessGroup); +#if __OBJC2__ +bool SOSCCSaveOctagonKeysToKeychain(NSString* keyLabel, NSData* keyDataToSave, __unused int keySize, SecKeyRef octagonPublicKey, NSError** error); +void SOSCCEnsureAccessGroupOfKey(SecKeyRef publicKey, NSString* oldAgrp, NSString* newAgrp); +#endif + __END_DECLS #endif diff --git a/keychain/securityd/SOSCloudCircleServer.m b/keychain/securityd/SOSCloudCircleServer.m index ae3a447d..1a336f80 100644 --- a/keychain/securityd/SOSCloudCircleServer.m +++ b/keychain/securityd/SOSCloudCircleServer.m @@ -55,7 +55,7 @@ #import "keychain/SigninMetrics/OctagonSignPosts.h" #import "NSError+UsefulConstructors.h" -#include +#import "utilities/SecCoreAnalytics.h" #include #include @@ -71,7 +71,6 @@ #include #include #include -#include #include #include @@ -224,7 +223,7 @@ exit: static SOSAccount* SOSKeychainAccountCreateSharedAccount(CFDictionaryRef our_gestalt) { - secdebug("account", "Created account"); + secdebug("account", "Create account for UID %d EUID %d", getuid(), geteuid()); CFDataRef savedAccount = SOSKeychainCopySavedAccountData(); SOSAccount* account = NULL; @@ -244,7 +243,7 @@ static SOSAccount* SOSKeychainAccountCreateSharedAccount(CFDictionaryRef our_ges if (account){ [account.trust updateGestalt:account newGestalt:our_gestalt]; } else { - secerror("Got error inflating account: %@", inflationError); + secnotice("account", "Got error inflating account: %@", inflationError); } } @@ -254,10 +253,10 @@ static SOSAccount* SOSKeychainAccountCreateSharedAccount(CFDictionaryRef our_ges account = SOSAccountCreate(kCFAllocatorDefault, our_gestalt, factory); if (!account) - secerror("Got NULL creating account"); + secnotice("account", "Got NULL creating account"); } - //[account startStateMachine]; + [account startStateMachine]; done: CFReleaseNull(savedAccount); @@ -466,7 +465,7 @@ static SOSAccount* GetSharedAccount(bool onlyIfItExists) { dispatch_once(&onceToken, ^{ secdebug("account", "Account Creation start"); - CFDictionaryRef gestalt = CreateDeviceGestaltDictionaryAndRegisterForUpdate(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + CFDictionaryRef gestalt = CreateDeviceGestaltDictionaryAndRegisterForUpdate(dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0), NULL); if (!gestalt) { #if TARGET_OS_IPHONE && TARGET_OS_SIMULATOR @@ -496,7 +495,7 @@ static SOSAccount* GetSharedAccount(bool onlyIfItExists) { // TODO: Figure out why peer_additions isn't right in some cases (like when joining a v2 circle with a v0 peer. if (CFSetGetCount(peer_additions) != 0) { secnotice("updates", "Requesting Ensure Peer Registration."); - SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0), NULL); } else { secinfo("updates", "Not requesting Ensure Peer Registration, since it's not needed"); } @@ -565,7 +564,7 @@ static SOSAccount* GetSharedAccount(bool onlyIfItExists) { } }; // TODO: We should not be doing extra work whenever securityd is launched, let's see if we can eliminate this call - SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(SOS_ACCOUNT_PRIORITY, 0), NULL); // provide state handler to sysdiagnose and logging os_state_add_handler(dispatch_get_global_queue(0, 0), accountStateBlock); @@ -686,6 +685,7 @@ static bool do_with_account_while_unlocked(CFErrorRef *error, bool (^action)(SOS // Get ramp settings from the Cloud if(ghostbustnow) { gbOptions = [SOSAccount ghostBustGetRampSettings]; + gbOptions += SOSGhostBustiCloudIdentities; } } #endif @@ -818,22 +818,16 @@ SOSViewResultCode SOSCCView_Server(CFStringRef viewname, SOSViewActionCode actio return status; } -bool SOSCCViewSetWithAnalytics_Server(CFSetRef enabledViews, CFSetRef disabledViews, CFDataRef parentEvent) { - __block bool status = false; +bool SOSCCViewSet_Server(CFSetRef enabledViews, CFSetRef disabledViews) { OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCViewSet); + __block bool status = false; do_with_account_if_after_first_unlock(NULL, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - status = [txn.account.trust updateViewSetsWithAnalytics:txn.account enabled:enabledViews disabled:disabledViews parentEvent:(__bridge NSData*)parentEvent]; + status = [txn.account.trust updateViewSets:txn.account enabled:enabledViews disabled:disabledViews]; return true; }); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCViewSet, OctagonSignpostNumber1(SOSSignpostNameSOSCCViewSet), (int)status); - return status; -} - - -bool SOSCCViewSet_Server(CFSetRef enabledViews, CFSetRef disabledViews) { - return SOSCCViewSetWithAnalytics_Server(enabledViews, disabledViews, NULL); -} + return status;} void sync_the_last_data_to_kvs(CFTypeRef account, bool waitForeverForSynchronization){ @@ -844,7 +838,7 @@ void sync_the_last_data_to_kvs(CFTypeRef account, bool waitForeverForSynchroniza secnoticeq("force-push", "calling SOSCloudKeychainSynchronizeAndWait"); - SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { + SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { if (sync_error) { secerrorq("SOSCloudKeychainSynchronizeAndWait: %@", sync_error); localError = sync_error; @@ -877,7 +871,7 @@ static bool SyncKVSAndWait(CFErrorRef *error) { secnoticeq("fresh", "EFP calling SOSCloudKeychainSynchronizeAndWait"); os_activity_initiate("CloudCircle EFRESH", OS_ACTIVITY_FLAG_DEFAULT, ^(void) { - SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(__unused CFDictionaryRef returnedValues, CFErrorRef sync_error) { + SOSCloudKeychainSynchronizeAndWait(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(__unused CFDictionaryRef returnedValues, CFErrorRef sync_error) { secnotice("fresh", "EFP returned, callback error: %@", sync_error); success = (sync_error == NULL); @@ -904,7 +898,7 @@ static bool Flush(CFErrorRef *error) { dispatch_semaphore_t wait_for = dispatch_semaphore_create(0); secnotice("flush", "Starting"); - SOSCloudKeychainFlush(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { + SOSCloudKeychainFlush(dispatch_get_global_queue(SOS_TRANSPORT_PRIORITY, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { success = (sync_error == NULL); if (error) { CFRetainAssign(*error, sync_error); @@ -923,134 +917,102 @@ static bool Flush(CFErrorRef *error) { } bool SOSCCTryUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) { + __block bool result = false; secnotice("updates", "Trying credentials and dsid (%@) for %@", dsid, user_label); - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCTryUserCredentials); + + dispatch_sync(SOSCCCredentialQueue(), ^{ + OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCTryUserCredentials); + + // Try the password with no EFRESH - attempting to get through this faster for rdar://problem/57242044 + result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { + bool retval = false; + if (dsid != NULL && CFStringCompare(dsid, CFSTR(""), 0) != 0) { + SOSAccountAssertDSID(txn.account, dsid); + } + if(txn.account.accountKeyDerivationParameters) { + retval = SOSAccountTryUserCredentials(txn.account, user_label, user_password, block_error); + } + return retval; + }); - bool result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - if (dsid != NULL && CFStringCompare(dsid, CFSTR(""), 0) != 0) { - SOSAccountAssertDSID(txn.account, dsid); + // If that fails - either lacking parameters to begin with or failed to construct the correct key try with EFRESH + if(result == false) { + if(SyncKVSAndWait(error) && Flush(error)) { + result = do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *block_error) { + return SOSAccountTryUserCredentials(txn.account, user_label, user_password, block_error); + }); + } } - return true; - }); - require_quiet(result, done); - - require_quiet(SyncKVSAndWait(error), done); // Make sure we've seen what the server has - require_quiet(Flush(error), done); // And processed it already...before asserting - - result = do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *block_error) { - return SOSAccountTryUserCredentials(txn.account, user_label, user_password, block_error); + // if either key constructions passed do a flush to bring through anything we weren't "interested" in before. + if(result) { + Flush(error); + } + OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCTryUserCredentials, OctagonSignpostNumber1(SOSSignpostNameSOSCCTryUserCredentials), (int)result); }); - - require_quiet(result, done); - require_quiet(Flush(error), done); - -done: - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCTryUserCredentials, OctagonSignpostNumber1(SOSSignpostNameSOSCCTryUserCredentials), (int)result); - return result; } -static bool SOSCCAssertUserCredentialsAndOptionalDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, NSData* parentEvent, CFErrorRef *error) { +static bool SOSCCAssertUserCredentialsAndOptionalDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) { + __block bool result = false; secnotice("updates", "Setting credentials and dsid (%@) for %@", dsid, user_label); - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameAssertUserCredentialsAndOptionalDSID); - - NSError* localError = nil; - SFSignInAnalytics* parent = nil; - - if(parentEvent) { - parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError]; - } - - SFSignInAnalytics *syncAndWaitEvent = nil; - SFSignInAnalytics *flushEvent = nil; - SFSignInAnalytics *secondFlushEvent = nil; - SFSignInAnalytics *generationSignatureUpdateEvent = nil; - - bool result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - if (dsid != NULL && CFStringCompare(dsid, CFSTR(""), 0) != 0) { - SOSAccountAssertDSID(txn.account, dsid); + + dispatch_sync(SOSCCCredentialQueue(), ^{ + OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameAssertUserCredentialsAndOptionalDSID); + + // Shortcut if we're talking to the same account and can construct the same trusted key + result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { + bool retval = false; + CFStringRef accountDSID = SOSAccountGetValue(txn.account, kSOSDSIDKey, NULL); + if(CFEqualSafe(accountDSID, dsid) && txn.account.accountKeyDerivationParameters && txn.account.accountKeyIsTrusted) { + retval = SOSAccountTryUserCredentials(txn.account, user_label, user_password, block_error); + } + return retval; + }); + if(result) { + return; // shortcut to not do the following work if we're duping a setcreds operation. } - return true; - }); - - require_quiet(result, done); - if(parent) { - syncAndWaitEvent = [parent newSubTaskForEvent:@"syncAndWaitEvent"]; - } - require_quiet(SyncKVSAndWait(error), done); // Make sure we've seen what the server has - if(syncAndWaitEvent) { - [syncAndWaitEvent stopWithAttributes:nil]; - } + result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { + if (dsid != NULL && CFStringCompare(dsid, CFSTR(""), 0) != 0) { + SOSAccountAssertDSID(txn.account, dsid); + } + return true; + }); - if(parent) { - flushEvent = [parent newSubTaskForEvent:@"flushEvent"]; - } - require_quiet(Flush(error), done); // And processed it already...before asserting - if(flushEvent) { - [flushEvent stopWithAttributes:nil]; - } + if(result && SyncKVSAndWait(error) && Flush(error)) { + result = do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *block_error) { + return SOSAccountAssertUserCredentials(txn.account, user_label, user_password, block_error); + }); + } - result = do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *block_error) { - return SOSAccountAssertUserCredentials(txn.account, user_label, user_password, block_error); - }); + // if either key constructions passed do a flush to bring through anything we weren't "interested" in before. + if(result) { + Flush(error); + } - require_quiet(result, done); - if(parent) { - secondFlushEvent = [parent newSubTaskForEvent:@"secondFlushEvent"]; - } - require_quiet(Flush(error), done); // Process any incoming information..circles et.al. before fixing our signature - if(secondFlushEvent) { - [secondFlushEvent stopWithAttributes:nil]; - } + result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { + return SOSAccountGenerationSignatureUpdate(txn.account, error); + }); + + secnotice("updates", "Complete credentials and dsid (%@) for %@: %d %@", + dsid, user_label, result, error ? *error : NULL); - if(parent) { - generationSignatureUpdateEvent = [parent newSubTaskForEvent:@"generationSignatureUpdateEvent"]; - } - result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - return SOSAccountGenerationSignatureUpdate(txn.account, error); + OctagonSignpostEnd(signPost, SOSSignpostNameAssertUserCredentialsAndOptionalDSID, OctagonSignpostNumber1(SOSSignpostNameAssertUserCredentialsAndOptionalDSID), (int)result); }); - if(generationSignatureUpdateEvent) { - [generationSignatureUpdateEvent stopWithAttributes:nil]; - } - -done: - if(syncAndWaitEvent){ - [syncAndWaitEvent stopWithAttributes:nil]; - } - if(flushEvent){ - [flushEvent stopWithAttributes:nil]; - } - if(secondFlushEvent){ - [secondFlushEvent stopWithAttributes:nil]; - } - if(generationSignatureUpdateEvent){ - [generationSignatureUpdateEvent stopWithAttributes:nil]; - } - secnotice("updates", "Complete credentials and dsid (%@) for %@: %d %@", - dsid, user_label, result, error ? *error : NULL); - - OctagonSignpostEnd(signPost, SOSSignpostNameAssertUserCredentialsAndOptionalDSID, OctagonSignpostNumber1(SOSSignpostNameAssertUserCredentialsAndOptionalDSID), (int)result); - return result; } bool SOSCCSetUserCredentialsAndDSID_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error) { // TODO: Return error if DSID is NULL to insist our callers provide one? - return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, dsid, nil, error); -} - -bool SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error) -{ - return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, dsid, (__bridge NSData*)parentEvent, error); + return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, dsid, error); } bool SOSCCSetUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error) { - return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, NULL, nil, error); + return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, NULL, error); } bool SOSCCCanAuthenticate_Server(CFErrorRef *error) @@ -1095,24 +1057,19 @@ SOSCCStatus SOSCCThisDeviceIsInCircle_Server(CFErrorRef *error) }) ? status : kSOSCCError; } -bool SOSCCRequestToJoinCircleWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error) +bool SOSCCRequestToJoinCircle_Server(CFErrorRef* error) { __block bool result = true; OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRequestToJoinCircle); bool requested = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - result = SOSAccountJoinCircles(txn, (__bridge NSData*)parentEvent, block_error); + result = SOSAccountJoinCircles(txn, block_error); return result; }); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestToJoinCircle, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestToJoinCircle), (int)requested); return requested; } -bool SOSCCRequestToJoinCircle_Server(CFErrorRef* error) -{ - return SOSCCRequestToJoinCircleWithAnalytics_Server(nil, error); -} - bool SOSCCAccountHasPublicKey_Server(CFErrorRef *error) { __block bool result = true; @@ -1129,45 +1086,24 @@ bool SOSCCAccountHasPublicKey_Server(CFErrorRef *error) return hasPublicKey; } -bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error) +bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error) { __block bool result = true; bool returned = false; OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore); returned = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - NSError* localError = nil; - SFSignInAnalytics* parent = nil; - SFSignInAnalytics *ensurePeerRegistrationEvent = nil; - - if(parentEvent) { - parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:(__bridge NSData*)parentEvent error:&localError]; - ensurePeerRegistrationEvent = [parent newSubTaskForEvent:@"ensurePeerRegistrationEvent"]; - } - SOSAccountEnsurePeerRegistration(txn.account, block_error); if(block_error && *block_error){ NSError* blockError = (__bridge NSError*)*block_error; - if(blockError){ - if(ensurePeerRegistrationEvent) { - [ensurePeerRegistrationEvent logRecoverableError:blockError]; - } + if (blockError) { secerror("ensure peer registration error: %@", blockError); } } - if(ensurePeerRegistrationEvent) { - [ensurePeerRegistrationEvent stopWithAttributes:nil]; - } - result = SOSAccountJoinCirclesAfterRestore(txn, (__bridge NSData*)parentEvent, block_error); + result = SOSAccountJoinCirclesAfterRestore(txn, block_error); return result; }); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore), (int)result); return returned; - -} - -bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error) -{ - return SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(nil, error); } bool SOSCCAccountSetToNew_Server(CFErrorRef *error) @@ -1213,36 +1149,6 @@ bool SOSCCResetToEmpty_Server(CFErrorRef* error) return resetResult; } -bool SOSCCResetToEmptyWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error) -{ - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCResetToEmpty); - - bool resetResult = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - bool result = false; - - if (!SOSAccountHasPublicKey(txn.account, error)) { - return result; - } - result = [txn.account.trust resetAccountToEmptyWithAnalytics:txn.account transport:txn.account.circle_transport parentEvent:(__bridge NSData*)parentEvent err:block_error]; - return result; - }); - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCResetToEmpty, OctagonSignpostNumber1(SOSSignpostNameSOSCCResetToEmpty), (int)resetResult); - return resetResult; -} - -bool SOSCCRemoveThisDeviceFromCircleWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error) -{ - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRemoveThisDeviceFromCircle); - - bool removeResult = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - bool result = [txn.account.trust leaveCircleWithAccount:txn.account withAnalytics:(__bridge NSData*)parentEvent err:error]; - return result; - }); - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRemoveThisDeviceFromCircle, OctagonSignpostNumber1(SOSSignpostNameSOSCCRemoveThisDeviceFromCircle), (int)removeResult); - - return removeResult; -} - bool SOSCCRemoveThisDeviceFromCircle_Server(CFErrorRef* error) { OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRemoveThisDeviceFromCircle); @@ -1260,23 +1166,29 @@ bool SOSCCRemovePeersFromCircle_Server(CFArrayRef peers, CFErrorRef* error) OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRemovePeersFromCircle); bool removeResult = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - bool result = SOSAccountRemovePeersFromCircle(txn.account, peers, nil, block_error); + bool result = SOSAccountRemovePeersFromCircle(txn.account, peers, block_error); return result; }); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRemovePeersFromCircle, OctagonSignpostNumber1(SOSSignpostNameSOSCCRemovePeersFromCircle), (int)removeResult); return removeResult; } -bool SOSCCRemovePeersFromCircleWithAnalytics_Server(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error) -{ - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRemovePeersFromCircle); +void SOSCCNotifyLoggedIntoAccount_Server() { + // This call is mixed in with SOSCCSetUserCredentialsAndDSID calls from our accountsd plugin + dispatch_async(SOSCCCredentialQueue(), ^{ + CFErrorRef error = NULL; + bool loggedInResult = do_with_account_while_unlocked(&error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { + secinfo("circleOps", "Signed into account!"); + txn.account.accountIsChanging = false; // we've changed + return true; + }); - bool removeResult = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - bool result = SOSAccountRemovePeersFromCircle(txn.account, peers, (__bridge NSData*)parentEvent, block_error); - return result; + if(!loggedInResult || error != NULL) { + secerror("circleOps: error delivering account-sign-in notification: %@", error); + } + + CFReleaseNull(error); }); - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRemovePeersFromCircle, OctagonSignpostNumber1(SOSSignpostNameSOSCCRemovePeersFromCircle), (int)removeResult); - return removeResult; } bool SOSCCLoggedOutOfAccount_Server(CFErrorRef *error) @@ -1296,7 +1208,7 @@ bool SOSCCLoggedOutOfAccount_Server(CFErrorRef *error) sync_the_last_data_to_kvs((__bridge CFTypeRef)(txn.account), waitForeverForSynchronization); SOSAccountSetToNew(txn.account); - + txn.account.accountIsChanging = true; return result; }); @@ -1459,99 +1371,6 @@ static uint64_t initialSyncTimeoutFromDefaultsWrite(void) return timeout; } -bool SOSCCWaitForInitialSyncWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error) { - __block dispatch_semaphore_t inSyncSema = NULL; - __block bool result = false; - __block bool synced = false; - bool timed_out = false; - __block CFStringRef inSyncCallID = NULL; - __block time_t start; - __block CFBooleanRef shouldUseInitialSyncV0 = false; - SFSignInAnalytics* syncingEvent = nil; - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCWaitForInitialSync); - - NSError* localError = nil; - SFSignInAnalytics* parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:(__bridge NSData*)parentEvent error:&localError]; - - secnotice("initial sync", "Wait for initial sync start!"); - - result = do_with_account_if_after_first_unlock(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) { - shouldUseInitialSyncV0 = (CFBooleanRef)SOSAccountGetValue(txn.account, kSOSInitialSyncTimeoutV0, error); - bool alreadyInSync = (SOSAccountHasCompletedInitialSync(txn.account)); - - if (!alreadyInSync) { - start = time(NULL); - inSyncSema = dispatch_semaphore_create(0); - - SFSignInAnalytics* callWhenInSyncEvent = [parent newSubTaskForEvent:@"callWhenInSync"]; - inSyncCallID = SOSAccountCallWhenInSync(txn.account, ^bool(SOSAccount* mightBeSynced) { - synced = true; - - if(inSyncSema){ - dispatch_semaphore_signal(inSyncSema); - NSDictionary* attributes = @{@"finishedSyncing" : @YES}; - [syncingEvent stopWithAttributes:attributes]; - } - return true; - }); - NSDictionary* attributes = @{}; - [callWhenInSyncEvent stopWithAttributes:attributes]; - } - else{ - synced = true; - } - return true; - }); - - require_quiet(result, fail); - - - if(inSyncSema){ - syncingEvent = [parent newSubTaskForEvent:@"initialSyncEvent"]; - if(shouldUseInitialSyncV0){ - secnotice("piggy","setting initial sync timeout to 5 minutes"); - timed_out = dispatch_semaphore_wait(inSyncSema, dispatch_time(DISPATCH_TIME_NOW, 300ull * NSEC_PER_SEC)); - } - else{ - uint64_t timeoutFromDefaultsWrite = initialSyncTimeoutFromDefaultsWrite(); - secnotice("piggy","setting initial sync timeout to %llu seconds", timeoutFromDefaultsWrite); - timed_out = dispatch_semaphore_wait(inSyncSema, dispatch_time(DISPATCH_TIME_NOW, timeoutFromDefaultsWrite * NSEC_PER_SEC)); - } - } - if (timed_out && shouldUseInitialSyncV0) { - do_with_account(^(SOSAccountTransaction* txn) { - if (SOSAccountUnregisterCallWhenInSync(txn.account, inSyncCallID)) { - if(inSyncSema){ - inSyncSema = NULL; // We've canceled the timeout so we must be the last. - } - } - }); - NSError* error = [NSError errorWithDomain:@"securityd" code:errSecTimedOut userInfo:@{NSLocalizedDescriptionKey: @"timed out waiting for initial sync"}]; - [syncingEvent logUnrecoverableError:error]; - NSDictionary* attributes = @{@"finishedSyncing" : @NO, @"legacyPiggybacking" : @YES}; - [syncingEvent stopWithAttributes:attributes]; - } - - require_quiet(result, fail); - - if(result) - { - SecADClientPushValueForDistributionKey(SOSAggdSyncCompletionKey, getTimeDifference(start)); - } - else if(!result) - { - SecADAddValueForScalarKey(SOSAggdSyncTimeoutKey, 1); - } - - secnotice("initial sync", "Finished!: %d", result); - -fail: - CFReleaseNull(inSyncCallID); - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCWaitForInitialSync, OctagonSignpostNumber1(SOSSignpostNameSOSCCWaitForInitialSync), (int)result); - - return result; -} - bool SOSCCWaitForInitialSync_Server(CFErrorRef* error) { __block dispatch_semaphore_t inSyncSema = NULL; @@ -1611,18 +1430,14 @@ bool SOSCCWaitForInitialSync_Server(CFErrorRef* error) { } }); } - - require_quiet(result, fail); - if(result) - { - SecADClientPushValueForDistributionKey(SOSAggdSyncCompletionKey, getTimeDifference(start)); - } - else if(!result) - { - SecADAddValueForScalarKey(SOSAggdSyncTimeoutKey, 1); + if(result) { + [SecCoreAnalytics sendEvent:(__bridge id)SOSAggdSyncCompletionKey + event:@{SecCoreAnalyticsValue: [NSNumber numberWithLong:getTimeDifference(start)]}]; + } else { + [SecCoreAnalytics sendEvent:(__bridge id)SOSAggdSyncTimeoutKey + event:@{SecCoreAnalyticsValue: @1}]; } - secnotice("initial sync", "Finished!: %d", result); fail: @@ -1766,20 +1581,87 @@ bool SOSCCProcessEnsurePeerRegistration_Server(CFErrorRef* error) return processResult; } +static bool internalSyncWithPeers(CFSetRef peers, CFSetRef backupPeers, CFMutableSetRef handled, CFErrorRef *error) { + return do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *error) { + CFSetRef addedResult = SOSAccountProcessSyncWithPeers(txn, peers, backupPeers, error); + CFSetUnion(handled, addedResult); + bool retval = (addedResult != NULL); + CFReleaseNull(addedResult); + return retval; + }); +} + +#define MAXPEERS 7 + +static bool SOSCFSubsetOfN(CFSetRef peers, size_t n, CFErrorRef* error, bool (^action)(CFSetRef subset, CFErrorRef* error)) { + __block bool retval = true; + __block size_t ready = 0; + __block CFMutableSetRef subset = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); + + CFSetForEach(peers, ^(const void *value) { + CFSetAddValue(subset, value); + ready++; + if(ready >= n) { + retval &= action(subset, error); + ready = 0; + CFSetRemoveAllValues(subset); + } + }); + if(CFSetGetCount(subset)) { + retval &= action(subset, error); + } + CFReleaseNull(subset); + return retval; +} + CF_RETURNS_RETAINED CFSetRef SOSCCProcessSyncWithPeers_Server(CFSetRef peers, CFSetRef backupPeers, CFErrorRef *error) { - __block CFSetRef result = NULL; - OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCProcessSyncWithPeers); + static dispatch_queue_t swpQueue = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + swpQueue = dispatch_queue_create("syncWithPeers", DISPATCH_QUEUE_SERIAL); + }); + + __block CFMutableSetRef handled = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); + __block CFSetRef noPeers = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); - if (!do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *error) { - result = SOSAccountProcessSyncWithPeers(txn, peers, backupPeers, error); - return result != NULL; - })) { - // Be sure we don't return a result if we got an error - CFReleaseNull(result); + if(!peers) { + peers = noPeers; } - OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCProcessSyncWithPeers, OctagonSignpostNumber1(SOSSignpostNameSOSCCProcessSyncWithPeers), (int)(result != NULL)); - return result; + if(!backupPeers) { + backupPeers = noPeers; + } + + dispatch_sync(swpQueue, ^{ + OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCProcessSyncWithPeers); + + if((CFSetGetCount(peers) + CFSetGetCount(backupPeers)) < MAXPEERS) { + internalSyncWithPeers(peers, backupPeers, handled, error); + } else { + // sync any backupPeers + if(backupPeers && CFSetGetCount(backupPeers)) { + SOSCFSubsetOfN(backupPeers, MAXPEERS, error, ^bool(CFSetRef subset, CFErrorRef *error) { + return internalSyncWithPeers(noPeers, subset, handled, error); + }); + } + + // sync any device peers + if(peers && CFSetGetCount(peers)) { + SOSCFSubsetOfN(peers, MAXPEERS, error, ^bool(CFSetRef subset, CFErrorRef *error) { + return internalSyncWithPeers(subset, noPeers, handled, error); + }); + } + } + + OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCProcessSyncWithPeers, OctagonSignpostNumber1(SOSSignpostNameSOSCCProcessSyncWithPeers), (int)(CFSetGetCount(handled) != 0)); + + if(CFSetGetCount(handled) == 0) { + CFReleaseNull(handled); + } + CFReleaseNull(noPeers); + }); + + return handled; } SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers_Server(CFErrorRef* error) @@ -1856,7 +1738,7 @@ void SOSCCRequestSyncWithPeersList(CFArrayRef /*CFStringRef*/ peerIDs) { }); SOSCloudKeychainRequestSyncWithPeers(peerIDs, empty, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + dispatch_get_global_queue(SOS_ENGINE_PRIORITY, 0), NULL); CFReleaseNull(empty); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestSyncWithPeersList, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestSyncWithPeersList), (int)true); }); @@ -1873,7 +1755,7 @@ void SOSCCRequestSyncWithBackupPeerList(CFArrayRef /* CFStringRef */ backupPeerI }); SOSCloudKeychainRequestSyncWithPeers(empty, backupPeerIDs, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + dispatch_get_global_queue(SOS_ENGINE_PRIORITY, 0), NULL); CFReleaseNull(empty); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestSyncWithBackupPeerList, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestSyncWithBackupPeerList), (int)true); @@ -1889,7 +1771,7 @@ void SOSCCEnsurePeerRegistration(void) { os_activity_initiate("CloudCircle EnsurePeerRegistration", OS_ACTIVITY_FLAG_DEFAULT, ^(void) { OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCEnsurePeerRegistration); - SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(SOS_ENGINE_PRIORITY, 0), NULL); OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCEnsurePeerRegistration, OctagonSignpostNumber1(SOSSignpostNameSOSCCEnsurePeerRegistration), (int)true); }); @@ -2148,28 +2030,23 @@ void SOSCCPerformWithAllOctagonKeys(void (^action)(SecKeyRef octagonEncryptionKe CFReleaseNull(localError); } -static bool saveOctagonKeysToKeychain(NSString* keyLabel, NSData* keyDataToSave, int keySize, SecKeyRef octagonPublicKey, NSError** error) { +bool SOSCCSaveOctagonKeysToKeychain(NSString* keyLabel, NSData* keyDataToSave, __unused int keySize, SecKeyRef octagonPublicKey, NSError** error) { NSError* localerror = nil; - CFDataRef publicKeyHash = SecKeyCopyPublicKeyHash(octagonPublicKey); - NSMutableDictionary* query = [@{ - (id)kSecClass : (id)kSecClassKey, - (id)kSecAttrKeyType : (id)kSecAttrKeyTypeEC, - (id)kSecAttrKeyClass : (id)kSecAttrKeyClassPrivate, - (id)kSecAttrAccessGroup : (id)kSOSInternalAccessGroup, - (id)kSecAttrLabel : keyLabel, - (id)kSecAttrApplicationLabel : (__bridge NSData*)(publicKeyHash), - (id)kSecAttrSynchronizable : (id)kCFBooleanFalse, - (id)kSecUseDataProtectionKeychain : @YES, - (id)kSecValueData : keyDataToSave, - } mutableCopy]; + NSMutableDictionary* query = [((NSDictionary*)CFBridgingRelease(SecKeyGeneratePrivateAttributeDictionary(octagonPublicKey, + kSecAttrKeyTypeEC, + (__bridge CFDataRef)keyDataToSave))) mutableCopy]; + + query[(id)kSecAttrLabel] = keyLabel; + query[(id)kSecUseDataProtectionKeychain] = @YES; + query[(id)kSecAttrSynchronizable] = (id)kCFBooleanFalse; + query[(id)kSecAttrAccessGroup] = (id)kSOSInternalAccessGroup; CFTypeRef result = NULL; OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, &result); if(status == errSecSuccess) { - CFReleaseNull(publicKeyHash); return true; } if(status == errSecDuplicateItem) { @@ -2204,11 +2081,28 @@ static bool saveOctagonKeysToKeychain(NSString* keyLabel, NSData* keyDataToSave, *error = localerror; } - CFReleaseNull(publicKeyHash); - return (status == errSecSuccess); } +void SOSCCEnsureAccessGroupOfKey(SecKeyRef publicKey, NSString* oldAgrp, NSString* newAgrp) +{ + NSData* publicKeyHash = CFBridgingRelease(SecKeyCopyPublicKeyHash(publicKey)); + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassKey, + (id)kSecAttrSynchronizable: (id)kSecAttrSynchronizableAny, + (id)kSecAttrApplicationLabel: publicKeyHash, + (id)kSecAttrAccessGroup: oldAgrp, + }; + + OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)query, + (__bridge CFDictionaryRef)@{ + (id)kSecAttrAccessGroup: newAgrp, + }); + + secnotice("octagon", "Ensuring key agrp ('%@' from '%@') status: %d", newAgrp, oldAgrp, (int)status); +}; + static NSString* createKeyLabel(NSDictionary *gestalt, NSString* circleName, NSString* prefix) { NSString *keyName = [NSString stringWithFormat:@"ID for %@-%@",SOSPeerGestaltGetName((__bridge CFDictionaryRef)(gestalt)), circleName]; @@ -2223,18 +2117,19 @@ static NSError* saveKeysToKeychain(SOSAccount* account, NSData* octagonSigningFu NSError* saveToKeychainError = nil; NSString* circleName = (__bridge NSString*)(SOSCircleGetName(account.trust.trustedCircle)); + NSString* signingPrefix = @"Octagon Peer Signing "; NSString* encryptionPrefix = @"Octagon Peer Encryption "; NSString* octagonSigningKeyName = createKeyLabel(account.gestalt, circleName, signingPrefix); NSString* octagonEncryptionKeyName = createKeyLabel(account.gestalt, circleName, encryptionPrefix); /* behavior mimics GeneratePermanentFullECKey_internal */ - saveOctagonKeysToKeychain(octagonSigningKeyName, octagonSigningFullKey, 384, octagonSigningPublicKeyRef, &saveToKeychainError); + SOSCCSaveOctagonKeysToKeychain(octagonSigningKeyName, octagonSigningFullKey, 384, octagonSigningPublicKeyRef, &saveToKeychainError); if(saveToKeychainError) { secerror("octagon: could not save signing key: %@", saveToKeychainError); return saveToKeychainError; } - saveOctagonKeysToKeychain(octagonEncryptionKeyName, octagonEncryptionFullKey, 384, octagonEncryptionPublicKeyRef, &saveToKeychainError); + SOSCCSaveOctagonKeysToKeychain(octagonEncryptionKeyName, octagonEncryptionFullKey, 384, octagonEncryptionPublicKeyRef, &saveToKeychainError); if(saveToKeychainError) { secerror("octagon: could not save encryption key: %@", saveToKeychainError); return saveToKeychainError; @@ -2290,6 +2185,57 @@ void SOSCCPerformUpdateOfAllOctagonKeys(CFDataRef octagonSigningFullKey, CFDataR CFReleaseNull(localError); } +void SOSCCPerformPreloadOfAllOctagonKeys(CFDataRef octagonSigningFullKey, CFDataRef octagonEncryptionFullKey, + SecKeyRef octagonSigningFullKeyRef, SecKeyRef octagonEncryptionFullKeyRef, + SecKeyRef octagonSigningPublicKeyRef, SecKeyRef octagonEncryptionPublicKeyRef, + void (^action)(CFErrorRef error)) +{ + CFErrorRef localError = NULL; + do_with_account_if_after_first_unlock(&localError, ^bool(SOSAccountTransaction *txn, CFErrorRef *err) { + + //save octagon key set to the keychain + NSError* saveError = nil; + saveError = saveKeysToKeychain(txn.account, (__bridge NSData*)octagonSigningFullKey, (__bridge NSData*)octagonEncryptionFullKey, + octagonSigningPublicKeyRef, octagonEncryptionPublicKeyRef); + + if(saveError) { + secerror("octagon-preload-keys: failed to save Octagon keys to the keychain: %@", saveError); + action((__bridge CFErrorRef)saveError); + return false; + } + + //now update the sos account to contain octagon keys + if(txn.account){ + txn.account.octagonSigningFullKeyRef = CFRetainSafe(octagonSigningFullKeyRef); + txn.account.octagonEncryptionFullKeyRef = CFRetainSafe(octagonEncryptionFullKeyRef); + } else { + secnotice("octagon-preload-keys", "No SOSAccount to update?"); + NSError *noAccountError = [NSError errorWithDomain:(__bridge NSString*)kSOSErrorDomain code:kSOSErrorNoAccount userInfo:@{NSLocalizedDescriptionKey : @"Device has no SOSAccount"}]; + action((__bridge CFErrorRef)noAccountError); + return false; + } + + secnotice("octagon-preload-keys", "Success! Octagon Keys Preloaded!"); + + action(nil); + return true; + }); + CFReleaseNull(localError); +} + +bool SOSCCSetCKKS4AllStatus(bool supports, CFErrorRef* error) +{ + CFErrorRef cfAccountError = NULL; + bool ret = do_with_account_if_after_first_unlock(&cfAccountError, ^bool(SOSAccountTransaction *txn, CFErrorRef *cferror) { + SOSAccountUpdatePeerInfo(txn.account, CFSTR("CKKS4All update"), cferror, ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *blockError) { + return SOSFullPeerInfoSetCKKS4AllSupport(fpi, supports, blockError); + }); + return true; + }); + CFErrorPropagate(cfAccountError, error); + return ret; +} + void SOSCCPerformWithTrustedPeers(void (^action)(CFSetRef sosPeerInfoRefs, CFErrorRef error)) { CFErrorRef cfAccountError = NULL; diff --git a/keychain/securityd/SecDbBackupManager.h b/keychain/securityd/SecDbBackupManager.h index 2459ad75..3e6c29a3 100644 --- a/keychain/securityd/SecDbBackupManager.h +++ b/keychain/securityd/SecDbBackupManager.h @@ -22,13 +22,11 @@ */ // For now at least, we'll support backups only on iOS and macOS -#define SECDB_BACKUPS_ENABLED ((TARGET_OS_OSX || TARGET_OS_IOS || TARGET_OS_IOSMAC) && !TARGET_OS_SIMULATOR && !TARGET_DARWINOS) +#define SECDB_BACKUPS_ENABLED ((TARGET_OS_OSX || TARGET_OS_IOS || TARGET_OS_MACCATALYST) && !TARGET_OS_SIMULATOR && !TARGET_DARWINOS) #if __OBJC2__ #import -#if !TARGET_OS_BRIDGE // Specifically needed until rdar://problem/40583882 lands #import -#endif #import "SecAKSObjCWrappers.h" #import "CheckV12DevEnabled.h" @@ -69,22 +67,20 @@ typedef NS_ENUM(NSInteger, SecDbBackupErrorCode) { SecDbBackupTestCodeFailure = 255, // support code for testing is falling over somehow }; -@interface SecDbBackupWrappedItemKey : NSObject +@interface SecDbBackupWrappedKey : NSObject @property (nonatomic) NSData* wrappedKey; @property (nonatomic) NSData* baguuid; @end @interface SecDbBackupManager : NSObject -+ (instancetype)manager; +// Nullable to make analyzer not complain in the case where the stub returns nil ++ (instancetype _Nullable)manager; - (instancetype)init NS_UNAVAILABLE; -#if !TARGET_OS_BRIDGE // Specifically needed until rdar://problem/40583882 lands -- (SecDbBackupWrappedItemKey* _Nullable)wrapItemKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error; -#else -- (SecDbBackupWrappedItemKey* _Nullable)wrapItemKey:(id)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error; -#endif - +- (NSData* _Nullable)currentBackupBagUUID; +- (SecDbBackupWrappedKey* _Nullable)wrapItemKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error; +- (SecDbBackupWrappedKey* _Nullable)wrapMetadataKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error; - (void)verifyBackupIntegrity:(bool)lightweight completion:(void (^)(NSDictionary* results, NSError* _Nullable error))completion; @@ -96,3 +92,4 @@ NS_ASSUME_NONNULL_END // Declare C functions here bool SecDbBackupCreateOrLoadBackupInfrastructure(CFErrorRef _Nullable * _Nonnull error); +void SecDbResetBackupManager(void); // For testing. Here so SecKeychainDbReset can use it. diff --git a/keychain/securityd/SecDbBackupManager.m b/keychain/securityd/SecDbBackupManager.m index ff4dc45a..b2a5c420 100644 --- a/keychain/securityd/SecDbBackupManager.m +++ b/keychain/securityd/SecDbBackupManager.m @@ -22,11 +22,12 @@ */ #import "SecDbBackupManager.h" +#import "sec_action.h" NSString* const KeychainBackupsErrorDomain = @"com.apple.security.keychain.backups"; // oink oink -@implementation SecDbBackupWrappedItemKey +@implementation SecDbBackupWrappedKey + (BOOL)supportsSecureCoding { return YES; } @@ -44,36 +45,7 @@ NSString* const KeychainBackupsErrorDomain = @"com.apple.security.keychain.backu } @end -#if !SECDB_BACKUPS_ENABLED - -@implementation SecDbBackupManager - -+ (instancetype)manager -{ - return nil; -} - -- (void)verifyBackupIntegrity:(bool)lightweight - completion:(void (^)(NSDictionary* results, NSError* _Nullable error))completion -{ - completion(nil, [NSError errorWithDomain:KeychainBackupsErrorDomain - code:SecDbBackupNotSupported - userInfo:@{NSLocalizedDescriptionKey : @"platform doesn't do backups"}]); -} - -- (SecDbBackupWrappedItemKey* _Nullable)wrapItemKey:(id)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error -{ - return nil; -} - -@end - -bool SecDbBackupCreateOrLoadBackupInfrastructure(CFErrorRef* error) -{ - return true; -} - -#else // SECDB_BACKUPS_ENABLED is true, roll out the code +#if SECDB_BACKUPS_ENABLED // The bottom of this file contains stubs in case the feature is disabled #import "SecDbBackupManager_Internal.h" #include @@ -101,6 +73,11 @@ bool SecDbBackupCreateOrLoadBackupInfrastructure(CFErrorRef* error) return ok; } +void SecDbResetBackupManager() { + secnotice("SecDbBackup", "Resetting backup manager"); + [SecDbBackupManager resetManager]; +} + // Reading from disk is relatively expensive. Keep wrapped key in memory and just delete the unwrapped copy on lock @interface InMemoryKCSK : NSObject @property aks_ref_key_t refKey; @@ -190,7 +167,8 @@ static SecDbBackupManager* staticManager; + (void)resetManager { if (staticManager) { - staticManager = [SecDbBackupManager new]; + secnotice("SecDbBackup", "Resetting backup manager"); + staticManager = [[SecDbBackupManager alloc] init]; } } @@ -215,7 +193,7 @@ static SecDbBackupManager* staticManager; } CFTypeRef cftype = NULL; CFErrorRef cferr = NULL; - const uint8_t* derp = der_decode_plist(kCFAllocatorDefault, NSPropertyListImmutable, &cftype, &cferr, bytes, bytes + len); + const uint8_t* derp = der_decode_plist(kCFAllocatorDefault, &cftype, &cferr, bytes, bytes + len); free(bytes); if (derp == NULL || derp != (bytes + len) || cftype == NULL) { [self fillError:error code:SecDbBackupMalformedKCSKDataOnDisk underlying:CFBridgingRelease(cferr) description:@"Unable to parse der data"]; @@ -227,6 +205,11 @@ static SecDbBackupManager* staticManager; error:error]; } +- (NSData*)currentBackupBagUUID +{ + return [_bagIdentity.baguuid copy]; +} + #pragma mark - Fixup And Verification - (void)verifyBackupIntegrity:(bool)lightweight @@ -438,8 +421,6 @@ static SecDbBackupManager* staticManager; return bad_keybag_handle; } - // TODO: verify that bag is still signed, rdar://problem/46702467 - secnotice("SecDbBackup", "Backup bag loaded and verified."); // Must load readBag's identity because the hash from AKS is unstable. @@ -451,6 +432,7 @@ static SecDbBackupManager* staticManager; - (BOOL)onQueueReloadDefaultBackupBagWithError:(NSError**)error { + dispatch_assert_queue(_queue); if (_handle != bad_keybag_handle) { aks_unload_bag(_handle); } @@ -541,6 +523,7 @@ static SecDbBackupManager* staticManager; - (InMemoryKCSK*)onQueueReadKCSKFromDiskForClass:(keyclass_t)keyclass error:(NSError**)error { + dispatch_assert_queue(_queue); __block bool ok = true; __block CFErrorRef cfError = NULL; __block NSData* readUUID; @@ -610,6 +593,7 @@ static SecDbBackupManager* staticManager; - (SFECKeyPair*)onQueueFetchKCSKForKeyclass:(keyclass_t)keyclass error:(NSError**)error { + dispatch_assert_queue(_queue); assert(error); assert(_bagIdentity); assert(_handle != bad_keybag_handle); @@ -889,9 +873,23 @@ static SecDbBackupManager* staticManager; #pragma mark - Item Encryption -- (SecDbBackupWrappedItemKey*)wrapItemKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error +- (SecDbBackupWrappedKey*)wrapItemKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error { assert(error); + // We don't care about rolled keyclasses; we care about semantic classes + if (keyclass > key_class_last) { + static dispatch_once_t rolledkeyclassnotifytoken; + static sec_action_t rolledkeyclassnotifyaction; + dispatch_once(&rolledkeyclassnotifytoken, ^{ + rolledkeyclassnotifyaction = sec_action_create("rolledkeyclassnotifyaction", 300); + sec_action_set_handler(rolledkeyclassnotifyaction, ^{ + secnotice("SecDbBackup", "Rolled keyclass for item wrap, %d -> %d", keyclass, SecAKSSanitizedKeyclass(keyclass)); + }); + }); + sec_action_perform(rolledkeyclassnotifyaction); + keyclass = SecAKSSanitizedKeyclass(keyclass); + } + if (keyclass == key_class_akpu) { secwarning("SecDbBackup: Don't tempt me Frodo!"); [self fillError:error code:SecDbBackupInvalidArgument underlying:nil description:@"Do not call wrapItemKey with class akpu"]; @@ -905,7 +903,7 @@ static SecDbBackupManager* staticManager; return nil; } - __block SecDbBackupWrappedItemKey* backupWrappedKey; + __block SecDbBackupWrappedKey* backupWrappedKey; __block NSMutableData* wrappedKey = [NSMutableData dataWithLength:APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN]; __block NSError* localError; @@ -928,7 +926,7 @@ static SecDbBackupManager* staticManager; return; } } - backupWrappedKey = [SecDbBackupWrappedItemKey new]; + backupWrappedKey = [SecDbBackupWrappedKey new]; backupWrappedKey.wrappedKey = [NSKeyedArchiver archivedDataWithRootObject:wrappedAndSigned requiringSecureCoding:YES error:&localError]; backupWrappedKey.baguuid = self->_bagIdentity.baguuid; }); @@ -944,6 +942,7 @@ static SecDbBackupManager* staticManager; - (SFSignedData*)onQueueSignData:(NSMutableData*)data withKCSKForKeyclass:(keyclass_t)keyclass error:(NSError**)error { + dispatch_assert_queue(_queue); SFECKeyPair* kcsk = [self onQueueFetchKCSKForKeyclass:keyclass error:error]; if (!kcsk) { return nil; @@ -953,6 +952,19 @@ static SecDbBackupManager* staticManager; return [op sign:data withKey:kcsk error:error]; } +#pragma mark - Metadata Key Encryption + +- (SecDbBackupWrappedKey*)wrapMetadataKey:(_SFAESKey *)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error +{ + // We don't care about rolled keyclasses; we care about semantic classes + if (keyclass > key_class_last) { + secnotice("SecDbBackup", "Rolled keyclass for metadata wrap, %d -> %d", keyclass, SecAKSSanitizedKeyclass(keyclass)); + keyclass = SecAKSSanitizedKeyclass(keyclass); + } + // For now, this is identical to item encryption. This will likely change when ACLs are implemented + return [self wrapItemKey:key forKeyclass:keyclass error:error]; +} + #pragma mark - Testing Helpers - (keybag_handle_t)createBackupBagWithSecret:(NSData*)secret error:(NSError**)error @@ -1052,4 +1064,30 @@ static SecDbBackupManager* staticManager; @end -#endif // SECDB_BACKUPS_ENABLED +#else // SECDB_BACKUPS_ENABLED is false +#pragma mark - Stubs for when backups are disabled + +@implementation SecDbBackupManager + ++ (instancetype)manager +{ + return nil; +} + +- (NSData* _Nullable)currentBackupBagUUID {return nil;} +- (SecDbBackupWrappedKey* _Nullable)wrapItemKey:(id)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error {return nil;} +- (SecDbBackupWrappedKey* _Nullable)wrapMetadataKey:(SFAESKey*)key forKeyclass:(keyclass_t)keyclass error:(NSError**)error {return nil;} +- (void)verifyBackupIntegrity:(bool)lightweight + completion:(void (^)(NSDictionary* results, NSError* _Nullable error))completion +{ + completion(nil, [NSError errorWithDomain:KeychainBackupsErrorDomain + code:SecDbBackupNotSupported + userInfo:@{NSLocalizedDescriptionKey : @"platform doesn't do backups"}]); +} + +@end + +bool SecDbBackupCreateOrLoadBackupInfrastructure(CFErrorRef* error) {return true;} +void SecDbResetBackupManager() {} + +#endif // SECDB_BACKUPS_ENABLED diff --git a/keychain/securityd/SecDbBackupManager_Internal.h b/keychain/securityd/SecDbBackupManager_Internal.h index 71a3b3eb..24b7499e 100644 --- a/keychain/securityd/SecDbBackupManager_Internal.h +++ b/keychain/securityd/SecDbBackupManager_Internal.h @@ -63,7 +63,7 @@ // Pure utilities - (NSData*)getSHA256OfData:(NSData*)data; -- (SFECKeyPair*)ECKeyPairFromDerBytes:(void*)bytes length:(size_t)len error:(NSError**)error; +- (SFECKeyPair*)getECKeyPairFromDERBytes:(void*)bytes length:(size_t)len error:(NSError**)error; @end diff --git a/keychain/securityd/SecDbItem.c b/keychain/securityd/SecDbItem.c index 5b63b41a..4e28f17c 100644 --- a/keychain/securityd/SecDbItem.c +++ b/keychain/securityd/SecDbItem.c @@ -337,8 +337,20 @@ static CFTypeRef SecDbItemGetCachedValue(SecDbItemRef item, const SecDbAttr *des } CFMutableDictionaryRef SecDbItemCopyPListWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error) { + return SecDbItemCopyPListWithFlagAndSkip(item, mask, 0, error); +} + +CFMutableDictionaryRef SecDbItemCopyPListWithFlagAndSkip(SecDbItemRef item, + CFOptionFlags mask, + CFOptionFlags flagsToSkip, + CFErrorRef *error) +{ CFMutableDictionaryRef dict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); SecDbForEachAttrWithMask(item->class, desc, mask) { + if((desc->flags & flagsToSkip) != 0) { + break; + } + CFTypeRef value = SecDbItemGetValue(item, desc, error); if (value) { if (!CFEqual(kCFNull, value)) { @@ -559,28 +571,62 @@ static bool SecDbItemGetBoolValue(SecDbItemRef item, const SecDbAttr *desc, bool return true; } +static void SecDbItemAppendAttributeToDescription(SecDbItemRef item, const SecDbAttr *attr, CFMutableStringRef mdesc) +{ + // In non-debug builds, the following attributes aren't very useful. +#ifndef DEBUG + if (CFEqual(CFSTR("data"), attr->name)|| + CFEqual(CFSTR("v_pk"), attr->name)) { + return; + } +#endif + + CFTypeRef value = SecDbItemGetValue(item, attr, NULL); + if (value && value != kCFNull) { + CFStringAppend(mdesc, CFSTR(",")); + CFStringAppend(mdesc, attr->name); + CFStringAppend(mdesc, CFSTR("=")); + if (CFEqual(CFSTR("data"), attr->name)) { + CFStringAppendEncryptedData(mdesc, value); + } else if (CFEqual(CFSTR("v_Data"), attr->name)) { + CFStringAppend(mdesc, CFSTR("")); + } else if (isData(value)) { + CFStringAppendHexData(mdesc, value); + } else { + CFStringAppendFormat(mdesc, 0, CFSTR("%@"), value); + } + } +} + static CFStringRef SecDbItemCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { CFStringRef desc; if (isDictionary(formatOptions) && CFDictionaryContainsKey(formatOptions, kSecDebugFormatOption)) { SecDbItemRef item = (SecDbItemRef)cf; CFMutableStringRef mdesc = CFStringCreateMutable(CFGetAllocator(cf), 0); CFStringAppendFormat(mdesc, NULL, CFSTR("<%@"), item->class->name); + + // First, the primary key attributes + SecDbForEachAttrWithMask(item->class, attr, kSecDbPrimaryKeyFlag) { + SecDbItemAppendAttributeToDescription(item, attr, mdesc); + } + + CFStringAppend(mdesc, CFSTR(", |otherAttr")); + // tombstone values are very important, and should print next SecDbForEachAttr(item->class, attr) { - CFTypeRef value = SecDbItemGetValue(item, attr, NULL); - if (value) { - CFStringAppend(mdesc, CFSTR(",")); - CFStringAppend(mdesc, attr->name); - CFStringAppend(mdesc, CFSTR("=")); - if (CFEqual(CFSTR("data"), attr->name)) { - CFStringAppendEncryptedData(mdesc, value); - } else if (CFEqual(CFSTR("v_Data"), attr->name)) { - CFStringAppend(mdesc, CFSTR("")); - } else if (isData(value)) { - CFStringAppendHexData(mdesc, value); - } else { - CFStringAppendFormat(mdesc, 0, CFSTR("%@"), value); - } - } + if(CFEqualSafe(CFSTR("tomb"), attr->name)) { + SecDbItemAppendAttributeToDescription(item, attr, mdesc); + } + } + + // And finally, everything else + SecDbForEachAttr(item->class, attr) { + if((attr->flags & kSecDbPrimaryKeyFlag) != 0) { + continue; + } + if(CFEqualSafe(CFSTR("tomb"), attr->name)) { + continue; + } + SecDbItemAppendAttributeToDescription(item, attr, mdesc); } CFStringAppend(mdesc, CFSTR(">")); desc = mdesc; @@ -886,6 +932,28 @@ bool SecDbItemSetValueWithName(SecDbItemRef item, CFStringRef name, CFTypeRef va return false; } +bool SecItemPreserveAttribute(SecDbItemRef target, SecDbItemRef source, const SecDbAttr* attr) { + CFErrorRef cferror = nil; + CFTypeRef v = SecDbItemGetValue(source, attr, &cferror); + if(cferror) { + secnotice("secitem", "Merging: unable to get attribute (%@) : %@", attr->name, cferror); + CFReleaseNull(cferror); + return false; + } + if(!v || CFEqualSafe(v, kCFNull)) { + return true; + } + secnotice("secitem", "Preserving existing data for %@", attr->name); + SecDbItemSetValue(target, attr, v, &cferror); + if(cferror) { + secnotice("secitem", "Unable to set attribute (%@) : %@", attr->name, cferror); + CFReleaseNull(cferror); + return false; + } + return true; +} + + bool SecDbItemSetAccessControl(SecDbItemRef item, SecAccessControlRef access_control, CFErrorRef *error) { bool ok = true; if (item->_edataState == kSecDbItemClean) @@ -1058,7 +1126,7 @@ static bool SecDbItemMakeYounger(SecDbItemRef new_item, SecDbItemRef old_item, C return attr && SecDbItemMakeAttrYounger(new_item, old_item, attr, error); } -static SecDbItemRef SecDbItemCopyTombstone(SecDbItemRef item, CFBooleanRef makeTombStone, CFErrorRef *error) { +static SecDbItemRef SecDbItemCopyTombstone(SecDbItemRef item, CFBooleanRef makeTombStone, bool tombstone_time_from_item, CFErrorRef *error) { SecDbItemRef new_item = SecDbItemCreate(CFGetAllocator(item), item->class, item->keybag); SecDbForEachAttr(item->class, attr) { if (attr->kind == kSecDbTombAttr) { @@ -1075,6 +1143,10 @@ static SecDbItemRef SecDbItemCopyTombstone(SecDbItemRef item, CFBooleanRef makeT break; } } else if (attr->kind == kSecDbModificationDateAttr) { + if(tombstone_time_from_item) { + SecItemPreserveAttribute(new_item, item, attr); + } + if (!SecDbItemMakeAttrYounger(new_item, item, attr, error)) { CFReleaseNull(new_item); break; @@ -1296,7 +1368,7 @@ static SecDbQueryRef SecDbQueryCreateWithItemPrimaryKey(SecDbItemRef item, CFErr if (!dict) return NULL; - SecDbQueryRef query = query_create(item->class, NULL, NULL, error); + SecDbQueryRef query = query_create(item->class, NULL, NULL, NULL, error); if (query) { CFReleaseSafe(query->q_item); query->q_item = dict; @@ -1343,7 +1415,8 @@ static bool SecDbItemIsCorrupt(SecDbItemRef item, bool *is_corrupt, CFErrorRef * if (storedSHA1 && computedSHA1 && !CFEqual(storedSHA1, computedSHA1)) { CFStringRef storedHex = CFDataCopyHexString(storedSHA1), computedHex = CFDataCopyHexString(computedSHA1); secerror("error %@ %@ != %@ item %@ (corrupted)", sha1attr->name, storedHex, computedHex, item); - __security_simulatecrash(CFSTR("Corrupted item (sha1 mismatch) found in keychain"), __sec_exception_code_CorruptItem); + // Do not simulate crash for this condition. + // The keychain hashes floating point numbers which causes many false positives, this is not fixable except by major surgery CFReleaseSafe(storedHex); CFReleaseSafe(computedHex); *is_corrupt = true; @@ -1472,11 +1545,21 @@ bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFEr return ok & SecErrorPropagate(localError, error); // Don't use && here! } -bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error) { +bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, bool always_use_uuid_from_new_item, CFErrorRef *error) { return SecDbItemInsertOrReplace(item, dbconn, error, ^(SecDbItemRef old_item, SecDbItemRef *replace) { if (SecDbItemIsTombstone(old_item)) { CFRetain(item); *replace = item; + + // If the caller doesn't care about the UUID, then use old_item's UUID + // Note: this will modify item! + if(!always_use_uuid_from_new_item) { + SecDbForEachAttr(SecDbItemGetClass(item), attr) { + if(CFEqual(attr->name, v10itemuuid.name)) { + SecItemPreserveAttribute(item, old_item, attr); + } + } + } } }); } @@ -1700,7 +1783,7 @@ bool SecDbItemUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnecti if (ok && !pk_equal && !CFEqualSafe(makeTombstone, kCFBooleanFalse)) { /* The primary key of new_item is different than that of old_item, we have been asked to make a tombstone so leave one for the old_item. */ - SecDbItemRef tombstone = SecDbItemCopyTombstone(old_item, makeTombstone, error); + SecDbItemRef tombstone = SecDbItemCopyTombstone(old_item, makeTombstone, false, error); ok = tombstone; if (tombstone) { ok = (SecDbItemClearRowId(tombstone, error) && @@ -1713,10 +1796,10 @@ bool SecDbItemUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnecti } // Replace the object with a tombstone -bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, CFBooleanRef makeTombstone, CFErrorRef *error) { +bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, CFBooleanRef makeTombstone, bool tombstone_time_from_item, CFErrorRef *error) { bool ok = false; if (!CFEqualSafe(makeTombstone, kCFBooleanFalse)) { - SecDbItemRef tombstone = SecDbItemCopyTombstone(item, makeTombstone, error); + SecDbItemRef tombstone = SecDbItemCopyTombstone(item, makeTombstone, tombstone_time_from_item, error); if (tombstone) { ok = SecDbItemDoUpdate(item, tombstone, dbconn, error, ^bool(const SecDbAttr *attr) { return attr->kind == kSecDbRowIdAttr; diff --git a/keychain/securityd/SecDbItem.h b/keychain/securityd/SecDbItem.h index 586b8c00..1d9966cd 100644 --- a/keychain/securityd/SecDbItem.h +++ b/keychain/securityd/SecDbItem.h @@ -81,6 +81,7 @@ enum { kSecDbSyncPrimaryKeyV0 = (1 << 14), kSecDbSyncPrimaryKeyV2 = (1 << 15), kSecDbSyncFlag = (1 << 16), + kSecDbSyncSOSCannotSyncFlag= (1 << 17), }; #define SecVersionDbFlag(v) ((v & 0xFF) << 8) @@ -176,6 +177,10 @@ bool SecDbItemSetValue(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value bool SecDbItemSetValues(SecDbItemRef item, CFDictionaryRef values, CFErrorRef *error); bool SecDbItemSetValueWithName(SecDbItemRef item, CFStringRef name, CFTypeRef value, CFErrorRef *error); +// Copies a given attribute from source to target. If source does not have that atttribute, +// doesn't modify target. +bool SecItemPreserveAttribute(SecDbItemRef target, SecDbItemRef source, const SecDbAttr* attr); + sqlite3_int64 SecDbItemGetRowId(SecDbItemRef item, CFErrorRef *error); bool SecDbItemSetRowId(SecDbItemRef item, sqlite3_int64 rowid, CFErrorRef *error); bool SecDbItemClearRowId(SecDbItemRef item, CFErrorRef *error); @@ -189,6 +194,14 @@ bool SecDbItemIsTombstone(SecDbItemRef item); CFMutableDictionaryRef SecDbItemCopyPListWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error); +/* + * Note that "mask" requires a single option, but flagsToSkip can have any number combined. + */ +CFMutableDictionaryRef SecDbItemCopyPListWithFlagAndSkip(SecDbItemRef item, + CFOptionFlags mask, + CFOptionFlags flagsToSkip, + CFErrorRef *error); + CFDataRef SecDbItemGetPrimaryKey(SecDbItemRef item, CFErrorRef *error); CFDataRef SecDbItemGetSHA1(SecDbItemRef item, CFErrorRef *error); @@ -214,9 +227,10 @@ bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFEr // SecDbItemInsertOrReplace returns an error even when it succeeds; use this to determine if it's spurious bool SecErrorIsSqliteDuplicateItemError(CFErrorRef error); -bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error); +// Note: this function might modify item, unless always_use_uuid_from_new_item is true +bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, bool always_use_uuid_from_new_item, CFErrorRef *error); -bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, CFBooleanRef makeTombstone, CFErrorRef *error); +bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, CFBooleanRef makeTombstone, bool tombstone_time_from_item, CFErrorRef *error); bool SecDbItemDoDeleteSilently(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error); diff --git a/keychain/securityd/SecDbKeychainItem.h b/keychain/securityd/SecDbKeychainItem.h index ce889868..83aaaa5d 100644 --- a/keychain/securityd/SecDbKeychainItem.h +++ b/keychain/securityd/SecDbKeychainItem.h @@ -32,34 +32,38 @@ #include "keychain/securityd/SecDbItem.h" #include "keychain/securityd/SecDbQuery.h" +CF_ASSUME_NONNULL_BEGIN + __BEGIN_DECLS -bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context, - CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, bool useDefaultIV, CFErrorRef *error); -bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context, - CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, CFDataRef *bkUUID, bool useDefaultIV, CFErrorRef *error); -bool ks_encrypt_data_legacy(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context, - CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, bool useDefaultIV, CFErrorRef *error); // used for backup -bool ks_decrypt_data(keybag_handle_t keybag, CFTypeRef cryptoOp, SecAccessControlRef *paccess_control, CFDataRef acm_context, +bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef _Nullable access_control, CFDataRef _Nullable acm_context, + CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef _Nullable *_Nonnull pBlob, bool useDefaultIV, CFErrorRef _Nullable *_Nullable error); +bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef _Nullable access_control, CFDataRef _Nullable acm_context, + CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef _Nullable *_Nonnull pBlob, CFDataRef _Nullable *_Nullable bkUUID, bool useDefaultIV, CFErrorRef _Nullable *_Nullable error); +bool ks_encrypt_data_legacy(keybag_handle_t keybag, SecAccessControlRef _Nullable access_control, CFDataRef _Nullable acm_context, + CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef _Nullable *_Nonnull pBlob, bool useDefaultIV, CFErrorRef _Nullable *_Nullable error); // used for backup +bool ks_decrypt_data(keybag_handle_t keybag, CFTypeRef cryptoOp, SecAccessControlRef _Nullable *_Nullable paccess_control, CFDataRef acm_context, CFDataRef blob, const SecDbClass *db_class, CFArrayRef caller_access_groups, - CFMutableDictionaryRef *attributes_p, uint32_t *version_p, bool decryptSecretData, keyclass_t* outKeyclass, CFErrorRef *error); + CFMutableDictionaryRef _Nullable *_Nullable attributes_p, uint32_t *_Nullable version_p, bool decryptSecretData, keyclass_t*_Nullable outKeyclass, CFErrorRef _Nullable *_Nullable error); bool s3dl_item_from_data(CFDataRef edata, Query *q, CFArrayRef accessGroups, - CFMutableDictionaryRef *item, SecAccessControlRef *access_control, keyclass_t* keyclass, CFErrorRef *error); -SecDbItemRef SecDbItemCreateWithBackupDictionary(CFAllocatorRef allocator, const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef *error); -bool SecDbItemExtractRowIdFromBackupDictionary(SecDbItemRef item, CFDictionaryRef dict, CFErrorRef *error); -bool SecDbItemInferSyncable(SecDbItemRef item, CFErrorRef *error); + CFMutableDictionaryRef _Nonnull *_Nonnull item, SecAccessControlRef _Nullable *_Nullable access_control, keyclass_t *_Nullable keyclass, CFErrorRef _Nullable *_Nullable error); +SecDbItemRef _Nullable SecDbItemCreateWithBackupDictionary(const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef _Nullable *_Nullable error); +bool SecDbItemExtractRowIdFromBackupDictionary(SecDbItemRef item, CFDictionaryRef dict, CFErrorRef _Nullable *_Nullable error); +bool SecDbItemInferSyncable(SecDbItemRef item, CFErrorRef _Nullable *_Nullable error); -CFTypeRef SecDbKeychainItemCopyPrimaryKey(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error); -CFTypeRef SecDbKeychainItemCopySHA256PrimaryKey(SecDbItemRef item, CFErrorRef *error); -CFTypeRef SecDbKeychainItemCopySHA1(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error); -CFTypeRef SecDbKeychainItemCopyCurrentDate(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error); -CFTypeRef SecDbKeychainItemCopyEncryptedData(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error); +CFTypeRef _Nullable SecDbKeychainItemCopyPrimaryKey(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef _Nullable *_Nullable error); +CFTypeRef _Nullable SecDbKeychainItemCopySHA256PrimaryKey(SecDbItemRef item, CFErrorRef _Nullable *_Nullable error); +CFTypeRef _Nullable SecDbKeychainItemCopySHA1(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef _Nullable *_Nullable error); +CFTypeRef _Nullable SecDbKeychainItemCopyCurrentDate(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef _Nullable *_Nullable error); +CFTypeRef _Nullable SecDbKeychainItemCopyEncryptedData(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef _Nullable *_Nullable error); -SecAccessControlRef SecDbItemCopyAccessControl(SecDbItemRef item, CFErrorRef *error); -bool SecDbItemSetAccessControl(SecDbItemRef item, SecAccessControlRef access_control, CFErrorRef *error); +SecAccessControlRef _Nullable SecDbItemCopyAccessControl(SecDbItemRef item, CFErrorRef _Nullable *_Nullable error); +bool SecDbItemSetAccessControl(SecDbItemRef item, SecAccessControlRef access_control, CFErrorRef _Nullable *_Nullable error); void SecDbResetMetadataKeys(void); __END_DECLS +CF_ASSUME_NONNULL_END + #endif /* _SECURITYD_SECKEYCHAINITEM_H_ */ diff --git a/keychain/securityd/SecDbKeychainItem.m b/keychain/securityd/SecDbKeychainItem.m index 4ad9c892..cd7032e0 100644 --- a/keychain/securityd/SecDbKeychainItem.m +++ b/keychain/securityd/SecDbKeychainItem.m @@ -78,25 +78,25 @@ static CFDataRef kc_create_auth_data(SecAccessControlRef access_control, CFDicti static CFDataRef kc_copy_access_groups_data(CFArrayRef access_groups, CFErrorRef *error); #endif -static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef pl, CFOptionFlags mutability, CFPropertyListRef* cf, CFErrorRef *error, +static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef pl, CFPropertyListRef* cf, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, + const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end)); -static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFDictionaryRef* dictionary, CFErrorRef *error, +static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator, CFDictionaryRef* dictionary, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, + const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end)); -static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error, +static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, + const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end)); -static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFArrayRef* array, CFErrorRef *error, +static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFArrayRef* array, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, + const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end)); -static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFSetRef* set, CFErrorRef *error, +static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFSetRef* set, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, + const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end)); const uint32_t kUseDefaultIVMask = 1<<31; @@ -305,13 +305,13 @@ ks_warn_non_device_keybag(void) sec_action_perform(action); } -bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context, - CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, bool useDefaultIV, CFErrorRef *error) { +bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef _Nullable access_control, CFDataRef _Nullable acm_context, + CFDictionaryRef _Nonnull secretData, CFDictionaryRef _Nonnull attributes, CFDictionaryRef _Nonnull authenticated_attributes, CFDataRef _Nonnull *pBlob, bool useDefaultIV, CFErrorRef *error) { return ks_encrypt_data_with_backupuuid(keybag, access_control, acm_context, secretData, attributes, authenticated_attributes, pBlob, NULL, useDefaultIV, error); } -bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context, - CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, CFDataRef *bkUUID, bool useDefaultIV, CFErrorRef *error) { +bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef _Nullable access_control, CFDataRef _Nullable acm_context, + CFDictionaryRef _Nonnull secretData, CFDictionaryRef _Nonnull attributes, CFDictionaryRef _Nonnull authenticated_attributes, CFDataRef _Nonnull *pBlob, CFDataRef _Nullable *bkUUID, bool useDefaultIV, CFErrorRef *error) { if (keybag != KEYBAG_DEVICE) { ks_warn_non_device_keybag(); @@ -331,8 +331,8 @@ bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef if (SecAccessControlGetConstraints(access_control)) { NSMutableDictionary* allAttributes = [(__bridge NSDictionary*)attributes mutableCopy]; - [allAttributes addEntriesFromDictionary:(__bridge NSDictionary*)secretData]; - return ks_encrypt_data_legacy(keybag, access_control, acm_context, (__bridge CFDictionaryRef)allAttributes, authenticated_attributes, pBlob, useDefaultIV, error); + [allAttributes addEntriesFromDictionary:(__bridge NSDictionary*_Nonnull)secretData]; + return ks_encrypt_data_legacy(keybag, access_control, acm_context, (__bridge CFDictionaryRef _Nonnull)allAttributes, authenticated_attributes, pBlob, useDefaultIV, error); } bool success = false; @@ -342,7 +342,7 @@ bool ks_encrypt_data_with_backupuuid(keybag_handle_t keybag, SecAccessControlRef metadataAttributes[@"SecAccessControl"] = (__bridge_transfer NSData*)SecAccessControlCopyData(access_control); NSString* tamperCheck = [[NSUUID UUID] UUIDString]; // can use the item persistent reference when that starts getting filled in - SecDbKeychainItemV7* item = [[SecDbKeychainItemV7 alloc] initWithSecretAttributes:(__bridge NSDictionary*)secretData metadataAttributes:metadataAttributes tamperCheck:tamperCheck keyclass:key_class]; + SecDbKeychainItemV7* item = [[SecDbKeychainItemV7 alloc] initWithSecretAttributes:(__bridge NSDictionary*_Nonnull)secretData metadataAttributes:metadataAttributes tamperCheck:tamperCheck keyclass:key_class]; NSError* localError = nil; NSData* encryptedBlob = [item encryptedBlobWithKeybag:keybag accessControl:access_control acmContext:(__bridge NSData*)acm_context error:&localError]; @@ -789,7 +789,7 @@ static bool kc_attribs_key_encrypted_data_from_blob(keybag_handle_t keybag, cons CFDataRef ed = NULL; bool ok = false; - der_decode_plist(NULL, kCFPropertyListImmutable, (CFPropertyListRef*)&blob_dict, NULL, blob_data, blob_data + blob_data_len); + der_decode_plist(NULL, (CFPropertyListRef*)&blob_dict, NULL, blob_data, blob_data + blob_data_len); require_action_quiet(blob_dict, out, SecError(errSecDecode, error, CFSTR("kc_attribs_key_encrypted_data_from_blob: failed to decode 'blob data'"))); if (!ks_separate_data_and_key(blob_dict, &ed, &key_data)) { @@ -804,7 +804,7 @@ static bool kc_attribs_key_encrypted_data_from_blob(keybag_handle_t keybag, cons require_quiet(external_data = ks_ref_key_get_external_data(keybag, key_data, &tmp_ref_key, &external_data_len, error), out); CFPropertyListRef external_data_dict = NULL; - der_decode_plist(NULL, kCFPropertyListImmutable, &external_data_dict, NULL, external_data, external_data + external_data_len); + der_decode_plist(NULL, &external_data_dict, NULL, external_data, external_data + external_data_len); require_action_quiet(external_data_dict, out, SecError(errSecDecode, error, CFSTR("kc_attribs_key_encrypted_data_from_blob: failed to decode 'encrypted data dictionary'"))); acl = CFDictionaryCreateMutableCopy(NULL, 0, external_data_dict); SecDbForEachAttrWithMask(class, attr_desc, kSecDbInAuthenticatedDataFlag) { @@ -902,7 +902,7 @@ static CFDataRef kc_copy_protection_data(SecAccessControlRef access_control) static CFTypeRef kc_copy_protection_from(const uint8_t *der, const uint8_t *der_end) { CFTypeRef result = NULL; - der_decode_plist(NULL, kCFPropertyListImmutable, &result, NULL, der, der_end); + der_decode_plist(NULL, &result, NULL, der, der_end); return result; } @@ -925,8 +925,8 @@ CFMutableDictionaryRef s3dl_item_v2_decode(CFDataRef plain, CFErrorRef *error) { return dictionaryFromPlist(item, error); } -static const uint8_t* (^s3dl_item_v3_decode_repair_date)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*) = - ^const uint8_t*(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { +static const uint8_t* (^s3dl_item_v3_decode_repair_date)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*) = + ^const uint8_t*(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) { if (error && CFEqualSafe(CFErrorGetDomain(*error), sSecDERErrorDomain) && CFErrorGetCode(*error) == kSecDERErrorUnknownEncoding) { CFAbsoluteTime date = 0; CFCalendarRef calendar = CFCalendarCreateWithIdentifier(allocator, kCFGregorianCalendar); @@ -950,10 +950,10 @@ CFMutableDictionaryRef s3dl_item_v3_decode(CFDataRef plain, CFErrorRef *error) { CFPropertyListRef item = NULL; const uint8_t *der_beg = CFDataGetBytePtr(plain); const uint8_t *der_end = der_beg + CFDataGetLength(plain); - const uint8_t *der = der_decode_plist(0, kCFPropertyListMutableContainers, &item, error, der_beg, der_end); + const uint8_t *der = der_decode_plist(0, &item, error, der_beg, der_end); if (!der && error && CFEqualSafe(CFErrorGetDomain(*error), sSecDERErrorDomain) && CFErrorGetCode(*error) == kSecDERErrorUnknownEncoding) { CFReleaseNull(*error); - der = der_decode_plist_with_repair(0, kCFPropertyListMutableContainers, &item, error, der_beg, der_end, s3dl_item_v3_decode_repair_date); + der = der_decode_plist_with_repair(0, &item, error, der_beg, der_end, s3dl_item_v3_decode_repair_date); } if (der && der != der_end) { SecCFCreateError(errSecDecode, kSecErrorDomain, CFSTR("trailing garbage at end of decrypted item"), NULL, error); @@ -1145,7 +1145,7 @@ bool SecDbItemInferSyncable(SecDbItemRef item, CFErrorRef *error) src_keybag is normally the backup keybag. dst_keybag is normally the device keybag. */ -SecDbItemRef SecDbItemCreateWithBackupDictionary(CFAllocatorRef allocator, const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef *error) +SecDbItemRef SecDbItemCreateWithBackupDictionary(const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef *error) { CFDataRef edata = CFDictionaryGetValue(dict, CFSTR("v_Data")); SecDbItemRef item = NULL; @@ -1322,10 +1322,10 @@ out: return result; } -static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef allocator, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, + const uint8_t* (^repairBlock)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*)) { if (NULL == der) { @@ -1341,38 +1341,38 @@ static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef allocator, CFO switch (tag) { case CCDER_NULL: - return der_decode_null(allocator, mutability, (CFNullRef*)pl, error, der, der_end); + return der_decode_null(allocator, (CFNullRef*)pl, error, der, der_end); case CCDER_BOOLEAN: - return der_decode_boolean(allocator, mutability, (CFBooleanRef*)pl, error, der, der_end); + return der_decode_boolean(allocator, (CFBooleanRef*)pl, error, der, der_end); case CCDER_OCTET_STRING: - return der_decode_data(allocator, mutability, (CFDataRef*)pl, error, der, der_end); + return der_decode_data(allocator, (CFDataRef*)pl, error, der, der_end); case CCDER_GENERALIZED_TIME: { - const uint8_t* der_result = der_decode_date(allocator, mutability, (CFDateRef*)pl, error, der, der_end); + const uint8_t* der_result = der_decode_date(allocator, (CFDateRef*)pl, error, der, der_end); if (!der_result) { - der_result = repairBlock(allocator, mutability, pl, error, der, der_end); + der_result = repairBlock(allocator, pl, error, der, der_end); } return der_result; } case CCDER_CONSTRUCTED_SEQUENCE: - return der_decode_array_with_repair(allocator, mutability, (CFArrayRef*)pl, error, der, der_end, repairBlock); + return der_decode_array_with_repair(allocator, (CFArrayRef*)pl, error, der, der_end, repairBlock); case CCDER_UTF8_STRING: - return der_decode_string(allocator, mutability, (CFStringRef*)pl, error, der, der_end); + return der_decode_string(allocator, (CFStringRef*)pl, error, der, der_end); case CCDER_INTEGER: - return der_decode_number(allocator, mutability, (CFNumberRef*)pl, error, der, der_end); + return der_decode_number(allocator, (CFNumberRef*)pl, error, der, der_end); case CCDER_CONSTRUCTED_SET: - return der_decode_dictionary_with_repair(allocator, mutability, (CFDictionaryRef*)pl, error, der, der_end, repairBlock); + return der_decode_dictionary_with_repair(allocator, (CFDictionaryRef*)pl, error, der, der_end, repairBlock); case CCDER_CONSTRUCTED_CFSET: - return der_decode_set_with_repair(allocator, mutability, (CFSetRef*)pl, error, der, der_end, repairBlock); + return der_decode_set_with_repair(allocator, (CFSetRef*)pl, error, der, der_end, repairBlock); default: SecCFDERCreateError(kSecDERErrorUnsupportedDERType, CFSTR("Unsupported DER Type"), NULL, error); return NULL; } } -static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator, CFDictionaryRef* dictionary, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, + const uint8_t* (^repairBlock)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*)) { if (NULL == der) { @@ -1401,7 +1401,7 @@ static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator CFTypeRef key = NULL; CFTypeRef value = NULL; - payload = der_decode_key_value_with_repair(allocator, mutability, &key, &value, error, payload, payload_end, repairBlock); + payload = der_decode_key_value_with_repair(allocator, &key, &value, error, payload, payload_end, repairBlock); if (payload) { CFDictionaryAddValue(dict, key, value); @@ -1423,10 +1423,10 @@ exit: return payload; } -static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, + const uint8_t* (^repairBlock)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*)) { const uint8_t *payload_end = 0; @@ -1441,8 +1441,8 @@ static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFTypeRef valueObject = NULL; - payload = der_decode_plist_with_repair(allocator, mutability, &keyObject, error, payload, payload_end, repairBlock); - payload = der_decode_plist_with_repair(allocator, mutability, &valueObject, error, payload, payload_end, repairBlock); + payload = der_decode_plist_with_repair(allocator, &keyObject, error, payload, payload_end, repairBlock); + payload = der_decode_plist_with_repair(allocator, &valueObject, error, payload, payload_end, repairBlock); if (payload != NULL) { *key = keyObject; @@ -1454,10 +1454,10 @@ static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, return payload; } -static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFArrayRef* array, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, + const uint8_t* (^repairBlock)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*)) { if (NULL == der) { @@ -1472,7 +1472,7 @@ static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFO while (current_element != NULL && current_element < elements_end) { CFPropertyListRef element = NULL; - current_element = der_decode_plist_with_repair(allocator, mutability, &element, error, current_element, elements_end, repairBlock); + current_element = der_decode_plist_with_repair(allocator, &element, error, current_element, elements_end, repairBlock); if (current_element) { CFArrayAppendValue(result, element); CFReleaseNull(element); @@ -1488,10 +1488,10 @@ static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFO return current_element; } -static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, +static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFSetRef* set, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end, - const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, + const uint8_t* (^repairBlock)(CFAllocatorRef, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*)) { if (NULL == der) { @@ -1519,7 +1519,7 @@ static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFOpt while (payload != NULL && payload < payload_end) { CFTypeRef value = NULL; - payload = der_decode_plist_with_repair(allocator, mutability, &value, error, payload, payload_end, repairBlock); + payload = der_decode_plist_with_repair(allocator, &value, error, payload, payload_end, repairBlock); if (payload) { CFSetAddValue(theSet, value); diff --git a/keychain/securityd/SecDbKeychainItemV7.m b/keychain/securityd/SecDbKeychainItemV7.m index 90ccbe00..6f7f449a 100644 --- a/keychain/securityd/SecDbKeychainItemV7.m +++ b/keychain/securityd/SecDbKeychainItemV7.m @@ -109,7 +109,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { @property (readonly) NSData* serializedRepresentation; - (instancetype)initWithData:(NSData*)data; -- (instancetype)initWithCiphertext:(SFAuthenticatedCiphertext*)ciphertext wrappedKey:(SecDbKeychainAKSWrappedKey*)wrappedKey tamperCheck:(NSString*)tamperCheck backupWrappedKey:(SecDbBackupWrappedItemKey*)backupWrappedKey error:(NSError**)error; +- (instancetype)initWithCiphertext:(SFAuthenticatedCiphertext*)ciphertext wrappedKey:(SecDbKeychainAKSWrappedKey*)wrappedKey tamperCheck:(NSString*)tamperCheck backupWrappedKey:(SecDbBackupWrappedKey*)backupWrappedKey error:(NSError**)error; @end @@ -249,7 +249,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { - (instancetype)initWithCiphertext:(SFAuthenticatedCiphertext*)ciphertext wrappedKey:(SecDbKeychainAKSWrappedKey*)wrappedKey tamperCheck:(NSString*)tamperCheck - backupWrappedKey:(SecDbBackupWrappedItemKey*)backupWrappedKey + backupWrappedKey:(SecDbBackupWrappedKey*)backupWrappedKey error:(NSError**)error { if (self = [super init]) { @@ -412,8 +412,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { { if (!_metadataAttributes) { SFAESKey* metadataClassKey = [self metadataClassKeyWithKeybag:_keybag - createKeyIfMissing:false - overwriteCorruptKey:false + allowWrites:false error:error]; if (metadataClassKey) { NSError* localError = nil; @@ -569,8 +568,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { SFAuthenticatedCiphertext* ciphertext = [encryptionOperation encrypt:metadata withKey:key error:error]; SFAESKey* metadataClassKey = [self metadataClassKeyWithKeybag:keybag - createKeyIfMissing:true - overwriteCorruptKey:true + allowWrites:true error:error]; if (metadataClassKey) { SFAuthenticatedCiphertext* wrappedKey = [encryptionOperation encrypt:key.keyData withKey:metadataClassKey error:error]; @@ -607,7 +605,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { SFAuthenticatedCiphertext* ciphertext = [encryptionOperation encrypt:secretData withKey:key error:error]; SecDbKeychainAKSWrappedKey* wrappedKey = [self wrapToAKS:key withKeybag:keybag accessControl:accessControl acmContext:acmContext error:error]; - SecDbBackupWrappedItemKey* backupWrappedKey; + SecDbBackupWrappedKey* backupWrappedKey; if (checkV12DevEnabled()) { backupWrappedKey = [[SecDbBackupManager manager] wrapItemKey:key forKeyclass:_keyclass error:error]; if (backupWrappedKey) { @@ -629,15 +627,13 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { } - (SFAESKey*)metadataClassKeyWithKeybag:(keybag_handle_t)keybag - createKeyIfMissing:(bool)createIfMissing - overwriteCorruptKey:(bool)force + allowWrites:(bool)allowWrites error:(NSError**)error { return [[SecDbKeychainMetadataKeyStore sharedStore] keyForKeyclass:_keyclass keybag:keybag keySpecifier:[self.class keySpecifier] - createKeyIfMissing:(bool)createIfMissing - overwriteCorruptKey:force + allowWrites:allowWrites error:error]; } @@ -703,12 +699,12 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { return [[SecDbKeychainAKSWrappedKey alloc] initRefKeyWrappedKeyWithData:wrappedKey refKeyBlob:refKeyBlob]; } else { - NSMutableData* wrappedKey = [[NSMutableData alloc] initWithLength:(size_t)keyData.length + 40]; + NSMutableData* wrappedKey = [[NSMutableData alloc] initWithLength:APPLE_KEYSTORE_MAX_SYM_WRAPPED_KEY_LEN]; bool success = [SecAKSObjCWrappers aksEncryptWithKeybag:keybag keyclass:_keyclass plaintext:keyData outKeyclass:&_keyclass ciphertext:wrappedKey error:error]; return success ? [[SecDbKeychainAKSWrappedKey alloc] initRegularWrappedKeyWithData:wrappedKey] : nil; } #else - NSMutableData* wrappedKey = [[NSMutableData alloc] initWithLength:(size_t)keyData.length + 40]; + NSMutableData* wrappedKey = [[NSMutableData alloc] initWithLength:APPLE_KEYSTORE_MAX_SYM_WRAPPED_KEY_LEN]; bool success = [SecAKSObjCWrappers aksEncryptWithKeybag:keybag keyclass:_keyclass plaintext:keyData outKeyclass:&_keyclass ciphertext:wrappedKey error:error]; return success ? [[SecDbKeychainAKSWrappedKey alloc] initRegularWrappedKeyWithData:wrappedKey] : nil; #endif @@ -719,8 +715,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { NSData* wrappedKeyData = wrappedKey.wrappedKey; if (wrappedKey.type == SecDbKeychainAKSWrappedKeyTypeRegular) { - NSMutableData* unwrappedKey = [NSMutableData dataWithCapacity:wrappedKeyData.length + 40]; - unwrappedKey.length = wrappedKeyData.length + 40; + NSMutableData* unwrappedKey = [NSMutableData dataWithLength:APPLE_KEYSTORE_MAX_KEY_LEN]; bool result = [SecAKSObjCWrappers aksDecryptWithKeybag:_keybag keyclass:_keyclass ciphertext:wrappedKeyData outKeyclass:&_keyclass plaintext:unwrappedKey error:error]; if (result) { return [[SFAESKey alloc] initWithData:unwrappedKey specifier:[self.class keySpecifier] error:error]; @@ -742,7 +737,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { return nil; } NSDictionary* aclDict = nil; - der_decode_plist(NULL, kCFPropertyListImmutable, (CFPropertyListRef*)(void*)&aclDict, &cfError, refKeyExternalDataBytes, refKeyExternalDataBytes + refKeyExternalDataLength); + der_decode_plist(NULL, (CFPropertyListRef*)(void*)&aclDict, &cfError, refKeyExternalDataBytes, refKeyExternalDataBytes + refKeyExternalDataLength); if (!aclDict) { SecError(errSecDecode, &cfError, CFSTR("SecDbKeychainItemV7: failed to decode acl dict")); } @@ -779,7 +774,7 @@ typedef NS_ENUM(uint32_t, SecDbKeychainAKSWrappedKeyType) { } CFPropertyListRef unwrappedKeyData = NULL; - der_decode_plist(NULL, kCFPropertyListImmutable, &unwrappedKeyData, &cfError, unwrappedKeyDERData, unwrappedKeyDERData + unwrappedKeyDERLength); + der_decode_plist(NULL, &unwrappedKeyData, &cfError, unwrappedKeyDERData, unwrappedKeyDERData + unwrappedKeyDERLength); SFAESKey* result = nil; if ([(__bridge NSData*)unwrappedKeyData isKindOfClass:[NSData class]]) { result = [[SFAESKey alloc] initWithData:(__bridge NSData*)unwrappedKeyData specifier:[self.class keySpecifier] error:error]; diff --git a/keychain/securityd/SecDbKeychainMetadataKeyStore.h b/keychain/securityd/SecDbKeychainMetadataKeyStore.h index 5c35094a..f49ee4d6 100644 --- a/keychain/securityd/SecDbKeychainMetadataKeyStore.h +++ b/keychain/securityd/SecDbKeychainMetadataKeyStore.h @@ -41,12 +41,11 @@ NS_ASSUME_NONNULL_BEGIN - (void)dropClassAKeys; -- (SFAESKey*)keyForKeyclass:(keyclass_t)keyClass - keybag:(keybag_handle_t)keybag - keySpecifier:(SFAESKeySpecifier*)keySpecifier - createKeyIfMissing:(bool)createIfMissing - overwriteCorruptKey:(bool)overwriteCorruptKey - error:(NSError**)error; +- (SFAESKey* _Nullable)keyForKeyclass:(keyclass_t)keyClass + keybag:(keybag_handle_t)keybag + keySpecifier:(SFAESKeySpecifier*)keySpecifier + allowWrites:(BOOL)allowWrites // (re)create keys if missing, corrupt or outdated format + error:(NSError**)error; @end diff --git a/keychain/securityd/SecDbKeychainMetadataKeyStore.m b/keychain/securityd/SecDbKeychainMetadataKeyStore.m index 860529cf..cd7a321a 100644 --- a/keychain/securityd/SecDbKeychainMetadataKeyStore.m +++ b/keychain/securityd/SecDbKeychainMetadataKeyStore.m @@ -27,9 +27,15 @@ #import #import "SecItemServer.h" #import "SecAKSObjCWrappers.h" +#import "SecDbBackupManager.h" +#import "SecDbKeychainSerializedMetadataKey.h" +#include "SecItemDb.h" // kc_transaction +#include "CheckV12DevEnabled.h" #import "sec_action.h" -static SecDbKeychainMetadataKeyStore* sharedStore = nil; +NS_ASSUME_NONNULL_BEGIN + +static SecDbKeychainMetadataKeyStore*_Nullable sharedStore = nil; static dispatch_queue_t sharedMetadataStoreQueue; static void initializeSharedMetadataStoreQueue(void) { static dispatch_once_t onceToken; @@ -51,9 +57,7 @@ static void initializeSharedMetadataStoreQueue(void) { initializeSharedMetadataStoreQueue(); dispatch_sync(sharedMetadataStoreQueue, ^{ if(sharedStore) { - dispatch_sync(sharedStore->_queue, ^{ - [sharedStore _onQueueDropAllKeys]; - }); + [sharedStore dropAllKeys]; } sharedStore = nil; }); @@ -128,6 +132,13 @@ static void initializeSharedMetadataStoreQueue(void) { _keysDict[@(key_class_akpu)] = nil; } +- (void)dropAllKeys +{ + dispatch_sync(_queue, ^{ + [self _onQueueDropAllKeys]; + }); +} + - (void)_onQueueDropAllKeys { dispatch_assert_queue(_queue); @@ -136,254 +147,350 @@ static void initializeSharedMetadataStoreQueue(void) { [_keysDict removeAllObjects]; } -- (void)_updateActualKeyclassIfNeeded:(keyclass_t)actualKeyclassToWriteBackToDB keyclass:(keyclass_t)keyclass +// Return SFAESKey and actual keyclass if NSData decrypts, or nil if it does not and populate error +- (SFAESKey* _Nullable)validateWrappedKey:(NSData*)wrapped + forKeyClass:(keyclass_t)keyclass + actualKeyClass:(keyclass_t*)outKeyclass + keybag:(keybag_handle_t)keybag + keySpecifier:(SFAESKeySpecifier*)specifier + error:(NSError**)error { - __block CFErrorRef cfError = NULL; + keyclass_t classToUse = keyclass; + if (*outKeyclass != key_class_none && *outKeyclass != keyclass) { + classToUse = *outKeyclass; + } + + NSMutableData* unwrapped = [NSMutableData dataWithLength:APPLE_KEYSTORE_MAX_KEY_LEN]; + SFAESKey* key = NULL; + NSError *localError = nil; + if ([SecAKSObjCWrappers aksDecryptWithKeybag:keybag keyclass:classToUse ciphertext:wrapped outKeyclass:NULL plaintext:unwrapped error:&localError]) { + key = [[SFAESKey alloc] initWithData:unwrapped specifier:specifier error:&localError]; + if (!key) { + secerror("SecDbKeychainItemV7: AKS decrypted metadata blob for class %d but could not turn it into a key: %@", classToUse, localError); + } + } +#if USE_KEYSTORE + else if (classToUse < key_class_last && *outKeyclass == key_class_none) { + *outKeyclass = classToUse | (key_class_last + 1); + if ([SecAKSObjCWrappers aksDecryptWithKeybag:keybag keyclass:*outKeyclass ciphertext:wrapped outKeyclass:NULL plaintext:unwrapped error:&localError]) { + key = [[SFAESKey alloc] initWithData:unwrapped specifier:specifier error:&localError]; + } + } +#endif + if (!key) { + // Don't be noisy for mundane error + if (!([localError.domain isEqualToString:(__bridge NSString*)kSecErrorDomain] && localError.code == errSecInteractionNotAllowed)) { + secerror("SecDbKeychainItemV7: Unable to create key from retrieved data: %@", localError); + } + if (error) { + *error = localError; + } + } - secnotice("SecDbKeychainItemV7", "saving actualKeyclass %d for metadata keyclass %d", actualKeyclassToWriteBackToDB, keyclass); + return key; +} - kc_with_dbt_non_item_tables(true, &cfError, ^bool(SecDbConnectionRef dbt) { - __block bool actualKeyWriteBackOk = true; +- (SFAESKey* _Nullable)newKeyForKeyclass:(keyclass_t)keyclass + withKeybag:(keybag_handle_t)keybag + keySpecifier:(SFAESKeySpecifier*)specifier + database:(SecDbConnectionRef)dbt + error:(NSError**)error +{ + NSError *localError = nil; + SFAESKey* key = [[SFAESKey alloc] initRandomKeyWithSpecifier:specifier error:&localError]; + if (!key) { + if (error) { + *error = localError; + } + return nil; + } + return [self writeKey:key ForKeyclass:keyclass withKeybag:keybag keySpecifier:specifier database:dbt error:error]; +} - // we did not find an actualKeyclass entry in the db, so let's add one in now. - NSString *sql = @"UPDATE metadatakeys SET actualKeyclass = ? WHERE keyclass = ? AND actualKeyclass IS NULL"; - __block CFErrorRef actualKeyWriteBackError = NULL; - actualKeyWriteBackOk &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &actualKeyWriteBackError, ^(sqlite3_stmt* stmt) { - actualKeyWriteBackOk &= SecDbBindInt(stmt, 1, actualKeyclassToWriteBackToDB, &actualKeyWriteBackError); - actualKeyWriteBackOk &= SecDbBindInt(stmt, 2, keyclass, &actualKeyWriteBackError); - actualKeyWriteBackOk &= SecDbStep(dbt, stmt, &actualKeyWriteBackError, ^(bool* stop) { - // woohoo - }); - }); +- (SFAESKey* _Nullable)writeKey:(SFAESKey*)key + ForKeyclass:(keyclass_t)keyclass + withKeybag:(keybag_handle_t)keybag + keySpecifier:(SFAESKeySpecifier*)specifier + database:(SecDbConnectionRef)dbt + error:(NSError**)error +{ + NSError *localError = nil; + dispatch_assert_queue(_queue); - if (actualKeyWriteBackOk) { - secnotice("SecDbKeychainItemV7", "successfully saved actualKeyclass %d for metadata keyclass %d", actualKeyclassToWriteBackToDB, keyclass); + NSMutableData* wrappedKey = [NSMutableData dataWithLength:APPLE_KEYSTORE_MAX_SYM_WRAPPED_KEY_LEN]; + keyclass_t outKeyclass = keyclass; + if (![SecAKSObjCWrappers aksEncryptWithKeybag:keybag keyclass:keyclass plaintext:key.keyData outKeyclass:&outKeyclass ciphertext:wrappedKey error:&localError]) { + secerror("SecDbMetadataKeyStore: Unable to encrypt new metadata key to keybag: %@", localError); + if (error) { + *error = localError; } - else { - // we can always try this again in the future if it failed - secerror("SecDbKeychainItemV7: failed to save actualKeyclass %d for metadata keyclass %d; error: %@", actualKeyclassToWriteBackToDB, keyclass, actualKeyWriteBackError); + return nil; + } + + NSData* mdkdatablob; + if (checkV12DevEnabled()) { + SecDbBackupWrappedKey* backupWrappedKey; + if (SecAKSSanitizedKeyclass(keyclass) != key_class_akpu) { + backupWrappedKey = [[SecDbBackupManager manager] wrapMetadataKey:key forKeyclass:keyclass error:&localError]; + if (!backupWrappedKey) { + secerror("SecDbMetadataKeyStore: Unable to encrypt new metadata key to backup infrastructure: %@", localError); + if (error) { + *error = localError; + } + return nil; + } + } + + SecDbKeychainSerializedMetadataKey* metadatakeydata = [SecDbKeychainSerializedMetadataKey new]; + metadatakeydata.keyclass = keyclass; + metadatakeydata.actualKeyclass = outKeyclass; + metadatakeydata.baguuid = backupWrappedKey.baguuid; + metadatakeydata.akswrappedkey = wrappedKey; + metadatakeydata.backupwrappedkey = backupWrappedKey.wrappedKey; + mdkdatablob = [metadatakeydata data]; + } + + __block bool ok = true; + __block CFErrorRef cfErr = NULL; + NSString* sql; + if (checkV12DevEnabled()) { + sql = @"INSERT OR REPLACE INTO metadatakeys (keyclass, actualKeyclass, data, metadatakeydata) VALUES (?,?,?,?)"; + } else { + sql = @"INSERT OR REPLACE INTO metadatakeys (keyclass, actualKeyclass, data) VALUES (?,?,?)"; + } + ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &cfErr, ^(sqlite3_stmt *stmt) { + ok &= SecDbBindObject(stmt, 1, (__bridge CFNumberRef)@(keyclass), &cfErr); + ok &= SecDbBindObject(stmt, 2, (__bridge CFNumberRef)@(outKeyclass), &cfErr); + if (!checkV12DevEnabled()) { + ok &= SecDbBindBlob(stmt, 3, wrappedKey.bytes, wrappedKey.length, SQLITE_TRANSIENT, &cfErr); + } else { + // Leave stmt param 3 unbound so SQLite will NULL it out + ok &= SecDbBindBlob(stmt, 4, mdkdatablob.bytes, mdkdatablob.length, SQLITE_TRANSIENT, &cfErr); } - return actualKeyWriteBackOk; + ok &= SecDbStep(dbt, stmt, &cfErr, NULL); }); + + if (!ok) { + secerror("Failed to write new metadata key for %d: %@", keyclass, cfErr); + BridgeCFErrorToNSErrorOut(error, cfErr); + return nil; + } + + return key; } -- (SFAESKey*)keyForKeyclass:(keyclass_t)keyclass +- (BOOL)readKeyDataForClass:(keyclass_t)keyclass + fromDb:(SecDbConnectionRef)dbt + actualKeyclass:(keyclass_t*)actualKeyclass + oldFormatData:(NSData**)oldFmt + newFormatData:(NSData**)newFmt + error:(NSError**)error +{ + dispatch_assert_queue(_queue); + + NSString* sql; + if (checkV12DevEnabled()) { + sql = @"SELECT data, actualKeyclass, metadatakeydata FROM metadatakeys WHERE keyclass = ?"; + } else { + sql = @"SELECT data, actualKeyclass FROM metadatakeys WHERE keyclass = ?"; + } + + __block NSData* wrappedKey; + __block NSData* mdkdatablob; + __block bool ok = true; + __block bool found = false; + __block CFErrorRef cfError = NULL; + ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &cfError, ^(sqlite3_stmt *stmt) { + ok &= SecDbBindObject(stmt, 1, (__bridge CFNumberRef)@(keyclass), &cfError); + ok &= SecDbStep(dbt, stmt, &cfError, ^(bool *stop) { + wrappedKey = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)]; + *actualKeyclass = sqlite3_column_int(stmt, 1); + mdkdatablob = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 2) length:sqlite3_column_bytes(stmt, 2)]; + found = true; + }); + }); + + // ok && !found means no error is passed back, which is specifically handled in keyForKeyclass + if (!ok || !found) { + BridgeCFErrorToNSErrorOut(error, cfError); + *actualKeyclass = key_class_none; + return NO; + } + + *oldFmt = wrappedKey; + *newFmt = mdkdatablob; + return YES; +} + +- (SFAESKey* _Nullable)fetchKeyForClass:(keyclass_t)keyclass + fromDb:(SecDbConnectionRef)dbt + keybag:(keybag_handle_t)keybag + specifier:(SFAESKeySpecifier*)keySpecifier + allowWrites:(BOOL)allowWrites + error:(NSError**)error +{ + dispatch_assert_queue(_queue); + + NSData* wrappedKey; + NSData* mdkdatablob; + keyclass_t actualKeyClass = key_class_none; + if (![self readKeyDataForClass:keyclass fromDb:dbt actualKeyclass:&actualKeyClass oldFormatData:&wrappedKey newFormatData:&mdkdatablob error:error]) { + return nil; + } + + // each entry should be either old format or new format. Otherwise this is a bug. + if (!(wrappedKey.length == 0 ^ mdkdatablob.length == 0)) { + if (error) { + *error = [NSError errorWithDomain:(id)kSecErrorDomain code:errSecInternal userInfo:@{NSLocalizedDescriptionKey: @"Metadata key blob both old-world and new-world"}]; + } + return nil; + } + + SFAESKey* key; + BOOL rewrite = NO; + keyclass_t classFromDisk = key_class_none; + if (wrappedKey.length > 0) { // old format read + classFromDisk = actualKeyClass; + key = [self validateWrappedKey:wrappedKey forKeyClass:keyclass actualKeyClass:&actualKeyClass keybag:keybag keySpecifier:keySpecifier error:error]; + if (!key) { + return nil; + } + if (checkV12DevEnabled()) { + rewrite = YES; + } + } else if (mdkdatablob.length > 0) { // new format read + SecDbKeychainSerializedMetadataKey* mdkdata = [[SecDbKeychainSerializedMetadataKey alloc] initWithData:mdkdatablob]; + if (!mdkdata) { + // bad read, key corrupt? + if (error) { + *error = [NSError errorWithDomain:(id)kSecErrorDomain code:errSecDecode userInfo:@{NSLocalizedDescriptionKey: @"New-format metadata key blob didn't deserialize"}]; + } + return nil; + } + + // Ignore the old-read actualKeyClass and use blob + actualKeyClass = mdkdata.actualKeyclass; + classFromDisk = mdkdata.actualKeyclass; + key = [self validateWrappedKey:mdkdata.akswrappedkey forKeyClass:keyclass actualKeyClass:&actualKeyClass keybag:keybag keySpecifier:keySpecifier error:error]; + if (!key) { + return nil; + } + + if (!mdkdata.backupwrappedkey || ![mdkdata.baguuid isEqual:[[SecDbBackupManager manager] currentBackupBagUUID]]) { + rewrite = YES; + secnotice("SecDbMetadataKeyStore", "Metadata key for %d has no or mismatching backup data; will rewrite.", keyclass); + } + + } else { // Wait, there's a row for this class but not something which might be a key? + secnotice("SecDbMetadataKeyStore", "No metadata key found on disk despite existing row. That's odd."); + return nil; + } + + if (allowWrites && (rewrite || classFromDisk != actualKeyClass)) { + NSError* localError; + if (![self writeKey:key ForKeyclass:keyclass withKeybag:keybag keySpecifier:keySpecifier database:dbt error:&localError]) { + // if this fails we can try again in future + secwarning("SecDbMetadataKeyStore: Unable to rewrite metadata key for %d to new format: %@", keyclass, localError); + localError = nil; + } + } + + return key; +} + +- (SFAESKey* _Nullable)keyForKeyclass:(keyclass_t)keyclass keybag:(keybag_handle_t)keybag keySpecifier:(SFAESKeySpecifier*)keySpecifier - createKeyIfMissing:(bool)createIfMissing - overwriteCorruptKey:(bool)overwriteCorruptKey + allowWrites:(BOOL)allowWrites error:(NSError**)error { - __block SFAESKey* key = nil; - __block NSError* nsErrorLocal = nil; - __block CFErrorRef cfError = NULL; - static __thread BOOL reentrant = NO; + if (!error) { + secerror("keyForKeyclass called without error param, this is a bug"); + return nil; + } + static __thread BOOL reentrant = NO; NSAssert(!reentrant, @"re-entering -[%@ %@] - that shouldn't happen!", NSStringFromClass(self.class), NSStringFromSelector(_cmd)); reentrant = YES; keyclass = SecAKSSanitizedKeyclass(keyclass); + __block SFAESKey* key = nil; + __block NSError* nsErrorLocal = nil; + __block CFErrorRef cfError = NULL; + __block bool ok = true; dispatch_sync(_queue, ^{ - // if we think we're locked, it's possible AKS will still give us access to keys, such as during backup, - // but we should force AKS to be the truth and not used cached class A keys while locked - bool allowKeyCaching = [SecDbKeychainMetadataKeyStore cachingEnabled]; - - // However, we must not cache a newly-created key, just in case someone above us in the stack rolls back our database transaction and the stored key is lost. - __block bool keyIsNewlyCreated = false; -#if 0 - // Fix keychain lock state check to be both secure and fast for EDU mode - if (![SecDbKeychainItemV7 isKeychainUnlocked]) { - [self _onQueueDropClassAKeys]; - allowKeyCaching = !(keyclass == key_class_ak || keyclass == key_class_aku || keyclass == key_class_akpu); - } -#endif + // try our cache first and rejoice if that succeeds + bool allowCaching = [SecDbKeychainMetadataKeyStore cachingEnabled]; - key = allowKeyCaching ? self->_keysDict[@(keyclass)] : nil; - if (!key) { - __block bool ok = true; - __block bool metadataKeyDoesntAuthenticate = false; - ok &= kc_with_dbt_non_item_tables(createIfMissing, &cfError, ^bool(SecDbConnectionRef dbt) { - __block NSString* sql = [NSString stringWithFormat:@"SELECT data, actualKeyclass FROM metadatakeys WHERE keyclass = %d", keyclass]; - ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &cfError, ^(sqlite3_stmt *stmt) { - ok &= SecDbStep(dbt, stmt, &cfError, ^(bool *stop) { - NSData* wrappedKeyData = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)]; - NSMutableData* unwrappedKeyData = [NSMutableData dataWithLength:wrappedKeyData.length]; - - keyclass_t actualKeyclass = sqlite3_column_int(stmt, 1); - - keyclass_t actualKeyclassToWriteBackToDB = 0; - keyclass_t keyclassForUnwrapping = actualKeyclass == 0 ? keyclass : actualKeyclass; - ok &= [SecAKSObjCWrappers aksDecryptWithKeybag:keybag keyclass:keyclassForUnwrapping ciphertext:wrappedKeyData outKeyclass:NULL plaintext:unwrappedKeyData error:&nsErrorLocal]; - if (ok) { - key = [[SFAESKey alloc] initWithData:unwrappedKeyData specifier:keySpecifier error:&nsErrorLocal]; - - if(!key) { - if (__security_simulatecrash_enabled()) { - os_log_fault(secLogObjForScope("SecDbKeychainItemV7"), "Metadata class key (%d) decrypted, but didn't become a key: %@", keyclass, nsErrorLocal); - } - } - - if (actualKeyclass == 0) { - actualKeyclassToWriteBackToDB = keyclassForUnwrapping; - } - } -#if USE_KEYSTORE - else if (actualKeyclass == 0 && keyclass <= key_class_last) { - // in this case we might have luck decrypting with a key-rolled keyclass - keyclass_t keyrolledKeyclass = keyclass | (key_class_last + 1); - secerror("SecDbKeychainItemV7: failed to decrypt metadata key for class %d, but trying keyrolled keyclass (%d); error: %@", keyclass, keyrolledKeyclass, nsErrorLocal); - - // we don't want to pollute subsequent error-handling logic with what happens on our retry - // we'll give it a shot, and if it works, great - if it doesn't work, we'll just report that error in the log and move on - NSError* retryError = nil; - ok = [SecAKSObjCWrappers aksDecryptWithKeybag:keybag keyclass:keyrolledKeyclass ciphertext:wrappedKeyData outKeyclass:NULL plaintext:unwrappedKeyData error:&retryError]; - - if (ok) { - secerror("SecDbKeychainItemV7: successfully decrypted metadata key using keyrolled keyclass %d", keyrolledKeyclass); - key = [[SFAESKey alloc] initWithData:unwrappedKeyData specifier:keySpecifier error:&retryError]; - - if(!key) { - if (__security_simulatecrash_enabled()) { - os_log_fault(secLogObjForScope("SecDbKeychainItemV7"), - "Metadata class key (%d) decrypted using keyrolled keyclass %d, but didn't become a key: %@", - keyclass, keyrolledKeyclass, retryError); - } - nsErrorLocal = retryError; - } - } - else { - secerror("SecDbKeychainItemV7: failed to decrypt metadata key with keyrolled keyclass %d; error: %@", keyrolledKeyclass, retryError); - } - } -#endif + key = allowCaching ? self->_keysDict[@(keyclass)] : nil; + if (key) { + return; // Cache contains validated key for class, excellent! + } - if (ok && key) { - if (actualKeyclassToWriteBackToDB > 0) { - // check if we have updated this keyclass or not already - static NSMutableDictionary* updated = NULL; - if (!updated) { - updated = [NSMutableDictionary dictionary]; - } - if (!updated[@(keyclass)]) { - updated[@(keyclass)] = @YES; - dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{ - [self _updateActualKeyclassIfNeeded:actualKeyclassToWriteBackToDB keyclass:keyclass]; - }); - } - } - } - else { - if (nsErrorLocal && [nsErrorLocal.domain isEqualToString:(__bridge NSString*)kSecErrorDomain] && nsErrorLocal.code == errSecInteractionNotAllowed) { - static dispatch_once_t kclockedtoken; - static sec_action_t kclockedaction; - dispatch_once(&kclockedtoken, ^{ - kclockedaction = sec_action_create("keychainlockedlogmessage", 1); - sec_action_set_handler(kclockedaction, ^{ - secerror("SecDbKeychainItemV7: failed to decrypt metadata key because the keychain is locked (%d)", (int)errSecInteractionNotAllowed); - }); - }); - sec_action_perform(kclockedaction); - } else { - secerror("SecDbKeychainItemV7: failed to decrypt and create metadata key for class %d; error: %@", keyclass, nsErrorLocal); - - // If this error is errSecDecode, then it's failed authentication and likely will forever. Other errors are scary. - metadataKeyDoesntAuthenticate = [nsErrorLocal.domain isEqualToString:NSOSStatusErrorDomain] && nsErrorLocal.code == errSecDecode; - if(metadataKeyDoesntAuthenticate) { - if (__security_simulatecrash_enabled()) { - os_log_fault(secLogObjForScope("SecDbKeychainItemV7"), "Metadata class key (%d) failed to decrypt: %@", keyclass, nsErrorLocal); - } - } - } - } + // Key not in cache. Open a transaction to find or optionally (re)create key. Transactions can be nested, so this is fine. + ok &= kc_with_dbt_non_item_tables(true, &cfError, ^bool(SecDbConnectionRef dbt) { + key = [self fetchKeyForClass:keyclass + fromDb:dbt + keybag:keybag + specifier:keySpecifier + allowWrites:allowWrites + error:&nsErrorLocal]; + + // The code for this conditional is a little convoluted because I want the "keychain locked" message to take precedence over the "not allowed to create one" message. + if (!key && ([nsErrorLocal.domain isEqualToString:(__bridge NSString*)kSecErrorDomain] && nsErrorLocal.code == errSecInteractionNotAllowed)) { + static sec_action_t logKeychainLockedMessageAction; + static dispatch_once_t keychainLockedMessageOnceToken; + dispatch_once(&keychainLockedMessageOnceToken, ^{ + logKeychainLockedMessageAction = sec_action_create("keychainlockedlogmessage", 1); + sec_action_set_handler(logKeychainLockedMessageAction, ^{ + secerror("SecDbKeychainItemV7: cannot decrypt metadata key because the keychain is locked (%ld)", (long)nsErrorLocal.code); }); }); - - bool keyNotYetCreated = ok && !key; - bool forceOverwriteBadKey = !key && metadataKeyDoesntAuthenticate && overwriteCorruptKey; - - if (createIfMissing && (keyNotYetCreated || forceOverwriteBadKey)) { - // we completed the database query, but no key exists or it's broken - we should create one - if(forceOverwriteBadKey) { - secerror("SecDbKeychainItemV7: metadata key is irreparably corrupt; throwing away forever"); - // TODO: track this in LocalKeychainAnalytics - } - - ok = true; // Reset 'ok': we have a second chance - - key = [[SFAESKey alloc] initRandomKeyWithSpecifier:keySpecifier error:&nsErrorLocal]; - keyIsNewlyCreated = true; - - if (key) { - NSMutableData* wrappedKey = [NSMutableData dataWithLength:key.keyData.length + 40]; - keyclass_t outKeyclass = keyclass; - ok &= [SecAKSObjCWrappers aksEncryptWithKeybag:keybag keyclass:keyclass plaintext:key.keyData outKeyclass:&outKeyclass ciphertext:wrappedKey error:&nsErrorLocal]; - if (ok) { - secinfo("SecDbKeychainItemV7", "attempting to save new metadata key for keyclass %d with actualKeyclass %d", keyclass, outKeyclass); - NSString* insertString = forceOverwriteBadKey ? @"INSERT OR REPLACE" : @"INSERT"; - sql = [NSString stringWithFormat:@"%@ into metadatakeys (keyclass, actualKeyclass, data) VALUES (?, ?, ?)", insertString]; - ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &cfError, ^(sqlite3_stmt* stmt) { - ok &= SecDbBindInt(stmt, 1, keyclass, &cfError); - ok &= SecDbBindInt(stmt, 2, outKeyclass, &cfError); - ok &= SecDbBindBlob(stmt, 3, wrappedKey.bytes, wrappedKey.length, SQLITE_TRANSIENT, NULL); - ok &= SecDbStep(dbt, stmt, &cfError, ^(bool *stop) { - // woohoo - }); - }); - - if (ok) { - secnotice("SecDbKeychainItemV7", "successfully saved new metadata key for keyclass %d", keyclass); - } - else { - secerror("SecDbKeychainItemV7: failed to save new metadata key for keyclass %d - probably there is already one in the database: %@", keyclass, cfError); - } - } else { - secerror("SecDbKeychainItemV7: unable to encrypt new metadata key(%d) with keybag(%d): %@", keyclass, keybag, nsErrorLocal); - } - } - else { - ok = false; - } - } else if(!key) { - // No key, but we're not supposed to make one. Make an error if one doesn't yet exist. - ok = false; - if(!nsErrorLocal) { - nsErrorLocal = [NSError errorWithDomain:(id)kSecErrorDomain code:errSecDecode userInfo:@{NSLocalizedDescriptionKey: @"Unable to find or create a suitable metadata key"}]; - } + sec_action_perform(logKeychainLockedMessageAction); + } else if (!key && !allowWrites) { + secwarning("SecDbMetadataKeyStore: Unable to load metadatakey for class %d from disk (%@) and not allowed to create new one", keyclass, nsErrorLocal); + if (!nsErrorLocal) { + // If this is at creation time we are allowed to create so won't be here + // If this is at fetch time and we have a missing or bad key then the item /is/ dead + nsErrorLocal = [NSError errorWithDomain:(id)kSecErrorDomain code:errSecDecode userInfo:@{NSLocalizedDescriptionKey: @"Unable to find a suitable metadata key and not permitted to create one"}]; } - - return ok; - }); - - if (ok && key) { - // We can't cache a newly-created key, just in case this db transaction is rolled back and we lose the persisted key. - // Don't worry, we'll cache it as soon as it's used again. - if (allowKeyCaching && !keyIsNewlyCreated) { - self->_keysDict[@(keyclass)] = key; - __weak __typeof(self) weakSelf = self; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60 * 5 * NSEC_PER_SEC)), self->_queue, ^{ - [weakSelf _onQueueDropClassAKeys]; - }); + return false; + // If this error is errSecDecode, then it's failed authentication and likely will forever. Other errors are scary. If !key and !error then no key existed. + } else if ((!key && !nsErrorLocal) || (!key && [nsErrorLocal.domain isEqualToString:NSOSStatusErrorDomain] && nsErrorLocal.code == errSecDecode)) { + secwarning("SecDbMetadataKeyStore: unable to use key (%ld), will attempt to create new one", (long)nsErrorLocal.code); + nsErrorLocal = nil; + key = [self newKeyForKeyclass:keyclass withKeybag:keybag keySpecifier:keySpecifier database:dbt error:&nsErrorLocal]; + if (!key) { + secerror("SecDbMetadataKeyStore: unable to create or save new key: %@", nsErrorLocal); + return false; } + } else if (!key) { + secerror("SecDbMetadataKeyStore: scary error encountered: %@", nsErrorLocal); + } else if (allowCaching) { + self->_keysDict[@(keyclass)] = key; // Only cache keys fetched from disk } - else { - key = nil; - } + return !!key; + }); // kc_with_dbt + }); // our queue + + if (!ok || !key) { + if (nsErrorLocal) { + *error = nsErrorLocal; + CFReleaseNull(cfError); + } else { + BridgeCFErrorToNSErrorOut(error, cfError); } - }); + assert(*error); // Triggers only in testing, which is by design not to break production + key = nil; + } reentrant = NO; - if (error && nsErrorLocal) { - *error = nsErrorLocal; - CFReleaseNull(cfError); - } - else { - BridgeCFErrorToNSErrorOut(error, cfError); - } - return key; } @end + +NS_ASSUME_NONNULL_END diff --git a/keychain/securityd/SecDbKeychainV7-protobufs/SecDbKeychainSerializedMetadataKey.proto b/keychain/securityd/SecDbKeychainV7-protobufs/SecDbKeychainSerializedMetadataKey.proto new file mode 100644 index 00000000..0e4f960e --- /dev/null +++ b/keychain/securityd/SecDbKeychainV7-protobufs/SecDbKeychainSerializedMetadataKey.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; + +message SecDbKeychainSerializedMetadataKey { + optional int32 keyclass = 1; + optional int32 actualKeyclass = 2; + optional bytes baguuid = 3; + optional bytes akswrappedkey = 4; + optional bytes backupwrappedkey = 5; +} diff --git a/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.h b/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.h new file mode 100644 index 00000000..9ff7f68d --- /dev/null +++ b/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.h @@ -0,0 +1,55 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from SecDbKeychainSerializedMetadataKey.proto + +#import +#import + +#ifdef __cplusplus +#define SECDBKEYCHAINSERIALIZEDMETADATAKEY_FUNCTION extern "C" +#else +#define SECDBKEYCHAINSERIALIZEDMETADATAKEY_FUNCTION extern +#endif + +@interface SecDbKeychainSerializedMetadataKey : PBCodable +{ + int32_t _actualKeyclass; + NSData *_akswrappedkey; + NSData *_backupwrappedkey; + NSData *_baguuid; + int32_t _keyclass; + struct { + int actualKeyclass:1; + int keyclass:1; + } _has; +} + + +@property (nonatomic) BOOL hasKeyclass; +@property (nonatomic) int32_t keyclass; + +@property (nonatomic) BOOL hasActualKeyclass; +@property (nonatomic) int32_t actualKeyclass; + +@property (nonatomic, readonly) BOOL hasBaguuid; +@property (nonatomic, retain) NSData *baguuid; + +@property (nonatomic, readonly) BOOL hasAkswrappedkey; +@property (nonatomic, retain) NSData *akswrappedkey; + +@property (nonatomic, readonly) BOOL hasBackupwrappedkey; +@property (nonatomic, retain) NSData *backupwrappedkey; + +// Performs a shallow copy into other +- (void)copyTo:(SecDbKeychainSerializedMetadataKey *)other; + +// Performs a deep merge from other into self +// If set in other, singular values in self are replaced in self +// Singular composite values are recursively merged +// Repeated values from other are appended to repeated values in self +- (void)mergeFrom:(SecDbKeychainSerializedMetadataKey *)other; + +SECDBKEYCHAINSERIALIZEDMETADATAKEY_FUNCTION BOOL SecDbKeychainSerializedMetadataKeyReadFrom(__unsafe_unretained SecDbKeychainSerializedMetadataKey *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.m b/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.m new file mode 100644 index 00000000..b16f7a51 --- /dev/null +++ b/keychain/securityd/SecDbKeychainV7-protobufs/generated_source/SecDbKeychainSerializedMetadataKey.m @@ -0,0 +1,294 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from SecDbKeychainSerializedMetadataKey.proto + +#import "SecDbKeychainSerializedMetadataKey.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation SecDbKeychainSerializedMetadataKey + +@synthesize keyclass = _keyclass; +- (void)setKeyclass:(int32_t)v +{ + _has.keyclass = YES; + _keyclass = v; +} +- (void)setHasKeyclass:(BOOL)f +{ + _has.keyclass = f; +} +- (BOOL)hasKeyclass +{ + return _has.keyclass != 0; +} +@synthesize actualKeyclass = _actualKeyclass; +- (void)setActualKeyclass:(int32_t)v +{ + _has.actualKeyclass = YES; + _actualKeyclass = v; +} +- (void)setHasActualKeyclass:(BOOL)f +{ + _has.actualKeyclass = f; +} +- (BOOL)hasActualKeyclass +{ + return _has.actualKeyclass != 0; +} +- (BOOL)hasBaguuid +{ + return _baguuid != nil; +} +@synthesize baguuid = _baguuid; +- (BOOL)hasAkswrappedkey +{ + return _akswrappedkey != nil; +} +@synthesize akswrappedkey = _akswrappedkey; +- (BOOL)hasBackupwrappedkey +{ + return _backupwrappedkey != nil; +} +@synthesize backupwrappedkey = _backupwrappedkey; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_has.keyclass) + { + [dict setObject:[NSNumber numberWithInt:self->_keyclass] forKey:@"keyclass"]; + } + if (self->_has.actualKeyclass) + { + [dict setObject:[NSNumber numberWithInt:self->_actualKeyclass] forKey:@"actualKeyclass"]; + } + if (self->_baguuid) + { + [dict setObject:self->_baguuid forKey:@"baguuid"]; + } + if (self->_akswrappedkey) + { + [dict setObject:self->_akswrappedkey forKey:@"akswrappedkey"]; + } + if (self->_backupwrappedkey) + { + [dict setObject:self->_backupwrappedkey forKey:@"backupwrappedkey"]; + } + return dict; +} + +BOOL SecDbKeychainSerializedMetadataKeyReadFrom(__unsafe_unretained SecDbKeychainSerializedMetadataKey *self, __unsafe_unretained PBDataReader *reader) { + while (PBReaderHasMoreData(reader)) { + uint32_t tag = 0; + uint8_t aType = 0; + + PBReaderReadTag32AndType(reader, &tag, &aType); + + if (PBReaderHasError(reader)) + break; + + if (aType == TYPE_END_GROUP) { + break; + } + + switch (tag) { + + case 1 /* keyclass */: + { + self->_has.keyclass = YES; + self->_keyclass = PBReaderReadInt32(reader); + } + break; + case 2 /* actualKeyclass */: + { + self->_has.actualKeyclass = YES; + self->_actualKeyclass = PBReaderReadInt32(reader); + } + break; + case 3 /* baguuid */: + { + NSData *new_baguuid = PBReaderReadData(reader); + self->_baguuid = new_baguuid; + } + break; + case 4 /* akswrappedkey */: + { + NSData *new_akswrappedkey = PBReaderReadData(reader); + self->_akswrappedkey = new_akswrappedkey; + } + break; + case 5 /* backupwrappedkey */: + { + NSData *new_backupwrappedkey = PBReaderReadData(reader); + self->_backupwrappedkey = new_backupwrappedkey; + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return SecDbKeychainSerializedMetadataKeyReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* keyclass */ + { + if (self->_has.keyclass) + { + PBDataWriterWriteInt32Field(writer, self->_keyclass, 1); + } + } + /* actualKeyclass */ + { + if (self->_has.actualKeyclass) + { + PBDataWriterWriteInt32Field(writer, self->_actualKeyclass, 2); + } + } + /* baguuid */ + { + if (self->_baguuid) + { + PBDataWriterWriteDataField(writer, self->_baguuid, 3); + } + } + /* akswrappedkey */ + { + if (self->_akswrappedkey) + { + PBDataWriterWriteDataField(writer, self->_akswrappedkey, 4); + } + } + /* backupwrappedkey */ + { + if (self->_backupwrappedkey) + { + PBDataWriterWriteDataField(writer, self->_backupwrappedkey, 5); + } + } +} + +- (void)copyTo:(SecDbKeychainSerializedMetadataKey *)other +{ + if (self->_has.keyclass) + { + other->_keyclass = _keyclass; + other->_has.keyclass = YES; + } + if (self->_has.actualKeyclass) + { + other->_actualKeyclass = _actualKeyclass; + other->_has.actualKeyclass = YES; + } + if (_baguuid) + { + other.baguuid = _baguuid; + } + if (_akswrappedkey) + { + other.akswrappedkey = _akswrappedkey; + } + if (_backupwrappedkey) + { + other.backupwrappedkey = _backupwrappedkey; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + SecDbKeychainSerializedMetadataKey *copy = [[[self class] allocWithZone:zone] init]; + if (self->_has.keyclass) + { + copy->_keyclass = _keyclass; + copy->_has.keyclass = YES; + } + if (self->_has.actualKeyclass) + { + copy->_actualKeyclass = _actualKeyclass; + copy->_has.actualKeyclass = YES; + } + copy->_baguuid = [_baguuid copyWithZone:zone]; + copy->_akswrappedkey = [_akswrappedkey copyWithZone:zone]; + copy->_backupwrappedkey = [_backupwrappedkey copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + SecDbKeychainSerializedMetadataKey *other = (SecDbKeychainSerializedMetadataKey *)object; + return [other isMemberOfClass:[self class]] + && + ((self->_has.keyclass && other->_has.keyclass && self->_keyclass == other->_keyclass) || (!self->_has.keyclass && !other->_has.keyclass)) + && + ((self->_has.actualKeyclass && other->_has.actualKeyclass && self->_actualKeyclass == other->_actualKeyclass) || (!self->_has.actualKeyclass && !other->_has.actualKeyclass)) + && + ((!self->_baguuid && !other->_baguuid) || [self->_baguuid isEqual:other->_baguuid]) + && + ((!self->_akswrappedkey && !other->_akswrappedkey) || [self->_akswrappedkey isEqual:other->_akswrappedkey]) + && + ((!self->_backupwrappedkey && !other->_backupwrappedkey) || [self->_backupwrappedkey isEqual:other->_backupwrappedkey]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + (self->_has.keyclass ? PBHashInt((NSUInteger)self->_keyclass) : 0) + ^ + (self->_has.actualKeyclass ? PBHashInt((NSUInteger)self->_actualKeyclass) : 0) + ^ + [self->_baguuid hash] + ^ + [self->_akswrappedkey hash] + ^ + [self->_backupwrappedkey hash] + ; +} + +- (void)mergeFrom:(SecDbKeychainSerializedMetadataKey *)other +{ + if (other->_has.keyclass) + { + self->_keyclass = other->_keyclass; + self->_has.keyclass = YES; + } + if (other->_has.actualKeyclass) + { + self->_actualKeyclass = other->_actualKeyclass; + self->_has.actualKeyclass = YES; + } + if (other->_baguuid) + { + [self setBaguuid:other->_baguuid]; + } + if (other->_akswrappedkey) + { + [self setAkswrappedkey:other->_akswrappedkey]; + } + if (other->_backupwrappedkey) + { + [self setBackupwrappedkey:other->_backupwrappedkey]; + } +} + +@end + diff --git a/keychain/securityd/SecDbQuery.c b/keychain/securityd/SecDbQuery.c index 88d72177..f6d32354 100644 --- a/keychain/securityd/SecDbQuery.c +++ b/keychain/securityd/SecDbQuery.c @@ -412,11 +412,6 @@ void query_add_not_attribute(const void *key, const void *value, Query *q) } } - -/* AUDIT[securityd](done): - key (ok) is a caller provided, string starting with 'm'. - value (ok) is a caller provided, non NULL CFTypeRef. - */ static void query_add_match(const void *key, const void *value, Query *q) { /* Record the match key, value in q_pairs. */ @@ -874,6 +869,7 @@ bool query_notify_and_destroy(Query *q, bool ok, CFErrorRef *error) { Query *query_create(const SecDbClass *qclass, CFDataRef musr, CFDictionaryRef query, + SecurityClient* client, CFErrorRef *error) { if (!qclass) { @@ -926,6 +922,16 @@ Query *query_create(const SecDbClass *qclass, q->q_match_begin = q->q_match_end = key_count; q->q_item = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (client) { + // If not, don't do anything. Parent apps, schema migration, etc. all need access to all items, clip or no + if (client->isAppClip) { + secdebug("query", "Client is app clip, adding restriction to query attribute"); + CFDictionaryAddValue(q->q_item, kSecAttrAppClipItem, kCFBooleanTrue); + } + } else { + secdebug("query", "no client information specified so not tweaking query attributes"); + } + return q; } @@ -949,9 +955,9 @@ bool query_update_parse(Query *q, CFDictionaryRef update, return query_parse_with_applier(q, update, query_update_applier, error); } -Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, CFErrorRef *error) { +Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, SecurityClient* client, CFErrorRef *error) { Query *q; - q = query_create(query_get_class(query, error), musr, query, error); + q = query_create(query_get_class(query, error), musr, query, client, error); if (q) { q->q_limit = limit; if (!query_parse(q, query, error)) { diff --git a/keychain/securityd/SecDbQuery.h b/keychain/securityd/SecDbQuery.h index 820090bf..861c3ca3 100644 --- a/keychain/securityd/SecDbQuery.h +++ b/keychain/securityd/SecDbQuery.h @@ -30,6 +30,7 @@ #include "keychain/securityd/SecKeybagSupport.h" #include "keychain/securityd/SecDbItem.h" +#include "ipc/securityd_client.h" // be able to create queries which restrict API __BEGIN_DECLS @@ -116,9 +117,16 @@ typedef struct Query // instead of reporting them to the client as an error. bool q_skip_acl_items; + // Some queries (e.g. backups) explicitly do not want to deal with clip-created items + bool q_skip_app_clip_items; + // Set to true if any UUIDs generated by this query should be generated from the SHA2 digest of the item in question bool q_uuid_from_primary_key; + // Set to true if you'd like any Tombstones created by this query to have an mdat that is one second after the non-tombstone's mdat. + // This is used if you're deleting an item, but are unsure when the item deletion occurred (e.g., you receive an item delete via CloudKit). + bool q_tombstone_use_mdat_from_item; + // Set this to a callback that, on an add query, will get passed along with the CKKS subsystem and called when the item makes it off-device (or doesn't) __unsafe_unretained SecBoolCFErrorCallback q_add_sync_callback; @@ -146,10 +154,10 @@ typedef struct Query Pair q_pairs[]; } Query; -Query *query_create(const SecDbClass *qclass, CFDataRef musr, CFDictionaryRef query, CFErrorRef *error); +Query *query_create(const SecDbClass *qclass, CFDataRef musr, CFDictionaryRef query, SecurityClient* client, CFErrorRef *error); bool query_destroy(Query *q, CFErrorRef *error); bool query_error(Query *q, CFErrorRef *error); -Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, CFErrorRef *error); +Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, SecurityClient* client, CFErrorRef *error); void query_add_attribute(const void *key, const void *value, Query *q); void query_add_or_attribute(const void *key, const void *value, Query *q); void query_add_not_attribute(const void *key, const void *value, Query *q); diff --git a/keychain/securityd/SecItemBackupServer.c b/keychain/securityd/SecItemBackupServer.c index 78591837..605cfd19 100644 --- a/keychain/securityd/SecItemBackupServer.c +++ b/keychain/securityd/SecItemBackupServer.c @@ -78,6 +78,16 @@ CFArrayRef SecServerItemBackupCopyNames(CFErrorRef *error) { return names; } +CFStringRef SecServerItemBackupEnsureCopyView(CFStringRef viewName, CFErrorRef *error) { + __block CFStringRef name = NULL; + if(!withDataSourceAndEngine(error, ^(SOSDataSourceRef ds, SOSEngineRef engine) { + name = SOSEngineEnsureCopyBackupPeerForView(engine, viewName, error); + })) { + CFReleaseNull(name); + } + return name; +} + // TODO Move to datasource and remove dsRestoreObject static bool SOSDataSourceWithBackup(SOSDataSourceRef ds, CFDataRef backup, keybag_handle_t bag_handle, CFErrorRef *error, void(^with)(SOSObjectRef item)) { __block bool ok = true; diff --git a/keychain/securityd/SecItemBackupServer.h b/keychain/securityd/SecItemBackupServer.h index 04607c60..87156d28 100644 --- a/keychain/securityd/SecItemBackupServer.h +++ b/keychain/securityd/SecItemBackupServer.h @@ -37,6 +37,7 @@ __BEGIN_DECLS int SecServerItemBackupHandoffFD(CFStringRef backupName, CFErrorRef *error); bool SecServerItemBackupSetConfirmedManifest(CFStringRef backupName, CFDataRef keybagDigest, CFDataRef manifest, CFErrorRef *error); CFArrayRef SecServerItemBackupCopyNames(CFErrorRef *error); +CFStringRef SecServerItemBackupEnsureCopyView(CFStringRef peerID, CFErrorRef *error); bool SecServerItemBackupRestore(CFStringRef backupName, CFStringRef peerID, CFDataRef keybag, CFDataRef secret, CFDataRef backup, CFErrorRef *error); __END_DECLS diff --git a/keychain/securityd/SecItemDataSource.c b/keychain/securityd/SecItemDataSource.c index d5a3a283..9f6232e2 100644 --- a/keychain/securityd/SecItemDataSource.c +++ b/keychain/securityd/SecItemDataSource.c @@ -158,7 +158,7 @@ static SOSManifestRef SecItemDataSourceCopyManifestWithQueries(SecItemDataSource } static Query *SecItemDataSourceAppendQuery(CFMutableArrayRef queries, const SecDbClass *qclass, bool noTombstones, CFErrorRef *error) { - Query *q = query_create(qclass, NULL, NULL, error); + Query *q = query_create(qclass, NULL, NULL, NULL, error); if (q) { q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; q->q_limit = kSecMatchUnlimited; @@ -304,6 +304,7 @@ static SOSManifestRef SecItemDataSourceCopyManifestWithViewNameSet(SecItemDataSo } // Return the newest object (conflict resolver) +// Any fields marked as "kSecDbSyncSOSCannotSyncFlag" that are in item2 will be present in the returned item. static SecDbItemRef SecItemDataSourceCopyMergedItem(SecDbItemRef item1, SecDbItemRef item2, CFErrorRef *error) { CFErrorRef localError = NULL; SecDbItemRef result = NULL; @@ -323,7 +324,7 @@ static SecDbItemRef SecItemDataSourceCopyMergedItem(SecDbItemRef item1, SecDbIte // Return the item with the smallest digest. CFDataRef digest1 = SecDbItemGetSHA1(item1, &localError); CFDataRef digest2 = SecDbItemGetSHA1(item2, &localError); - if (digest1 && digest2) switch (CFDataCompare(digest1, digest2)) { + if (digest1 && digest2) switch (CFDataCompareDERData(digest1, digest2)) { case kCFCompareGreaterThan: case kCFCompareEqualTo: result = item2; @@ -350,6 +351,22 @@ static SecDbItemRef SecItemDataSourceCopyMergedItem(SecDbItemRef item1, SecDbIte else CFRelease(localError); } + + // Note, if we chose item2 as result above, there's no need to move attributes from item2 to item2 + if(result && item2 && result != item2) { + // We'd like to preserve our local UUID, no matter what. UUIDs are not sent across SOS channels, and so items + // arriving via SOS have randomly generated UUIDs. + SecDbForEachAttr(SecDbItemGetClass(result), attr) { + if(CFEqualSafe(attr->name, v10itemuuid.name)) { + SecItemPreserveAttribute(result, item2, attr); + } + } + + SecDbForEachAttrWithMask(SecDbItemGetClass(result), attr, kSecDbSyncSOSCannotSyncFlag) { + SecItemPreserveAttribute(result, item2, attr); + } + } + return CFRetainSafe(result); } @@ -399,7 +416,7 @@ static bool dsForEachObject(SOSDataSourceRef data_source, SOSTransactionRef txn, // Setup for (size_t class_ix = 0; class_ix < dsSyncedClassesSize; ++class_ix) { result = (result - && (queries[class_ix] = query_create(dsSyncedClasses()[class_ix], NULL, NULL, error)) + && (queries[class_ix] = query_create(dsSyncedClasses()[class_ix], NULL, NULL, NULL, error)) && (sqls[class_ix] = SecDbItemCopySelectSQL(queries[class_ix], return_attr, use_attr_in_where, NULL)) && (stmts[class_ix] = SecDbCopyStmt(dbconn, sqls[class_ix], NULL, error))); } @@ -480,9 +497,9 @@ static CFDateRef copyObjectModDate(SOSObjectRef object, CFErrorRef *error) { static CFDictionaryRef objectCopyPropertyList(SOSObjectRef object, CFErrorRef *error) { SecDbItemRef item = (SecDbItemRef) object; - CFMutableDictionaryRef secretDataDict = SecDbItemCopyPListWithMask(item, kSecDbReturnDataFlag, error); - CFMutableDictionaryRef cryptoDataDict = SecDbItemCopyPListWithMask(item, kSecDbInCryptoDataFlag, error); - CFMutableDictionaryRef authDataDict = SecDbItemCopyPListWithMask(item, kSecDbInAuthenticatedDataFlag, error); + CFMutableDictionaryRef secretDataDict = SecDbItemCopyPListWithFlagAndSkip(item, kSecDbReturnDataFlag, kSecDbSyncSOSCannotSyncFlag, error); + CFMutableDictionaryRef cryptoDataDict = SecDbItemCopyPListWithFlagAndSkip(item, kSecDbInCryptoDataFlag, kSecDbSyncSOSCannotSyncFlag, error); + CFMutableDictionaryRef authDataDict = SecDbItemCopyPListWithFlagAndSkip(item, kSecDbInAuthenticatedDataFlag, kSecDbSyncSOSCannotSyncFlag, error); if (cryptoDataDict) { if (authDataDict) { @@ -665,7 +682,7 @@ static CFDataRef dsCopyStateWithKey(SOSDataSourceRef data_source, CFStringRef ke NULL); CFReleaseSafe(dataSourceID); __block CFDataRef data = NULL; - SecDbQueryRef query = query_create(genp_class(), NULL, dict, error); + SecDbQueryRef query = query_create(genp_class(), NULL, dict, NULL, error); if (query) { if (query->q_item) CFReleaseSafe(query->q_item); query->q_item = dict; @@ -710,7 +727,7 @@ static CFDataRef dsCopyItemDataWithKeys(SOSDataSourceRef data_source, CFDictiona SecItemDataSourceRef ds = (SecItemDataSourceRef)data_source; CFMutableDictionaryRef dict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, keys); __block CFDataRef data = NULL; - SecDbQueryRef query = query_create(genp_class(), NULL, dict, error); + SecDbQueryRef query = query_create(genp_class(), NULL, dict, NULL, error); if (query) { if (query->q_item) CFReleaseSafe(query->q_item); query->q_item = dict; diff --git a/keychain/securityd/SecItemDb.c b/keychain/securityd/SecItemDb.c index c5258625..739db220 100644 --- a/keychain/securityd/SecItemDb.c +++ b/keychain/securityd/SecItemDb.c @@ -313,8 +313,11 @@ s3dl_query_add(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, CFErrorRef * } #endif - if (ok) - ok = SecDbItemInsert(item, dbt, error); + if (ok) { + // We care about the new item's UUID only when we just made it from the primary key. + // Otherwise, we just made a random one, and don't mind if it changes. + ok = SecDbItemInsert(item, dbt, q->q_uuid_from_primary_key, error); + } if (ok) { if (result && q->q_return_type) { @@ -535,39 +538,22 @@ decode: // errSecDecode means the item is corrupted, stash it for delete. if (status == errSecDecode) { secwarning("ignoring corrupt %@,rowid=%" PRId64 " %@", q->q_class->name, rowid, q->q_error); - { - CFStringRef tablename = CFStringCreateCopy(kCFAllocatorDefault, q->q_class->name); - // Can't get rid of this item on the read path. Let's come back from elsewhere. - dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ - __block CFErrorRef localErr = NULL; - __block bool ok = true; - ok &= kc_with_dbt(true, &localErr, ^bool(SecDbConnectionRef dbt) { - CFStringRef sql = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DELETE FROM %@ WHERE rowid=%lli"), tablename, rowid); - ok &= SecDbPrepare(dbt, sql, &localErr, ^(sqlite3_stmt *stmt) { - ok &= SecDbStep(dbt, stmt, &localErr, NULL); - }); - - if (!ok || localErr) { - secerror("Failed to delete corrupt item, %@ row %lli: %@", tablename, rowid, localErr); - } else { - secnotice("item", "Deleted corrupt rowid %lli from table %@", rowid, tablename); - } - CFReleaseNull(localErr); - CFReleaseNull(sql); - CFReleaseSafe(tablename); - return ok; - }); - }); - CFDataRef edata = s3dl_copy_data_from_col(stmt, 1, NULL); - CFMutableStringRef edatastring = CFStringCreateMutable(kCFAllocatorDefault, 0); - if(edatastring) { - CFStringAppendEncryptedData(edatastring, edata); - secnotice("item", "corrupted edata=%@", edatastring); - } - CFReleaseSafe(edata); - CFReleaseSafe(edatastring); + // Can't get rid of this item on the read path. Let's come back from elsewhere. + CFStringRef tablename = CFStringCreateCopy(kCFAllocatorDefault, q->q_class->name); + deleteCorruptedItemAsync(c->dbt, tablename, rowid); + CFReleaseNull(tablename); + + // provide helpful logging statement + CFDataRef edata = s3dl_copy_data_from_col(stmt, 1, NULL); + CFMutableStringRef edatastring = CFStringCreateMutable(kCFAllocatorDefault, 0); + if(edatastring) { + CFStringAppendEncryptedData(edatastring, edata); + secnotice("item", "corrupted edata=%@", edatastring); } + CFReleaseSafe(edata); + CFReleaseSafe(edatastring); + CFReleaseNull(q->q_error); // This item was never here, keep going } else if (status == errSecAuthNeeded) { secwarning("Authentication is needed for %@,rowid=%" PRId64 " (%" PRIdOSStatus "): %@", q->q_class->name, rowid, status, q->q_error); @@ -731,6 +717,19 @@ SecDbAppendWhereMusr(CFMutableStringRef sql, } } +static void +SecDbAppendWhereAppClip(CFMutableStringRef sql, + const Query* q, + bool* needWhere) +{ + if (!q->q_skip_app_clip_items) { + return; + } + + SecDbAppendWhereOrAnd(sql, needWhere); + CFStringAppend(sql, CFSTR("clip = 0")); +} + static void SecDbAppendWhereClause(CFMutableStringRef sql, const Query *q, CFArrayRef accessGroups) { bool needWhere = true; @@ -738,6 +737,7 @@ static void SecDbAppendWhereClause(CFMutableStringRef sql, const Query *q, SecDbAppendWhereAttrs(sql, q, &needWhere); SecDbAppendWhereMusr(sql, q, &needWhere); SecDbAppendWhereAccessGroups(sql, CFSTR("agrp"), accessGroups, &needWhere); + SecDbAppendWhereAppClip(sql, q, &needWhere); } static void SecDbAppendLimit(CFMutableStringRef sql, CFIndex limit) { @@ -748,14 +748,14 @@ static void SecDbAppendLimit(CFMutableStringRef sql, CFIndex limit) { static CFStringRef s3dl_create_select_sql(Query *q, CFArrayRef accessGroups) { CFMutableStringRef sql = CFStringCreateMutable(NULL, 0); if (q->q_class == identity_class()) { - CFStringAppendFormat(sql, NULL, CFSTR("SELECT crowid, %@" - ", rowid,data FROM " - "(SELECT cert.rowid AS crowid, cert.labl AS labl," - " cert.issr AS issr, cert.slnr AS slnr, cert.skid AS skid," - " keys.*,cert.data AS %@" - " FROM keys, cert" - " WHERE keys.priv == 1 AND cert.pkhh == keys.klbl"), - kSecAttrIdentityCertificateData, kSecAttrIdentityCertificateData); + CFStringAppend(sql, CFSTR("SELECT crowid, certdata" + ", rowid,data FROM " + "(SELECT cert.rowid AS crowid, cert.labl AS labl," + " cert.issr AS issr, cert.slnr AS slnr, cert.skid AS skid," + " cert.tkid AS tkid," + " keys.*,cert.data AS certdata" + " FROM keys, cert" + " WHERE keys.priv == 1 AND cert.pkhh == keys.klbl")); SecDbAppendWhereAccessGroups(sql, CFSTR("cert.agrp"), accessGroups, 0); /* The next 3 SecDbAppendWhere calls are in the same order as in SecDbAppendWhereClause(). This makes sqlBindWhereClause() work, @@ -766,8 +766,10 @@ static CFStringRef s3dl_create_select_sql(Query *q, CFArrayRef accessGroups) { SecDbAppendWhereAttrs(sql, q, &needWhere); SecDbAppendWhereMusr(sql, q, &needWhere); SecDbAppendWhereAccessGroups(sql, CFSTR("agrp"), accessGroups, &needWhere); + SecDbAppendWhereAppClip(sql, q, &needWhere); } else { - CFStringAppend(sql, CFSTR("SELECT rowid, data FROM ")); + // Most of the time we don't need agrp, but if an item fails to decode and we want to know more then this is helpful + CFStringAppend(sql, CFSTR("SELECT rowid, data, agrp FROM ")); CFStringAppend(sql, q->q_class->name); SecDbAppendWhereClause(sql, q, accessGroups); } @@ -975,7 +977,7 @@ s3dl_copy_matching(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, CFSTR("attributes to query illegal; both row_id and other attributes can't be searched at the same time")); if (q->q_token_object_id && query_attr_count(q) != 1) return SecError(errSecItemIllegalQuery, error, - CFSTR("attributes to query illegal; both token persitent ref and other attributes can't be searched at the same time")); + CFSTR("attributes to query illegal; both token persistent ref and other attributes can't be searched at the same time")); // Only copy things that aren't tombstones unless the client explicitly asks otherwise. if (!CFDictionaryContainsKey(q->q_item, kSecAttrTombstone)) @@ -1128,10 +1130,7 @@ static CFBooleanRef s3dl_should_make_tombstone(Query *q, bool item_is_syncable, else return kCFBooleanFalse; } -/* AUDIT[securityd](done): - attributesToUpdate (ok) is a caller provided dictionary, - only its cf types have been checked. - */ + bool s3dl_query_update(SecDbConnectionRef dbt, Query *q, CFDictionaryRef attributesToUpdate, CFArrayRef accessGroups, CFErrorRef *error) @@ -1147,7 +1146,7 @@ s3dl_query_update(SecDbConnectionRef dbt, Query *q, return SecError(errSecItemIllegalQuery, error, CFSTR("attributes to update illegal; both token persistent ref and other attributes can't be updated at the same time")); __block bool result = true; - Query *u = query_create(q->q_class, NULL, attributesToUpdate, error); + Query *u = query_create(q->q_class, NULL, attributesToUpdate, NULL, error); if (u == NULL) return false; require_action_quiet(query_update_parse(u, attributesToUpdate, error), errOut, result = false); query_pre_update(u); @@ -1174,7 +1173,7 @@ s3dl_query_update(SecDbConnectionRef dbt, Query *q, // We just ignore this, and treat as if item is not found. secwarning("deleting corrupt %@,rowid=%" PRId64 " %@", q->q_class->name, SecDbItemGetRowId(item, NULL), localError); CFReleaseNull(localError); - if (!SecDbItemDelete(item, dbt, false, &localError)) { + if (!SecDbItemDelete(item, dbt, false, false, &localError)) { secerror("failed to delete corrupt %@,rowid=%" PRId64 " %@", q->q_class->name, SecDbItemGetRowId(item, NULL), localError); CFReleaseNull(localError); } @@ -1254,7 +1253,7 @@ s3dl_query_delete(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups, CFE bool item_is_sync = SecDbItemIsSyncable(item); SecDbItemSetValue(item, sha1attr, storedSHA1, NULL); CFReleaseSafe(storedSHA1); - ok = SecDbItemDelete(item, dbt, s3dl_should_make_tombstone(q, item_is_sync, item), error); + ok = SecDbItemDelete(item, dbt, s3dl_should_make_tombstone(q, item_is_sync, item), q->q_tombstone_use_mdat_from_item, error); if (ok) { q->q_changed = true; if (item_is_sync) @@ -1502,8 +1501,9 @@ fail: if (stmt) { ok = SecDbFinalize(stmt, error); } - if (!ok) + if (!ok) { secwarning("DeleteAllFromTableForMUSRView failed for %@ for musr: %@: %@", sql2, musr, error ? *error : NULL); + } CFReleaseNull(sql2); @@ -1526,6 +1526,34 @@ bool SecServerDeleteAllForUser(SecDbConnectionRef dbt, CFDataRef musrView, bool } #endif +OSStatus SecServerDeleteForAppClipApplicationIdentifier(CFStringRef identifier) { + secnotice("item", "Request to delete app clip keychain items for identifier '%@'", identifier); + + __block CFErrorRef cfError = NULL; + __block bool ok = true; + ok &= kc_with_dbt(true, &cfError, ^bool(SecDbConnectionRef dbt) { + return kc_transaction(dbt, &cfError, ^bool{ + const SecDbSchema* schema = current_schema(); + for (const SecDbClass *const * class = schema->classes; *class != NULL; ++class) { + if ((*class)->itemclass) { + CFStringRef sqlStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DELETE FROM %@ WHERE agrp = ? AND clip = 1"), (*class)->name); + ok &= SecDbPrepare(dbt, sqlStr, &cfError, ^(sqlite3_stmt *stmt) { + ok &= SecDbBindObject(stmt, 1, identifier, &cfError); + ok &= SecDbStep(dbt, stmt, &cfError, NULL); + }); + CFReleaseNull(sqlStr); + } + } + return ok; + }); + }); + + OSStatus status = ok ? errSecSuccess : errSecInternal; + secnotice("item", "Finished request to delete app clip keychain items for identifier '%@' with status %i: %@", identifier, (int)status, cfError); + CFReleaseNull(cfError); + + return status; +} struct s3dl_export_row_ctx { struct s3dl_query_ctx qc; @@ -1540,9 +1568,6 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { SecAccessControlRef access_control = NULL; CFErrorRef localError = NULL; - /* Skip akpu items when backing up, those are intentionally lost across restores. The same applies to SEP-based keys */ - bool skip_akpu_or_token = c->filter == kSecBackupableItemFilter; - sqlite_int64 rowid = sqlite3_column_int64(stmt, 0); CFMutableDictionaryRef allAttributes = NULL; CFMutableDictionaryRef metadataAttributes = NULL; @@ -1561,12 +1586,14 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { } } + /* Skip akpu items when backing up, those are intentionally lost across restores. The same applies to SEP-based keys */ bool is_akpu = access_control ? CFEqualSafe(SecAccessControlGetProtection(access_control), kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly) // Mask generation, only look at class per se : (keyclass & key_class_last) == key_class_akpu; bool is_token = (ok && allAttributes != NULL) ? CFDictionaryContainsKey(allAttributes, kSecAttrTokenID) : false; + bool skip_akpu_or_token = (is_akpu || is_token) && c->filter == kSecBackupableItemFilter; - if (ok && allAttributes && !(skip_akpu_or_token && (is_akpu || is_token))) { + if (ok && allAttributes && !skip_akpu_or_token) { /* Only export sysbound items if do_sys_bound is true, only export non sysbound items otherwise. */ bool do_sys_bound = c->filter == kSecSysBoundItemFilter; if (c->filter == kSecNoItemFilter || @@ -1607,7 +1634,7 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { CFReleaseSafe(pref); } } - } else { + } else if (!ok || !allAttributes) { OSStatus status = SecErrorGetOSStatus(localError); if (status == errSecInteractionNotAllowed && is_akpu) { @@ -1615,13 +1642,15 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { secdebug("item", "Skipping akpu item for backup"); } else { // Probably failed to decrypt sysbound item. Should never be an akpu item in backup. secerror("Encountered akpu item we cannot export (filter %d), skipping. %@", c->filter, localError); - CFDictionaryRef payload = NULL; - CFTypeRef agrp = CFDictionaryGetValue(allAttributes, CFSTR("agrp")); - if (agrp) { - payload = CFDictionaryCreateForCFTypes(NULL, CFSTR("agrp"), agrp, NULL); + if (sqlite3_column_count(stmt) > 2) { // Should have rowid,data,agrp from s3dl_create_select_sql + CFStringRef agrp = CFStringCreateWithCString(kCFAllocatorDefault, (const char*)sqlite3_column_text(stmt, 2), kCFStringEncodingUTF8); + if (agrp) { + CFDictionaryRef payload = CFDictionaryCreateForCFTypes(NULL, CFSTR("agrp"), agrp, NULL); + SecABCTrigger(CFSTR("keychain"), CFSTR("invalid-akpu+sysbound"), NULL, payload); + CFReleaseNull(payload); + } + CFReleaseNull(agrp); } - SecABCTrigger(CFSTR("keychain"), CFSTR("invalid-akpu+sysbound"), NULL, payload); - CFReleaseNull(payload); } // We expect akpu items to be inaccessible when the device is locked. CFReleaseNull(localError); @@ -1637,7 +1666,10 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { q->q_error = localError; } } + } else { + secnotice("item", "export rowid %llu skipped. akpu/token: %i", rowid, skip_akpu_or_token); } + CFReleaseNull(access_control); CFReleaseNull(allAttributes); CFReleaseNull(metadataAttributes); @@ -1659,7 +1691,6 @@ SecCreateKeybagUUID(keybag_handle_t keybag) #endif } - CFDictionaryRef SecServerCopyKeychainPlist(SecDbConnectionRef dbt, SecurityClient *client, @@ -1689,7 +1720,7 @@ SecServerCopyKeychainPlist(SecDbConnectionRef dbt, kSecReturnPersistentRefMask; q.q_limit = kSecMatchUnlimited; q.q_skip_acl_items = true; - + q.q_skip_app_clip_items = true; #if TARGET_OS_IPHONE if (client && client->inMultiUser) { @@ -1808,7 +1839,7 @@ SecServerImportItem(const void *value, void *context) if (state->s->src_keybag == KEYBAG_NONE) { item = SecDbItemCreateWithAttributes(kCFAllocatorDefault, state->class, dict, state->s->dest_keybag, &state->s->error); } else { - item = SecDbItemCreateWithBackupDictionary(kCFAllocatorDefault, state->class, dict, state->s->src_keybag, state->s->dest_keybag, &state->s->error); + item = SecDbItemCreateWithBackupDictionary(state->class, dict, state->s->src_keybag, state->s->dest_keybag, &state->s->error); } /* If item is NULL here, control flow ends up at the end where error is cleared. */ @@ -1906,7 +1937,7 @@ SecServerImportItem(const void *value, void *context) SecDbItemExtractRowIdFromBackupDictionary(item, dict, &state->s->error); } SecDbItemInferSyncable(item, &state->s->error); - insertStatus = SecDbItemInsert(item, state->s->dbt, &state->s->error); + insertStatus = SecDbItemInsert(item, state->s->dbt, false, &state->s->error); if (!insertStatus) { /* When running in EduMode, multiple users share the same @@ -1920,7 +1951,7 @@ SecServerImportItem(const void *value, void *context) again to insert the record. */ SecDbItemClearRowId(item, NULL); - SecDbItemInsert(item, state->s->dbt, &state->s->error); + SecDbItemInsert(item, state->s->dbt, false, &state->s->error); } } @@ -2158,7 +2189,7 @@ bool s3dl_dbt_keys_current(SecDbConnectionRef dbt, uint32_t current_generation, }; for (size_t class_ix = 0; class_ix < array_size(classes); ++class_ix) { - Query *q = query_create(classes[class_ix], NULL, NULL, &localError); + Query *q = query_create(classes[class_ix], NULL, NULL, NULL, &localError); if (!q) return false; diff --git a/keychain/securityd/SecItemDb.h b/keychain/securityd/SecItemDb.h index 3a07bb65..3f8efb9e 100644 --- a/keychain/securityd/SecItemDb.h +++ b/keychain/securityd/SecItemDb.h @@ -95,6 +95,7 @@ SecServerBackupGetKeybagUUID(CFDictionaryRef keychain, CFErrorRef *error); #if TARGET_OS_IPHONE bool SecServerDeleteAllForUser(SecDbConnectionRef dbt, CFDataRef musrView, bool keepU, CFErrorRef *error); #endif +OSStatus SecServerDeleteForAppClipApplicationIdentifier(CFStringRef identifier); bool kc_transaction(SecDbConnectionRef dbt, CFErrorRef *error, bool(^perform)(void)); bool kc_transaction_type(SecDbConnectionRef dbt, SecDbTransactionType type, CFErrorRef *error, bool(^perform)(void)); diff --git a/keychain/securityd/SecItemSchema.c b/keychain/securityd/SecItemSchema.c index 9a58ef42..b49cb54e 100644 --- a/keychain/securityd/SecItemSchema.c +++ b/keychain/securityd/SecItemSchema.c @@ -58,23 +58,25 @@ #define __FLAGS_V0 kSecDbSyncPrimaryKeyV0 #define __FLAGS_V2 (kSecDbSyncPrimaryKeyV0 | kSecDbSyncPrimaryKeyV2) #define __FLAGS_Y kSecDbSyncFlag +#define __FLAGS_X kSecDbSyncFlag | kSecDbSyncSOSCannotSyncFlag // ,----------------- P : Part of primary key // / ,---------------- L : Stored in local database // / / ,--------------- I : Attribute wants an index in the database // / / / ,-------------- S : SHA1 hashed attribute value in database (implies L) -// / / / / ,------------- A : Returned to client as attribute in queries -// / / / / / ,------------ D : Returned to client as data in queries +// / / / / ,------------- A : Returned to client as attribute in queries (implied by C) +// / / / / / ,------------ D : Returned to client as data in queries (implied by C) // / / / / / / ,----------- R : Returned to client as ref/persistent ref in queries // / / / / / / / ,---------- C : Part of encrypted blob -// / / / / / / / / ,--------- H : Attribute is part of item SHA1 hash (Implied by C) +// / / / / / / / / ,--------- H : Attribute is part of item SHA1 hash // / / / / / / / / / ,-------- B : Attribute is part of iTunes/iCloud backup bag // / / / / / / / / / / ,------- Z : Attribute has a default value of 0 // / / / / / / / / / / / ,------ E : Attribute has a default value of "" or empty data // / / / / / / / / / / / / ,----- N : Attribute must have a value // / / / / / / / / / / / / / ,---- U : Attribute is stored in authenticated, but not necessarily encrypted data // / / / / / / / / / / / / / / ,--- V0: Sync primary key version -// / / / / / / / / / / / / / / / ,- Y : Attribute should be synced +// / / / / / / / / / / / / / / / ,- Y : Attribute should be synced, or +// | | | | | | | | | | | | | | | | X : Attribute should be synced in CKKS, and ignored in SOS // | | | | | | | | | | | | | | | | // common to all | | | | | | | | | | | | | | | | SECDB_ATTR(v6rowid, "rowid", RowId, SecDbFlags( ,L, , , , ,R, , ,B, , , , , , ), NULL, NULL); @@ -82,9 +84,9 @@ SECDB_ATTR(v6cdat, "cdat", CreationDate, SecDbFlags( ,L, , ,A, , ,C,H, , , , , SECDB_ATTR(v6mdat, "mdat",ModificationDate,SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ,Y), SecDbKeychainItemCopyCurrentDate, NULL); SECDB_ATTR(v6labl, "labl", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , , ,Y), NULL, NULL); SECDB_ATTR(v6data, "data", EncryptedData, SecDbFlags( ,L, , , , , , , ,B, , , , , , ), SecDbKeychainItemCopyEncryptedData, NULL); -SECDB_ATTR(v6agrp, "agrp", String, SecDbFlags(P,L,I, ,A, , , ,H, , , ,N,U,V0,Y), NULL, NULL); +SECDB_ATTR(v6agrp, "agrp", String, SecDbFlags(P,L, , ,A, , , ,H, , , ,N,U,V0,Y), NULL, NULL); SECDB_ATTR(v6pdmn, "pdmn", Access, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ,Y), NULL, NULL); -SECDB_ATTR(v6sync, "sync", Sync, SecDbFlags(P,L,I, ,A, , , ,H, ,Z, ,N,U,V0, ), NULL, NULL); +SECDB_ATTR(v6sync, "sync", Sync, SecDbFlags(P,L, , ,A, , , ,H, ,Z, ,N,U,V0, ), NULL, NULL); SECDB_ATTR(v6tomb, "tomb", Tomb, SecDbFlags( ,L, , , , , , ,H, ,Z, ,N,U, ,Y), NULL, NULL); SECDB_ATTR(v6sha1, "sha1", SHA1, SecDbFlags( ,L,I, ,A, ,R, , , , , , , , ,Y), SecDbKeychainItemCopySHA1, NULL); SECDB_ATTR(v6accc, "accc", AccessControl, SecDbFlags( , , , ,A, , , , , , , , , , , ), NULL, NULL); @@ -93,7 +95,8 @@ SECDB_ATTR(v6v_pk, "v_pk", PrimaryKey, SecDbFlags( , , , , , , , , , , , , , SECDB_ATTR(v7vwht, "vwht", String, SecDbFlags(P,L,I, ,A, , , ,H, , , , ,U,V2,Y), NULL, NULL); SECDB_ATTR(v7tkid, "tkid", String, SecDbFlags(P,L,I, ,A, , , ,H, , , , ,U,V2,Y), NULL, NULL); SECDB_ATTR(v7utomb, "u_Tomb", UTomb, SecDbFlags( , , , , , , , , , , , , , , , ), NULL, NULL); -SECDB_ATTR(v8musr, "musr", UUID, SecDbFlags(P,L,I, , , , , , , , , ,N,U, ,Y), NULL, NULL); +SECDB_ATTR(v8musr, "musr", UUID, SecDbFlags(P,L, , , , , , , , , , ,N,U, ,Y), NULL, NULL); +SECDB_ATTR(v11_7appclip, "clip", Number, SecDbFlags( ,L, , , , , , , , ,Z, ,N, , , ), NULL, NULL); // genp and inet and keys | | | | | | | | | | | | | | | | SECDB_ATTR(v6crtr, "crtr", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ,Y), NULL, NULL); SECDB_ATTR(v6alis, "alis", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , , ,Y), NULL, NULL); @@ -245,6 +248,16 @@ SECDB_ATTR(v11_5octagonStatus, "octagonstatus", String, SecDbFlags( ,L, , , , SECDB_ATTR(v11_6moreComing, "morecoming", Number, SecDbFlags( ,L, , , , , , , , , , , , , , ), NULL, NULL); +SECDB_ATTR(v11_8_bin_notes, "binn", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); +SECDB_ATTR(v11_8_bin_history, "bini", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); +SECDB_ATTR(v11_8_bin_client0, "bin0", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); +SECDB_ATTR(v11_8_bin_client1, "bin1", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); +SECDB_ATTR(v11_8_bin_client2, "bin2", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); +SECDB_ATTR(v11_8_bin_client3, "bin3", Data, SecDbFlags( , , , , ,D, ,C, , , , , , , ,X), NULL, NULL); + +SECDB_ATTR(v11_9_lastscan, "lastscan", String, SecDbFlags( ,L, , , , , , , , , , , , , , ), NULL, NULL); +SECDB_ATTR(v11_9_extra, "extra", Blob, SecDbFlags( ,L, , , , , , , , , , , , , , ), NULL, NULL); + SECDB_ATTR(v12_backupUUIDPrimary, "backupUUID", UUID, SecDbFlags(P,L,I, , , , , , , , , ,N, , , ), NULL, NULL); SECDB_ATTR(v12_backupUUID, "backupUUID", UUID, SecDbFlags( ,L,I, , , , , , , , ,E, , , , ), NULL, NULL); SECDB_ATTR(v12_backupBag, "backupbag", Blob, SecDbFlags( ,L, , , , , , , , , , ,N, , , ), NULL, NULL); @@ -339,6 +352,7 @@ const SecDbClass v12_genp_class = { &v10_1pcspublickey, &v10_1pcspublicidentity, &v10_1itempersistentref, + &v11_7appclip, &v12_backupUUID, 0 }, @@ -388,6 +402,13 @@ const SecDbClass v12_inet_class = { &v10_1pcspublickey, &v10_1pcspublicidentity, &v10_1itempersistentref, + &v11_7appclip, + &v11_8_bin_notes, + &v11_8_bin_history, + &v11_8_bin_client0, + &v11_8_bin_client1, + &v11_8_bin_client2, + &v11_8_bin_client3, &v12_backupUUID, 0 }, @@ -428,6 +449,7 @@ const SecDbClass v12_cert_class = { &v10_1pcspublickey, &v10_1pcspublicidentity, &v10_1itempersistentref, + &v11_7appclip, &v12_backupUUID, 0 }, @@ -486,11 +508,277 @@ const SecDbClass v12_keys_class = { &v10_1pcspublickey, &v10_1pcspublicidentity, &v10_1itempersistentref, + &v11_7appclip, &v12_backupUUID, 0 } }; +const SecDbClass v11_9_ckstate_class = { + .name = CFSTR("ckstate"), + .itemclass = false, + .attrs = { + &v10ckzone, + &v10ckzonecreated, + &v10ckzonesubscribed, + &v10lastfetchtime, + &v10changetoken, + &v10ratelimiter, + &v10_4lastFixup, + &v11_6moreComing, + &v11_9_lastscan, + &v11_9_extra, + 0 + } +}; + +const SecDbClass v11_8_inet_class = { + .name = CFSTR("inet"), + .itemclass = true, + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6sdmn, + &v6srvr, + &v6ptcl, + &v6atyp, + &v6port, + &v6path, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + &v10itemuuid, + &v10sysbound, + &v10_1pcsservice, + &v10_1pcspublickey, + &v10_1pcspublicidentity, + &v10_1itempersistentref, + &v11_7appclip, + &v11_8_bin_notes, + &v11_8_bin_history, + &v11_8_bin_client0, + &v11_8_bin_client1, + &v11_8_bin_client2, + &v11_8_bin_client3, + 0 + }, +}; + +const SecDbClass v11_7_genp_class = { + .name = CFSTR("genp"), + .itemclass = true, + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6svce, + &v6gena, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + &v10itemuuid, + &v10sysbound, + &v10_1pcsservice, + &v10_1pcspublickey, + &v10_1pcspublicidentity, + &v10_1itempersistentref, + &v11_7appclip, + 0 + }, +}; + +const SecDbClass v11_7_inet_class = { + .name = CFSTR("inet"), + .itemclass = true, + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6sdmn, + &v6srvr, + &v6ptcl, + &v6atyp, + &v6port, + &v6path, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + &v10itemuuid, + &v10sysbound, + &v10_1pcsservice, + &v10_1pcspublickey, + &v10_1pcspublicidentity, + &v10_1itempersistentref, + &v11_7appclip, + 0 + }, +}; + +const SecDbClass v11_7_cert_class = { + .name = CFSTR("cert"), + .itemclass = true, + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6ctyp, + &v6cenc, + &v6labl, + &v6certalis, + &v6subj, + &v6issr, + &v6slnr, + &v6skid, + &v6pkhh, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + &v10itemuuid, + &v10sysbound, + &v10_1pcsservice, + &v10_1pcspublickey, + &v10_1pcspublicidentity, + &v10_1itempersistentref, + &v11_7appclip, + 0 + }, +}; + +const SecDbClass v11_7_keys_class = { + .name = CFSTR("keys"), + .itemclass = true, + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6kcls, + &v6labl, + &v6alis, + &v6perm, + &v6priv, + &v6modi, + &v6klbl, + &v6atag, + &v6keycrtr, + &v6keytype, + &v6bsiz, + &v6esiz, + &v6sdat, + &v6edat, + &v6sens, + &v6asen, + &v6extr, + &v6next, + &v6encr, + &v6decr, + &v6drve, + &v6sign, + &v6vrfy, + &v6snrc, + &v6vyrc, + &v6wrap, + &v6unwp, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + &v10itemuuid, + &v10sysbound, + &v10_1pcsservice, + &v10_1pcspublickey, + &v10_1pcspublicidentity, + &v10_1itempersistentref, + &v11_7appclip, + 0 + } +}; + const SecDbClass v11_6_ckstate_class = { .name = CFSTR("ckstate"), .itemclass = false, @@ -1248,7 +1536,7 @@ const SecDbSchema v12_0_schema = { &v10_0_sync_key_class, &v10_1_ckmirror_class, &v10_0_current_key_class, - &v11_6_ckstate_class, + &v11_9_ckstate_class, &v10_0_item_backup_class, &v10_0_backup_keybag_class, &v10_2_ckmanifest_class, @@ -1269,6 +1557,114 @@ const SecDbSchema v12_0_schema = { } }; +/* + * Version 11.9 + * Add extra columns for CKState + */ +const SecDbSchema v11_9_schema = { + .majorVersion = 11, + .minorVersion = 9, + .classes = { + &v11_7_genp_class, + &v11_8_inet_class, + &v11_7_cert_class, + &v11_7_keys_class, + &v10_0_tversion_class, + &v10_2_outgoing_queue_class, + &v10_2_incoming_queue_class, + &v10_0_sync_key_class, + &v10_1_ckmirror_class, + &v10_0_current_key_class, + &v11_9_ckstate_class, + &v10_0_item_backup_class, + &v10_0_backup_keybag_class, + &v10_2_ckmanifest_class, + &v10_2_pending_manifest_class, + &v10_1_ckmanifest_leaf_class, + &v10_1_backup_keyarchive_class, + &v10_1_current_keyarchive_class, + &v10_1_current_archived_keys_class, + &v10_1_pending_manifest_leaf_class, + &v10_4_current_item_class, + &v11_5_ckdevicestate_class, + &v10_5_tlkshare_class, + &v11_2_metadatakeys_class, + 0 + } +}; + +/* + * Version 11.8 + * Add extra binary columns to inet + */ +const SecDbSchema v11_8_schema = { + .majorVersion = 11, + .minorVersion = 8, + .classes = { + &v11_7_genp_class, + &v11_8_inet_class, + &v11_7_cert_class, + &v11_7_keys_class, + &v10_0_tversion_class, + &v10_2_outgoing_queue_class, + &v10_2_incoming_queue_class, + &v10_0_sync_key_class, + &v10_1_ckmirror_class, + &v10_0_current_key_class, + &v11_6_ckstate_class, + &v10_0_item_backup_class, + &v10_0_backup_keybag_class, + &v10_2_ckmanifest_class, + &v10_2_pending_manifest_class, + &v10_1_ckmanifest_leaf_class, + &v10_1_backup_keyarchive_class, + &v10_1_current_keyarchive_class, + &v10_1_current_archived_keys_class, + &v10_1_pending_manifest_leaf_class, + &v10_4_current_item_class, + &v11_5_ckdevicestate_class, + &v10_5_tlkshare_class, + &v11_2_metadatakeys_class, + 0 + } +}; + +/* + * Version 11.7 + * Add 'clip' column to denote item was made by App Clip + */ +const SecDbSchema v11_7_schema = { + .majorVersion = 11, + .minorVersion = 7, + .classes = { + &v11_7_genp_class, + &v11_7_inet_class, + &v11_7_cert_class, + &v11_7_keys_class, + &v10_0_tversion_class, + &v10_2_outgoing_queue_class, + &v10_2_incoming_queue_class, + &v10_0_sync_key_class, + &v10_1_ckmirror_class, + &v10_0_current_key_class, + &v11_6_ckstate_class, + &v10_0_item_backup_class, + &v10_0_backup_keybag_class, + &v10_2_ckmanifest_class, + &v10_2_pending_manifest_class, + &v10_1_ckmanifest_leaf_class, + &v10_1_backup_keyarchive_class, + &v10_1_current_keyarchive_class, + &v10_1_current_archived_keys_class, + &v10_1_pending_manifest_leaf_class, + &v10_4_current_item_class, + &v11_5_ckdevicestate_class, + &v10_5_tlkshare_class, + &v11_2_metadatakeys_class, + 0 + } +}; + /* * Version 11.6 (Add 'moreComing' field to zone state) */ @@ -2920,6 +3316,9 @@ SecDbSchema const * const * kc_schemas = NULL; const SecDbSchema *v10_kc_schemas_dev[] = { &v12_0_schema, + &v11_9_schema, + &v11_8_schema, + &v11_7_schema, &v11_6_schema, &v11_5_schema, &v11_4_schema, @@ -2943,6 +3342,9 @@ const SecDbSchema *v10_kc_schemas_dev[] = { }; const SecDbSchema *v10_kc_schemas[] = { + &v11_9_schema, + &v11_8_schema, + &v11_7_schema, &v11_6_schema, &v11_5_schema, &v11_4_schema, diff --git a/keychain/securityd/SecItemServer+SWC.h b/keychain/securityd/SecItemServer+SWC.h new file mode 100644 index 00000000..d970c894 --- /dev/null +++ b/keychain/securityd/SecItemServer+SWC.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2007-2019 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@ + */ + +#include + +#if TARGET_OS_IOS && !TARGET_OS_BRIDGE +#include + +// Compatibility wrappers for SWC Objective-C interface. +typedef enum SecSWCFlags { + kSecSWCFlags_None = 0, + kSecSWCFlag_UserApproved = (1 << 0), + kSecSWCFlag_UserDenied = (1 << 1), + kSecSWCFlag_SiteApproved = (1 << 2), + kSecSWCFlag_SiteDenied = (1 << 3), +} SecSWCFlags; + +extern SecSWCFlags _SecAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFErrorRef *error); +extern void _SecSetAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFBooleanRef approved); + +extern CFTypeRef _SecCopyFQDNObjectFromString(CFStringRef entitlementValue); +extern CFStringRef _SecGetFQDNFromFQDNObject(CFTypeRef fqdnObject, SInt32 *outPort); +#if !TARGET_OS_SIMULATOR +extern bool _SecEntitlementContainsDomainForService(CFArrayRef domains, CFStringRef domain, SInt32 port); +#endif /* !TARGET_OS_SIMULATOR */ +#endif // TARGET_OS_IOS && !TARGET_OS_BRIDGE diff --git a/keychain/securityd/SecItemServer+SWC.m b/keychain/securityd/SecItemServer+SWC.m new file mode 100644 index 00000000..0c601a36 --- /dev/null +++ b/keychain/securityd/SecItemServer+SWC.m @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2007-2019 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@ + */ + +#import "SecItemServer+SWC.h" + +#if TARGET_OS_IOS && !TARGET_OS_BRIDGE +#import + +#import "utilities/debugging.h" +#import "utilities/SecCFError.h" + +// Methods in this category are here temporarily until I can add SPI in +// _SWCServiceSpecifier for the function below to consume. +@interface NSObject (Workaround61065225) +- (NSString *)domainHost; +@end + +SecSWCFlags _SecAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFErrorRef *error) +{ + __block SecSWCFlags flags = kSecSWCFlags_None; + + @autoreleasepool { + secnotice("swc", "Application %@ is requesting approval for %@", appID, fqdn); + + _SWCServiceSpecifier *specifier = [[_SWCServiceSpecifier alloc] initWithServiceType:_SWCServiceTypeWebCredentials + applicationIdentifier:(__bridge NSString *)appID + domain:(__bridge NSString *)fqdn]; + NSError *err = nil; + NSArray<_SWCServiceDetails *> *allDetails = [_SWCServiceDetails serviceDetailsWithServiceSpecifier:specifier error:&err]; + if (allDetails) { + _SWCServiceDetails *details = allDetails.firstObject; + if (details) { + switch (details.userApprovalState) { + case SWCServiceApprovalStateApproved: + flags |= kSecSWCFlag_UserApproved; + break; + + case SWCServiceApprovalStateDenied: + flags |= kSecSWCFlag_UserDenied; + break; + + default: + break; + } + switch (details.siteApprovalState) { + case SWCServiceApprovalStateApproved: + flags |= kSecSWCFlag_SiteApproved; + break; + + case SWCServiceApprovalStateDenied: + flags |= kSecSWCFlag_SiteDenied; + break; + + default: + break; + } + } + + } else { + // An error occurred. + secerror("+[_SWCServiceDetails serviceDetailsWithServiceSpecifier:error:] failed with %@", err); + } + } + + if (error) { + if (!(flags & kSecSWCFlag_SiteApproved)) { + SecError(errSecAuthFailed, error, CFSTR("\"%@\" failed to approve \"%@\""), fqdn, appID); + } else if (flags & kSecSWCFlag_UserDenied) { + SecError(errSecAuthFailed, error, CFSTR("User denied access to \"%@\" by \"%@\""), fqdn, appID); + } + } + + return flags; +} + +void _SecSetAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFBooleanRef approved) +{ + _SWCServiceSpecifier *specifier = [[_SWCServiceSpecifier alloc] initWithServiceType:_SWCServiceTypeWebCredentials + applicationIdentifier:(__bridge NSString *)appID + domain:(__bridge NSString *)fqdn]; + NSError *err = nil; + NSArray<_SWCServiceDetails *> *allDetails = [_SWCServiceDetails serviceDetailsWithServiceSpecifier:specifier error:&err]; + if (allDetails) { + _SWCServiceDetails *details = allDetails.firstObject; + if (details) { + SWCServiceApprovalState state = SWCServiceApprovalStateUnspecified; + if (approved == kCFBooleanTrue) { + state = SWCServiceApprovalStateApproved; + } else if (approved == kCFBooleanFalse) { + state = SWCServiceApprovalStateDenied; + } + if (![details setUserApprovalState:state error:&err]) { + secerror("-[_SWCServiceDetails setUserApprovalState:error:] failed with %@", err); + } + } + + } else { + secerror("+[_SWCServiceDetails serviceDetailsWithServiceSpecifier:error:] failed with %@", err); + } +} + +CFTypeRef _SecCopyFQDNObjectFromString(CFStringRef entitlementValue) +{ + CFTypeRef result = NULL; + + @autoreleasepool { + _SWCServiceSpecifier *serviceSpecifier = [_SWCServiceSpecifier serviceSpecifiersWithEntitlementValue:@[ (__bridge NSString *)entitlementValue ] error:NULL].firstObject; + if (!serviceSpecifier) { + serviceSpecifier = [[_SWCServiceSpecifier alloc] initWithServiceType:nil applicationIdentifier:nil domain:(__bridge NSString *)entitlementValue]; + } + if (serviceSpecifier) { + // Hiding an ObjC reference in a CFTypeRef since the caller is pure C. + result = CFBridgingRetain(serviceSpecifier); + } + } + + return result; +} + +CFStringRef _SecGetFQDNFromFQDNObject(CFTypeRef fqdnObject, SInt32 *outPort) +{ + CFStringRef result = NULL; + SInt32 port = -1; + + // Extracting an ObjC reference from a CFTypeRef since the caller is pure C. + _SWCServiceSpecifier *serviceSpecifier = (__bridge _SWCServiceSpecifier *)fqdnObject; + result = (__bridge CFStringRef)serviceSpecifier.domainHost; + if (outPort) { + NSNumber *portNumber = serviceSpecifier.domainPort; + if (portNumber) { + port = portNumber.unsignedShortValue; + } + + *outPort = port; + } + + return result; +} + +#if !TARGET_OS_SIMULATOR +bool _SecEntitlementContainsDomainForService(CFArrayRef domains, CFStringRef domain, SInt32 port) +{ + bool result = false; + + @autoreleasepool { + NSArray<_SWCServiceSpecifier *> *serviceSpecifiers; + serviceSpecifiers = [_SWCServiceSpecifier serviceSpecifiersWithEntitlementValue:(__bridge NSArray *)domains + serviceType:_SWCServiceTypeWebCredentials + error:NULL]; + for (_SWCServiceSpecifier *serviceSpecifier in serviceSpecifiers) { + // Check if the hostname matches. + NSString *specifierDomain = [serviceSpecifier domainHost]; + if (NSOrderedSame == [specifierDomain caseInsensitiveCompare:(__bridge NSString *)domain]) { + result = true; + + // Also check the port if specified by the caller. + if (result && port >= 0) { + NSNumber *specifierPort = serviceSpecifier.domainPort; + result = [specifierPort isEqualToNumber:@(port)]; + } + + if (result) { + break; + } + } + } + } + + return result; +} +#endif /* !TARGET_OS_SIMULATOR */ +#endif // TARGET_OS_IOS && !TARGET_OS_BRIDGE diff --git a/keychain/securityd/SecItemServer.c b/keychain/securityd/SecItemServer.c index cd9c7b97..fcace148 100644 --- a/keychain/securityd/SecItemServer.c +++ b/keychain/securityd/SecItemServer.c @@ -40,6 +40,8 @@ #include "keychain/securityd/SecItemDb.h" #include "keychain/securityd/SecItemSchema.h" #include +#include +#import #include "keychain/securityd/SecDbKeychainItem.h" #include "keychain/securityd/SOSCloudCircleServer.h" #include @@ -78,7 +80,6 @@ #endif #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR -#include #include #include #endif @@ -91,10 +92,8 @@ #include #include "swcagent_client.h" #include "SecPLWrappers.h" - -#if TARGET_OS_IOS && !TARGET_OS_BRIDGE -#include -#endif +#include "SecItemServer+SWC.h" +#include #include @@ -175,6 +174,7 @@ bool SecKeychainDbGetVersion(SecDbConnectionRef dbt, int *version, CFErrorRef *e } out: secnotice("upgr", "database version is: 0x%08x : %d : %@", *version, ok, localError); + secnotice("upgr", "UID: %d EUID: %d", getuid(), geteuid()); CFReleaseSafe(localError); @@ -213,11 +213,11 @@ measureUpgradePhase1(struct timeval *start, bool success, int64_t itemsMigrated) int64_t duration = measureDuration(start); if (success) { - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-items-success"), itemsMigrated); - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-time-success"), duration); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase1.migrated-items-success"), itemsMigrated); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase1.migrated-time-success"), duration); } else { - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-items-fail"), itemsMigrated); - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-time-fail"), duration); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase1.migrated-items-fail"), itemsMigrated); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase1.migrated-time-fail"), duration); } } @@ -226,8 +226,8 @@ measureUpgradePhase2(struct timeval *start, int64_t itemsMigrated) { int64_t duration = measureDuration(start); - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase2.migrated-items"), itemsMigrated); - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.phase2.migrated-time"), duration); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase2.migrated-items"), itemsMigrated); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.phase2.migrated-time"), duration); } #endif /* TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR */ @@ -372,7 +372,7 @@ static bool UpgradeSchemaPhase1(SecDbConnectionRef dbt, const SecDbSchema *oldSc // Prepare query to iterate through all items in cur_class. if (query != NULL) query_destroy(query, NULL); - require_quiet(query = query_create(renamedOldClass, SecMUSRGetAllViews(), NULL, error), out); + require_quiet(query = query_create(renamedOldClass, SecMUSRGetAllViews(), NULL, NULL, error), out); ok &= SecDbItemSelect(query, dbt, error, ^bool(const SecDbAttr *attr) { // We are interested in all attributes which are physically present in the DB. @@ -410,7 +410,7 @@ static bool UpgradeSchemaPhase1(SecDbConnectionRef dbt, const SecDbSchema *oldSc secnotice("upgr", "dropping item during schema upgrade due to agrp=com.apple.token: %@", item); } else { // Insert new item into the new table. - if (!SecDbItemInsert(item, dbt, &localError)) { + if (!SecDbItemInsert(item, dbt, false, &localError)) { secerror("item: %@ insert during upgrade: %@", item, localError); ok = false; } @@ -554,7 +554,7 @@ static bool UpgradeItemPhase2(SecDbConnectionRef inDbt, bool *inProgress, int ol if (query != NULL) { query_destroy(query, NULL); } - require_action_quiet(query = query_create(*class, SecMUSRGetAllViews(), NULL, error), out, ok = false); + require_action_quiet(query = query_create(*class, SecMUSRGetAllViews(), NULL, NULL, error), out, ok = false); ok &= SecDbItemSelect(query, threadDbt, error, NULL, ^bool(const SecDbAttr *attr) { // No simple per-attribute filtering. return false; @@ -586,7 +586,7 @@ static bool UpgradeItemPhase2(SecDbConnectionRef inDbt, bool *inProgress, int ol if (CFEqualSafe(SecDbItemGetCachedValueWithName(item, kSecAttrAccessGroup), kSecAttrAccessGroupToken) && SecDbItemGetCachedValueWithName(item, kSecAttrTokenID) == NULL) { secnotice("upgr", "dropping item during item upgrade due to agrp=com.apple.token: %@", item); - ok = SecDbItemDelete(item, threadDbt, kCFBooleanFalse, &localError); + ok = SecDbItemDelete(item, threadDbt, kCFBooleanFalse, false, &localError); } else { // Replace item with the new value in the table; this will cause the item to be decoded and recoded back, // incl. recalculation of item's hash. @@ -603,7 +603,7 @@ static bool UpgradeItemPhase2(SecDbConnectionRef inDbt, bool *inProgress, int ol // make sure we use a local error so that this error is not proppaged upward and cause a // migration failure. CFErrorRef deleteError = NULL; - (void)SecDbItemDelete(item, threadDbt, false, &deleteError); + (void)SecDbItemDelete(item, threadDbt, false, false, &deleteError); CFReleaseNull(deleteError); ok = true; break; @@ -670,6 +670,42 @@ out: return ok; } +// There's no data-driven approach for this. Let's think about it more if it gets unwieldy +static void performCustomIndexProcessing(SecDbConnectionRef dbt) { + CFErrorRef cfErr = NULL; + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS genpagrp; DROP INDEX IF EXISTS genpsync;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS inetagrp; DROP INDEX IF EXISTS inetsync;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS certagrp; DROP INDEX IF EXISTS certsync;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS keysagrp; DROP INDEX IF EXISTS keyssync;"), &cfErr), errhandler); + + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS genpsync0;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS inetsync0;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS certsync0;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS keyssync0;"), &cfErr), errhandler); + + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS genpmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS inetmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS certmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS keysmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS item_backupmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS backup_keybagmusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS backup_keyarchivemusr;"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("DROP INDEX IF EXISTS archived_key_backupmusr;"), &cfErr), errhandler); + + require(SecDbExec(dbt, CFSTR("CREATE INDEX IF NOT EXISTS agrp_musr_tomb_svce ON genp(agrp, musr, tomb, svce);"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("CREATE INDEX IF NOT EXISTS agrp_musr_tomb_srvr ON inet(agrp, musr, tomb, srvr);"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("CREATE INDEX IF NOT EXISTS agrp_musr_tomb_subj ON cert(agrp, musr, tomb, subj);"), &cfErr), errhandler); + require(SecDbExec(dbt, CFSTR("CREATE INDEX IF NOT EXISTS agrp_musr_tomb_atag ON keys(agrp, musr, tomb, atag);"), &cfErr), errhandler); + + secnotice("upgr", "processed custom indexes (now or in the past)"); + CFReleaseNull(cfErr); // Should be nil but belt and suspenders + return; + +errhandler: + secerror("upgr: failed to process custom indexes: %@", cfErr); + CFReleaseNull(cfErr); +} + static bool SecKeychainDbUpgradeFromVersion(SecDbConnectionRef dbt, int version, bool *inProgress, CFErrorRef *error) { __block bool didPhase2 = false; __block bool ok = true; @@ -707,6 +743,7 @@ static bool SecKeychainDbUpgradeFromVersion(SecDbConnectionRef dbt, int version, // If this is empty database, just create table according to schema and be done with it. require_action_quiet(version2 != 0, out, ok = SecItemDbCreateSchema(dbt, newSchema, NULL, true, &localError); + performCustomIndexProcessing(dbt); LKAReportKeychainUpgradeOutcomeWithError(version2, newVersion, LKAKeychainUpgradeOutcomeNewDb, localError)); int oldVersion = VERSION_OLD(version2); @@ -796,7 +833,7 @@ static bool SecKeychainDbUpgradeFromVersion(SecDbConnectionRef dbt, int version, if (ok && didPhase2) { #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.migration-success"), 1); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.migration-success"), 1); #endif } @@ -839,7 +876,7 @@ out: secerror("upgrade: marking database as corrupt"); SecDbCorrupt(dbt, localError); #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR - SecADSetValueForScalarKey(CFSTR("com.apple.keychain.migration-failure"), 1); + SecCoreAnalyticsSendValue(CFSTR("com.apple.keychain.migration-failure"), 1); #endif } } else { @@ -851,19 +888,13 @@ out: //If we're done here, we should opportunistically re-add all indices (just in case) if(skipped_upgrade || didPhase2) { // Create indices, ignoring all errors + performCustomIndexProcessing(dbt); for (SecDbClass const* const* newClass = newSchema->classes; *newClass; ++newClass) { SecDbForEachAttrWithMask((*newClass), desc, kSecDbIndexFlag | kSecDbInFlag) { CFStringRef sql = NULL; CFErrorRef classLocalError = NULL; bool localOk = true; - - if (desc->kind == kSecDbSyncAttr) { - // Replace the complete sync index with a partial index for sync=0. Most items are sync=1, so the complete index isn't helpful for sync=1 queries. - sql = CFStringCreateWithFormat(NULL, NULL, CFSTR("DROP INDEX IF EXISTS %@%@; CREATE INDEX IF NOT EXISTS %@%@0 on %@(%@) WHERE %@=0;"), - (*newClass)->name, desc->name, (*newClass)->name, desc->name, (*newClass)->name, desc->name, desc->name); - } else { - sql = CFStringCreateWithFormat(NULL, NULL, CFSTR("CREATE INDEX IF NOT EXISTS %@%@ ON %@(%@);"), (*newClass)->name, desc->name, (*newClass)->name, desc->name); - } + sql = CFStringCreateWithFormat(NULL, NULL, CFSTR("CREATE INDEX IF NOT EXISTS %@%@ ON %@(%@);"), (*newClass)->name, desc->name, (*newClass)->name, desc->name); localOk &= SecDbExec(dbt, sql, &classLocalError); CFReleaseNull(sql); @@ -1234,7 +1265,7 @@ void SecKeychainDbReset(dispatch_block_t inbetween) dispatch_sync(get_kc_dbhandle_dispatch(), ^{ CFReleaseNull(_kc_dbhandle); SecDbResetMetadataKeys(); - + SecDbResetBackupManager(); if (inbetween) inbetween(); }); @@ -1286,12 +1317,12 @@ bool kc_with_custom_db(bool writeAndRead, bool usesItemTables, SecDbRef db, CFEr // The kc_with_dbt upthread will clean this up when it's done. return perform(threadDbt); } - - if (writeAndRead && usesItemTables) { + #if SECUREOBJECTSYNC + if (writeAndRead && usesItemTables) { SecItemDataSourceFactoryGetDefault(); -#endif } +#endif bool ok = false; if (kc_acquire_dbt(writeAndRead, &threadDbt, error)) { @@ -1323,7 +1354,7 @@ items_matching_issuer_parent(SecDbConnectionRef dbt, CFArrayRef accessGroups, CF return false; CFErrorRef localError = NULL; - q = query_create_with_limit(query, musrView, kSecMatchUnlimited, &localError); + q = query_create_with_limit(query, musrView, kSecMatchUnlimited, NULL, &localError); CFRelease(query); if (q) { s3dl_copy_matching(dbt, q, (CFTypeRef*)&results, accessGroups, &localError); @@ -1544,6 +1575,46 @@ out: return ok; } +//Mark: - + +void deleteCorruptedItemAsync(SecDbConnectionRef dbt, CFStringRef tablename, sqlite_int64 rowid) +{ + // should really get db from dbt, but I don't know much much we should poke holes thought the boundaries. + SecDbRef db = kc_dbhandle(NULL); + if (db == NULL) { + return; + } + + CFRetain(db); + CFRetain(tablename); + + dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ + __block CFErrorRef localErr = NULL; + kc_with_custom_db(true, true, db, &localErr, ^bool(SecDbConnectionRef dbt) { + CFStringRef sql = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DELETE FROM %@ WHERE rowid=%lli"), tablename, rowid); + __block bool ok = true; + ok &= SecDbPrepare(dbt, sql, &localErr, ^(sqlite3_stmt *stmt) { + ok &= SecDbStep(dbt, stmt, &localErr, NULL); + }); + + if (!ok || localErr) { + secerror("Failed to delete corrupt item, %@ row %lli: %@", tablename, rowid, localErr); + } else { + secnotice("item", "Deleted corrupt rowid %lli from table %@", rowid, tablename); + } + CFReleaseNull(localErr); + CFReleaseNull(sql); + return true; + }); + + CFRelease(tablename); // can't be a CFReleaseNull() because of scope + CFRelease(db); + }); + +} + + + /**************************************************************************** **************** Beginning of Externally Callable Interface **************** ****************************************************************************/ @@ -1552,7 +1623,7 @@ static bool SecEntitlementError(CFErrorRef *error) { #if TARGET_OS_OSX #define SEC_ENTITLEMENT_WARNING CFSTR("com.apple.application-identifier nor com.apple.security.application-groups nor keychain-access-groups") -#elif TARGET_OS_IOSMAC +#elif TARGET_OS_MACCATALYST #define SEC_ENTITLEMENT_WARNING CFSTR("com.apple.developer.associated-application-identifier nor application-identifier nor com.apple.security.application-groups nor keychain-access-groups") #else #define SEC_ENTITLEMENT_WARNING CFSTR("application-identifier nor keychain-access-groups") @@ -1596,13 +1667,43 @@ static CFStringRef CopyAccessGroupForRowID(sqlite_int64 rowID, CFStringRef itemC } } -/* AUDIT[securityd](done): - query (ok) is a caller provided dictionary, only its cf type has been checked. - */ +// Expand this, rdar://problem/59297616 +// Known attributes which are not API/SPI should not be permitted in queries +static bool nonAPIAttributesInDictionary(CFDictionaryRef attrs) { + return CFDictionaryContainsKey(attrs, kSecAttrAppClipItem); +} + +static bool appClipHasSaneAccessGroups(SecurityClient* client) { + if (!client || !client->applicationIdentifier || !client->accessGroups) { + secerror("item: no app clip client or attributes not set, cannot verify restrictions"); + return false; + } + + CFIndex count = CFArrayGetCount(client->accessGroups); + if (count == 1 && CFEqualSafe(client->applicationIdentifier, CFArrayGetValueAtIndex(client->accessGroups, 0))) { + return true; + } + + // sigh, alright is the _other_ access group the application identifier? + if (count == 2) { + CFIndex tokenIdx = CFArrayGetFirstIndexOfValue(client->accessGroups, CFRangeMake(0, count), kSecAttrAccessGroupToken); + if (tokenIdx != kCFNotFound) { + return CFEqualSafe(client->applicationIdentifier, CFArrayGetValueAtIndex(client->accessGroups, tokenIdx == 0 ? 1 : 0)); + } + } + + return false; +} + static bool SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, SecurityClient *client, CFErrorRef *error) { + if (nonAPIAttributesInDictionary(query)) { + SecError(errSecParam, error, CFSTR("Non-API attributes present in query")); + return false; + } + CFArrayRef accessGroups = CFRetainSafe(client->accessGroups); CFIndex ag_count; @@ -1635,7 +1736,7 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, } bool ok = false; - Query *q = query_create_with_limit(query, client->musr, 1, error); + Query *q = query_create_with_limit(query, client->musr, 1, client, error); if (q) { CFStringRef agrp = CFDictionaryGetValue(q->q_item, kSecAttrAccessGroup); if (agrp) { @@ -1649,18 +1750,6 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, query_destroy(q, NULL); return false; } - } else { -#if !TARGET_OS_OSX - if (accessGroups != NULL) { - // On iOS, drop 'com.apple.token' AG from allowed accessGroups, to avoid inserting token elements into - // unsuspecting application's keychain. If the application on iOS wants to access token items, it needs - // explicitly specify kSecAttrAccessGroup=kSecAttrAccessGroupToken in its query. - CFMutableArrayRef mutableGroups = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, accessGroups); - CFArrayRemoveAllValue(mutableGroups, kSecAttrAccessGroupToken); - CFReleaseNull(accessGroups); - accessGroups = mutableGroups; - } -#endif } #if TARGET_OS_IPHONE @@ -1679,9 +1768,9 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, #endif query_set_caller_access_groups(q, accessGroups); - - /* Sanity check the query. */ - if (q->q_system_keychain && !client->allowSystemKeychain) { + if (client->isAppClip && !appClipHasSaneAccessGroups(client)) { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to use access groups other than application identifier")); + } else if (q->q_system_keychain && !client->allowSystemKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); @@ -1703,8 +1792,9 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, }); } - if (!query_destroy(q, error)) + if (!query_destroy(q, error)) { ok = false; + } } CFReleaseNull(accessGroups); @@ -1751,14 +1841,14 @@ SecurityClientCopyWritableAccessGroups(SecurityClient *client) { } } - -/* AUDIT[securityd](done): - attributes (ok) is a caller provided dictionary, only its cf type has - been checked. - */ bool _SecItemAdd(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *result, CFErrorRef *error) { + if (nonAPIAttributesInDictionary(attributes)) { + SecError(errSecParam, error, CFSTR("Non-API attributes present")); + return false; + } + CFArrayRef accessGroups = SecurityClientCopyWritableAccessGroups(client); bool ok = true; @@ -1770,20 +1860,22 @@ _SecItemAdd(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *resul SecSignpostStart(SecSignpostSecItemAdd); - Query *q = query_create_with_limit(attributes, client->musr, 0, error); + Query *q = query_create_with_limit(attributes, client->musr, 0, client, error); if (q) { /* Access group sanity checking. */ CFStringRef agrp = (CFStringRef)CFDictionaryGetValue(attributes, kSecAttrAccessGroup); /* Having the special accessGroup "*" allows access to all accessGroups. */ - if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) + if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) { CFReleaseNull(accessGroups); + } if (agrp) { /* The user specified an explicit access group, validate it. */ - if (!accessGroupsAllows(accessGroups, agrp, client)) + if (!accessGroupsAllows(accessGroups, agrp, client)) { ok = SecEntitlementErrorForExplicitAccessGroup(agrp, accessGroups, error); + } } else { agrp = (CFStringRef)CFArrayGetValueAtIndex(client->accessGroups, 0); @@ -1820,8 +1912,11 @@ _SecItemAdd(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *resul q->q_add_sync_callback = add_sync_callback; } #endif - - if (q->q_system_keychain && !client->allowSystemKeychain) { + if (client->isAppClip && !appClipHasSaneAccessGroups(client)) { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to use access groups other than application identifier")); + } else if (client->isAppClip && CFEqualSafe(CFDictionaryGetValue(attributes, kSecAttrSynchronizable), kCFBooleanTrue)) { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to add synchronizable items to the keychain")); + } else if (q->q_system_keychain && !client->allowSystemKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); @@ -1851,14 +1946,15 @@ _SecItemAdd(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *resul return ok; } -/* AUDIT[securityd](done): - query (ok) and attributesToUpdate (ok) are a caller provided dictionaries, - only their cf types have been checked. - */ bool _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, SecurityClient *client, CFErrorRef *error) { + if (nonAPIAttributesInDictionary(query) || nonAPIAttributesInDictionary(attributesToUpdate)) { + SecError(errSecParam, error, CFSTR("Non-API attributes present")); + return false; + } + CFArrayRef accessGroups = SecurityClientCopyWritableAccessGroups(client); CFIndex ag_count; @@ -1893,7 +1989,7 @@ _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, } bool ok = true; - Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, error); + Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, client, error); if (!q) { ok = false; } @@ -1906,10 +2002,14 @@ _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, q->q_system_keychain = false; } #endif - - /* Sanity check the query. */ query_set_caller_access_groups(q, accessGroups); - if (q->q_system_keychain && !client->allowSystemKeychain) { + if (client->isAppClip && !appClipHasSaneAccessGroups(client)) { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to use access groups other than application identifier")); + } else if (client->isAppClip && (CFEqualSafe(CFDictionaryGetValue(query, kSecAttrSynchronizable), kCFBooleanTrue) || + CFEqualSafe(CFDictionaryGetValue(attributesToUpdate, kSecAttrSynchronizable), kCFBooleanTrue))) + { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to make items synchronizable")); + } else if (q->q_system_keychain && !client->allowSystemKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); @@ -1959,13 +2059,14 @@ _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, return ok; } - -/* AUDIT[securityd](done): - query (ok) is a caller provided dictionary, only its cf type has been checked. - */ bool _SecItemDelete(CFDictionaryRef query, SecurityClient *client, CFErrorRef *error) { + if (nonAPIAttributesInDictionary(query)) { + SecError(errSecParam, error, CFSTR("Non-API attributes present")); + return false; + } + CFArrayRef accessGroups = SecurityClientCopyWritableAccessGroups(client); CFIndex ag_count; @@ -1997,7 +2098,7 @@ _SecItemDelete(CFDictionaryRef query, SecurityClient *client, CFErrorRef *error) CFReleaseNull(accessGroups); } - Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, error); + Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, client, error); bool ok; if (q) { #if TARGET_OS_IPHONE @@ -2010,8 +2111,9 @@ _SecItemDelete(CFDictionaryRef query, SecurityClient *client, CFErrorRef *error) #endif query_set_caller_access_groups(q, accessGroups); - /* Sanity check the query. */ - if (q->q_system_keychain && !client->allowSystemKeychain) { + if (client->isAppClip && !appClipHasSaneAccessGroups(client)) { + ok = SecError(errSecRestrictedAPI, error, CFSTR("App clips are not permitted to use access groups other than application identifier")); + } else if (q->q_system_keychain && !client->allowSystemKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); @@ -2044,11 +2146,8 @@ _SecItemDelete(CFDictionaryRef query, SecurityClient *client, CFErrorRef *error) } static bool SecItemDeleteTokenItems(SecDbConnectionRef dbt, CFTypeRef classToDelete, CFTypeRef tokenID, CFArrayRef accessGroups, SecurityClient *client, CFErrorRef *error) { - CFTypeRef keys[] = { kSecClass, kSecAttrTokenID }; - CFTypeRef values[] = { classToDelete, tokenID }; - - CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, error); + CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecClass, classToDelete, kSecAttrTokenID, tokenID, NULL); + Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, client, error); CFRelease(query); bool ok; if (q) { @@ -2062,73 +2161,55 @@ static bool SecItemDeleteTokenItems(SecDbConnectionRef dbt, CFTypeRef classToDel return ok; } -static bool SecItemAddTokenItem(SecDbConnectionRef dbt, CFDictionaryRef attributes, CFArrayRef accessGroups, SecurityClient *client, CFErrorRef *error) { - bool ok = true; - Query *q = query_create_with_limit(attributes, client->musr, 0, error); - if (q) { - CFStringRef agrp = kSecAttrAccessGroupToken; +static bool SecItemAddTokenItemToAccessGroups(SecDbConnectionRef dbt, CFDictionaryRef attributes, CFArrayRef accessGroups, SecurityClient *client, CFErrorRef *error) { + Query *q; + bool ok = false; + for (CFIndex i = 0; i < CFArrayGetCount(accessGroups); ++i) { + require_quiet(q = query_create_with_limit(attributes, client->musr, 0, client, error), out); + CFStringRef agrp = CFArrayGetValueAtIndex(accessGroups, i); query_add_attribute(kSecAttrAccessGroup, agrp, q); - - if (ok) { - query_ensure_access_control(q, agrp); - if (q->q_system_keychain && !client->allowSystemKeychain) { - ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); - } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { - ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); - } else if (q->q_row_id || q->q_token_object_id) { - ok = SecError(errSecValuePersistentRefUnsupported, error, CFSTR("q_row_id")); // TODO: better error string - } else if (!q->q_error) { - query_pre_add(q, true); - ok = s3dl_query_add(dbt, q, NULL, error); - } + query_ensure_access_control(q, agrp); + bool added = false; + if (!q->q_error) { + query_pre_add(q, true); + added = s3dl_query_add(dbt, q, NULL, error); } - ok = query_notify_and_destroy(q, ok, error); - } else { - return false; + require_quiet(query_notify_and_destroy(q, added, error), out); } + ok = true; +out: return ok; } -bool _SecItemUpdateTokenItems(CFStringRef tokenID, CFArrayRef items, SecurityClient *client, CFErrorRef *error) { - bool ok = true; - CFArrayRef accessGroups = client->accessGroups; - CFIndex ag_count; - if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { - return SecEntitlementError(error); +bool _SecItemUpdateTokenItemsForAccessGroups(CFStringRef tokenID, CFArrayRef accessGroups, CFArrayRef items, SecurityClient *client, CFErrorRef *error) { + // This is SPI for CTK only, don't even listen to app clips. + if (client->isAppClip) { + return SecError(errSecRestrictedAPI, error, CFSTR("App Clips may not call this API")); } - ok = kc_with_dbt(true, error, ^bool (SecDbConnectionRef dbt) { + return kc_with_dbt(true, error, ^bool (SecDbConnectionRef dbt) { return kc_transaction(dbt, error, ^bool { - if (items) { - const CFTypeRef classToDelete[] = { kSecClassGenericPassword, kSecClassInternetPassword, kSecClassCertificate, kSecClassKey }; - for (size_t i = 0; i < sizeof(classToDelete) / sizeof(classToDelete[0]); ++i) { - SecItemDeleteTokenItems(dbt, classToDelete[i], tokenID, accessGroups, client, NULL); + bool ok = false; + CFErrorRef localError = NULL; + const CFTypeRef classToDelete[] = { kSecClassGenericPassword, kSecClassInternetPassword, kSecClassCertificate, kSecClassKey }; + for (size_t i = 0; i < sizeof(classToDelete) / sizeof(classToDelete[0]); ++i) { + if (!SecItemDeleteTokenItems(dbt, classToDelete[i], tokenID, accessGroups, client, &localError)) { + require_action_quiet(CFErrorGetCode(localError) == errSecItemNotFound, out, CFErrorPropagate(localError, error)); + CFReleaseNull(localError); } + } + if (items) { for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) { - if (!SecItemAddTokenItem(dbt, CFArrayGetValueAtIndex(items, i), accessGroups, client, error)) - return false; + require_quiet(SecItemAddTokenItemToAccessGroups(dbt, CFArrayGetValueAtIndex(items, i), accessGroups, client, error), out); } - return true; - } - else { - const CFTypeRef classToDelete[] = { kSecClassGenericPassword, kSecClassInternetPassword, kSecClassCertificate, kSecClassKey }; - bool deleted = true; - for (size_t i = 0; i < sizeof(classToDelete) / sizeof(classToDelete[0]); ++i) { - if (!SecItemDeleteTokenItems(dbt, classToDelete[i], tokenID, accessGroups, client, error) && error && CFErrorGetCode(*error) != errSecItemNotFound) { - deleted = false; - break; - } - else if (error && *error) { - CFReleaseNull(*error); - } - } - return deleted; } + + ok = true; + out: + return ok; }); }); - - return ok; } static bool deleteNonSysboundItemsForItemClass(SecDbConnectionRef dbt, SecDbClass const* class, CFErrorRef* error) { @@ -2136,7 +2217,7 @@ static bool deleteNonSysboundItemsForItemClass(SecDbConnectionRef dbt, SecDbClas CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitAll); __block CFErrorRef localError = NULL; - SecDbQueryRef q = query_create(class, NULL, query, &localError); + SecDbQueryRef q = query_create(class, NULL, query, NULL, &localError); if (q == NULL) { // illegal query or out of memory secerror("SecItemServerDeleteAll: aborting because failed to initialize Query: %@", localError); abort(); @@ -2148,7 +2229,7 @@ static bool deleteNonSysboundItemsForItemClass(SecDbConnectionRef dbt, SecDbClas if (!SecItemIsSystemBound(item->attributes, class, false) && !CFEqual(CFDictionaryGetValue(item->attributes, kSecAttrAccessGroup), CFSTR("com.apple.bluetooth"))) { - SecDbItemDelete(item, dbt, kCFBooleanFalse, &localError); + SecDbItemDelete(item, dbt, kCFBooleanFalse, false, &localError); } }); query_destroy(q, &localError); @@ -2260,7 +2341,7 @@ _SecItemServerDeleteAllWithAccessGroups(CFArrayRef accessGroups, SecurityClient for (n = 0; n < sizeof(qclasses)/sizeof(qclasses[0]) && ok1; n++) { Query *q; - q = query_create(qclasses[n], client->musr, NULL, error); + q = query_create(qclasses[n], client->musr, NULL, client, error); require(q, fail2); (void)s3dl_query_delete(dbt, q, accessGroups, &localError); @@ -2282,82 +2363,15 @@ fail: #if SHAREDWEBCREDENTIALS +// OSX now has SWC enabled, but cannot link SharedWebCredentials framework: rdar://59958701 +#if TARGET_OS_IOS && !TARGET_OS_BRIDGE && !TARGET_OS_WATCH && !TARGET_OS_TV + /* constants */ #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v); SEC_CONST_DECL (kSecSafariAccessGroup, "com.apple.cfnetwork"); SEC_CONST_DECL (kSecSafariDefaultComment, "default"); SEC_CONST_DECL (kSecSafariPasswordsNotSaved, "Passwords not saved"); -SEC_CONST_DECL (kSecSharedCredentialUrlScheme, "https://"); -SEC_CONST_DECL (kSecSharedWebCredentialsService, "webcredentials"); - -#if !TARGET_OS_SIMULATOR -static SWCFlags -_SecAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFErrorRef *error) -{ - __block SWCFlags flags = kSWCFlags_None; - OSStatus status; - - secnotice("swc", "Application %@ is requesting approval for %@", appID, fqdn); - - dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - if (semaphore == NULL) - return 0; - - status = SWCCheckService(kSecSharedWebCredentialsService, appID, fqdn, ^void (OSStatus inStatus, SWCFlags inFlags, CFDictionaryRef inDetails) - { - if (inStatus == 0) { - flags = inFlags; - } else { - secerror("SWCCheckService failed with %d", (int)inStatus); - } - dispatch_semaphore_signal(semaphore); - }); - - if (status == 0) { - dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); - } else { - secerror("SWCCheckService: failed to queue"); - } - dispatch_release(semaphore); - - if (error) { - if (!(flags & kSWCFlag_SiteApproved)) { - SecError(errSecAuthFailed, error, CFSTR("\"%@\" failed to approve \"%@\""), fqdn, appID); - } else if (flags & kSWCFlag_UserDenied) { - SecError(errSecAuthFailed, error, CFSTR("User denied access to \"%@\" by \"%@\""), fqdn, appID); - } - } - return flags; -} - -static bool -_SecEntitlementContainsDomainForService(CFArrayRef domains, CFStringRef domain, CFStringRef service) -{ - bool result = false; - CFIndex idx, count = (domains) ? CFArrayGetCount(domains) : (CFIndex) 0; - if (!count || !domain || !service) { - return result; - } - for (idx=0; idx < count; idx++) { - CFStringRef str = (CFStringRef) CFArrayGetValueAtIndex(domains, idx); - if (str && CFStringHasPrefix(str, kSecSharedWebCredentialsService)) { - CFIndex prefix_len = CFStringGetLength(kSecSharedWebCredentialsService)+1; - CFIndex substr_len = CFStringGetLength(str) - prefix_len; - CFRange range = { prefix_len, substr_len }; - CFStringRef substr = CFStringCreateWithSubstring(kCFAllocatorDefault, str, range); - if (substr && CFEqual(substr, domain)) { - result = true; - } - CFReleaseSafe(substr); - if (result) { - break; - } - } - } - return result; -} -#endif /* !TARGET_OS_SIMULATOR */ static bool _SecAddNegativeWebCredential(SecurityClient *client, CFStringRef fqdn, CFStringRef appID, bool forSafari) @@ -2367,21 +2381,7 @@ _SecAddNegativeWebCredential(SecurityClient *client, CFStringRef fqdn, CFStringR if (!fqdn) { return result; } // update our database - CFRetainSafe(appID); - CFRetainSafe(fqdn); - if (0 == SWCSetServiceFlags(kSecSharedWebCredentialsService, appID, fqdn, kSWCFlag_ExternalMask, kSWCFlag_UserDenied, - ^void(OSStatus inStatus, SWCFlags inNewFlags){ - CFReleaseSafe(appID); - CFReleaseSafe(fqdn); - })) - { - result = true; - } - else // didn't queue the block - { - CFReleaseSafe(appID); - CFReleaseSafe(fqdn); - } + _SecSetAppDomainApprovalStatus(appID, fqdn, kCFBooleanFalse); if (!forSafari) { return result; } @@ -2475,20 +2475,13 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, // parse fqdn with CFURL here, since it could be specified as domain:port if (fqdn) { - CFStringRef urlStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%@"), kSecSharedCredentialUrlScheme, fqdn); - if (urlStr) { - CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, urlStr, nil); - if (url) { - CFStringRef hostname = CFURLCopyHostName(url); - if (hostname) { - CFReleaseSafe(fqdn); - fqdn = hostname; - port = CFURLGetPortNumber(url); - } - CFReleaseSafe(url); - } - CFReleaseSafe(urlStr); - } + CFTypeRef fqdnObject = _SecCopyFQDNObjectFromString(fqdn); + if (fqdnObject) { + CFReleaseSafe(fqdn); + fqdn = _SecGetFQDNFromFQDNObject(fqdnObject, &port); + CFRetainSafe(fqdn); + CFReleaseSafe(fqdnObject); + } } if (!account) { @@ -2509,7 +2502,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, SecError(status, error, CFSTR("Missing application-identifier entitlement")); goto cleanup; } - if (_SecEntitlementContainsDomainForService(domains, fqdn, kSecSharedWebCredentialsService)) { + if (_SecEntitlementContainsDomainForService(domains, fqdn, port)) { status = errSecSuccess; } if (errSecSuccess != status) { @@ -2528,8 +2521,8 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, secerror("Ignoring app/site approval state in the Simulator."); #else // get approval status for this app/domain pair - SWCFlags flags = _SecAppDomainApprovalStatus(appID, fqdn, error); - if (!(flags & kSWCFlag_SiteApproved)) { + SecSWCFlags flags = _SecAppDomainApprovalStatus(appID, fqdn, error); + if (!(flags & kSecSWCFlag_SiteApproved)) { goto cleanup; } #endif @@ -2589,7 +2582,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, bool samePassword = result && *result && CFEqual(*result, credential); CFReleaseSafe(credential); CFDictionaryAddValue(attrs, kSecAttrComment, kSecSafariDefaultComment); - + ok = samePassword || swca_confirm_operation(swca_update_request_id, clientAuditToken, query, error, ^void (CFStringRef confirm_fqdn) { _SecAddNegativeWebCredential(client, confirm_fqdn, appID, false); @@ -2609,7 +2602,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, ok = _SecItemDelete(query, &swcclient, error); } } - + if(result) CFReleaseNull(*result); if(error) CFReleaseNull(*error); @@ -2679,9 +2672,7 @@ _SecCopySharedWebCredential(CFDictionaryRef query, CFMutableArrayRef credentials = NULL; CFMutableArrayRef foundItems = NULL; CFMutableArrayRef fqdns = NULL; - CFStringRef fqdn = NULL; CFStringRef account = NULL; - SInt32 port = -1; bool ok = false; require_quiet(result, cleanup); @@ -2701,7 +2692,6 @@ _SecCopySharedWebCredential(CFDictionaryRef query, }; // On input, the query dictionary contains optional fqdn and account entries. - fqdn = CFDictionaryGetValue(query, kSecAttrServer); account = CFDictionaryGetValue(query, kSecAttrAccount); // Check autofill enabled status @@ -2711,28 +2701,30 @@ _SecCopySharedWebCredential(CFDictionaryRef query, } // Check fqdn; if NULL, add domains from caller's entitlement. - if (fqdn) { - CFArrayAppendValue(fqdns, fqdn); - } - else if (domains) { - CFIndex idx, count = CFArrayGetCount(domains); - for (idx=0; idx < count; idx++) { - CFStringRef str = (CFStringRef) CFArrayGetValueAtIndex(domains, idx); - // Parse the entry for our service label prefix - if (str && CFStringHasPrefix(str, kSecSharedWebCredentialsService)) { - CFIndex prefix_len = CFStringGetLength(kSecSharedWebCredentialsService)+1; - CFIndex substr_len = CFStringGetLength(str) - prefix_len; - CFRange range = { prefix_len, substr_len }; - fqdn = CFStringCreateWithSubstring(kCFAllocatorDefault, str, range); - if (fqdn) { - CFArrayAppendValue(fqdns, fqdn); - CFRelease(fqdn); + { + CFStringRef fqdn = CFDictionaryGetValue(query, kSecAttrServer); + if (fqdn) { + CFTypeRef fqdnObject = _SecCopyFQDNObjectFromString(fqdn); + if (fqdnObject) { + CFArrayAppendValue(fqdns, fqdnObject); + CFReleaseSafe(fqdnObject); + } + } + else if (domains) { + CFIndex idx, count = CFArrayGetCount(domains); + for (idx=0; idx < count; idx++) { + CFStringRef str = (CFStringRef) CFArrayGetValueAtIndex(domains, idx); + // Parse the entry for our service label prefix + CFTypeRef fqdnObject = _SecCopyFQDNObjectFromString(str); + if (fqdnObject) { + CFArrayAppendValue(fqdns, fqdnObject); + CFReleaseSafe(fqdnObject); } } } } CFIndex count, idx; - + count = CFArrayGetCount(fqdns); if (count < 1) { SecError(errSecParam, error, CFSTR("No domain provided")); @@ -2743,27 +2735,10 @@ _SecCopySharedWebCredential(CFDictionaryRef query, for (idx = 0; idx < count; idx++) { CFMutableArrayRef items = NULL; CFMutableDictionaryRef attrs = NULL; - fqdn = (CFStringRef) CFArrayGetValueAtIndex(fqdns, idx); - CFRetainSafe(fqdn); - port = -1; - // Parse the fqdn for a possible port specifier. - if (fqdn) { - CFStringRef urlStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%@"), kSecSharedCredentialUrlScheme, fqdn); - if (urlStr) { - CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, urlStr, nil); - if (url) { - CFStringRef hostname = CFURLCopyHostName(url); - if (hostname) { - CFReleaseSafe(fqdn); - fqdn = hostname; - port = CFURLGetPortNumber(url); - } - CFReleaseSafe(url); - } - CFReleaseSafe(urlStr); - } - } + CFTypeRef fqdnObject = CFArrayGetValueAtIndex(fqdns, idx); + SInt32 port = -1; + CFStringRef fqdn = _SecGetFQDNFromFQDNObject(fqdnObject, &port); #if TARGET_OS_SIMULATOR secerror("app/site association entitlements not checked in Simulator"); @@ -2771,11 +2746,10 @@ _SecCopySharedWebCredential(CFDictionaryRef query, OSStatus status = errSecMissingEntitlement; if (!appID) { SecError(status, error, CFSTR("Missing application-identifier entitlement")); - CFReleaseSafe(fqdn); goto cleanup; } // validate that fqdn is part of caller's entitlement - if (_SecEntitlementContainsDomainForService(domains, fqdn, kSecSharedWebCredentialsService)) { + if (_SecEntitlementContainsDomainForService(domains, fqdn, port)) { status = errSecSuccess; } if (errSecSuccess != status) { @@ -2786,7 +2760,6 @@ _SecCopySharedWebCredential(CFDictionaryRef query, } SecError(status, error, CFSTR("%@"), msg); CFReleaseSafe(msg); - CFReleaseSafe(fqdn); goto cleanup; } #endif @@ -2794,7 +2767,6 @@ _SecCopySharedWebCredential(CFDictionaryRef query, attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!attrs) { SecError(errSecAllocate, error, CFSTR("Unable to create query dictionary")); - CFReleaseSafe(fqdn); goto cleanup; } CFDictionaryAddValue(attrs, kSecClass, kSecClassInternetPassword); @@ -2827,12 +2799,12 @@ _SecCopySharedWebCredential(CFDictionaryRef query, bool approved = true; #else // get approval status for this app/domain pair - SWCFlags flags = _SecAppDomainApprovalStatus(appID, fqdn, error); + SecSWCFlags flags = _SecAppDomainApprovalStatus(appID, fqdn, error); if (count > 1) { // ignore interim error since we have multiple domains to check CFReleaseNull(*error); } - bool approved = (flags & kSWCFlag_SiteApproved); + bool approved = (flags & kSecSWCFlag_SiteApproved); #endif if (approved) { CFArrayAppendArray(foundItems, items, CFRangeMake(0, CFArrayGetCount(items))); @@ -2840,7 +2812,6 @@ _SecCopySharedWebCredential(CFDictionaryRef query, } CFReleaseSafe(items); CFReleaseSafe(attrs); - CFReleaseSafe(fqdn); } // If matching credentials are found, the credentials provided to the completionHandler @@ -2946,29 +2917,13 @@ _SecCopySharedWebCredential(CFDictionaryRef query, CFArrayRemoveAllValues(credentials); if (selected && ok) { #if TARGET_OS_IOS && !TARGET_OS_BRIDGE && !TARGET_OS_SIMULATOR - fqdn = CFDictionaryGetValue(selected, kSecAttrServer); + // register confirmation with database + CFStringRef fqdn = CFDictionaryGetValue(selected, kSecAttrServer); + _SecSetAppDomainApprovalStatus(appID, fqdn, kCFBooleanTrue); #endif CFArrayAppendValue(credentials, selected); } - if (ok) { -#if TARGET_OS_IOS && !TARGET_OS_BRIDGE && !TARGET_OS_SIMULATOR - // register confirmation with database - CFRetainSafe(appID); - CFRetainSafe(fqdn); - if (0 != SWCSetServiceFlags(kSecSharedWebCredentialsService, - appID, fqdn, kSWCFlag_ExternalMask, kSWCFlag_UserApproved, - ^void(OSStatus inStatus, SWCFlags inNewFlags){ - CFReleaseSafe(appID); - CFReleaseSafe(fqdn); - })) - { - // we didn't queue the block - CFReleaseSafe(appID); - CFReleaseSafe(fqdn); - } -#endif - } CFReleaseSafe(selected); } else if (NULL == *error) { @@ -2989,6 +2944,23 @@ cleanup: return ok; } +#else /* !(TARGET_OS_IOS && !TARGET_OS_BRIDGE && !TARGET_OS_WATCH && !TARGET_OS_TV) */ + +bool _SecAddSharedWebCredential(CFDictionaryRef attributes, SecurityClient *client, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef domains, CFTypeRef *result, CFErrorRef *error) { + if (error) { + SecError(errSecUnimplemented, error, CFSTR("_SecAddSharedWebCredential not supported on this platform")); + } + return false; +} + +bool _SecCopySharedWebCredential(CFDictionaryRef query, SecurityClient *client, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef domains, CFTypeRef *result, CFErrorRef *error) { + if (error) { + SecError(errSecUnimplemented, error, CFSTR("_SecCopySharedWebCredential not supported on this platform")); + } + return false; +} + +#endif /* !(TARGET_OS_IOS && !TARGET_OS_BRIDGE && !TARGET_OS_WATCH && !TARGET_OS_TV) */ #endif /* SHAREDWEBCREDENTIALS */ @@ -3269,6 +3241,13 @@ _SecServerRestoreSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef pa errOut: return ok; } + +#else /* SECUREOBJECTSYNC */ + +SOSDataSourceFactoryRef SecItemDataSourceFactoryGetDefault(void) { + return NULL; +} + #endif /* SECUREOBJECTSYNC */ bool _SecServerRollKeysGlue(bool force, CFErrorRef *error) { @@ -3308,7 +3287,7 @@ InitialSyncItems(CFMutableArrayRef items, bool limitToCurrent, CFStringRef agrp, bool result = false; Query *q = NULL; - q = query_create(qclass, NULL, NULL, error); + q = query_create(qclass, NULL, NULL, NULL, error); require(q, fail); q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; @@ -3452,7 +3431,7 @@ _SecServerImportInitialSyncCredentials(CFArrayRef array, CFErrorRef *error) continue; } - if (!SecDbItemInsert(dbi, dbt, &cferror)) { + if (!SecDbItemInsert(dbi, dbt, false, &cferror)) { secinfo("ImportInitialSyncItems", "Item store failed with: %@: %@", cferror, dbi); CFReleaseNull(cferror); } @@ -3506,7 +3485,7 @@ TransmogrifyItemsToSyncBubble(SecurityClient *client, uid_t uid, secnotice("syncbubble", "cleaning out old items"); - q = query_create(qclass, NULL, NULL, error); + q = query_create(qclass, NULL, NULL, client, error); require(q, fail); q->q_limit = kSecMatchUnlimited; @@ -3538,7 +3517,7 @@ TransmogrifyItemsToSyncBubble(SecurityClient *client, uid_t uid, secnotice("syncbubble", "migrating sync bubble items"); - q = query_create(qclass, NULL, NULL, error); + q = query_create(qclass, NULL, NULL, client, error); require(q, fail); q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; @@ -3578,7 +3557,7 @@ TransmogrifyItemsToSyncBubble(SecurityClient *client, uid_t uid, return; } - if (!SecDbItemInsert(new_item, dbt, &error3)) { + if (!SecDbItemInsert(new_item, dbt, false, &error3)) { secnotice("syncbubble", "migration failed with %@ for item %@", error3, new_item); } CFRelease(new_item); @@ -3820,7 +3799,7 @@ _SecServerTransmogrifyToSystemKeychain(SecurityClient *client, CFErrorRef *error continue; } - q = query_create(*kcClass, SecMUSRGetSingleUserKeychainUUID(), NULL, error); + q = query_create(*kcClass, SecMUSRGetSingleUserKeychainUUID(), NULL, client, error); if (q == NULL) continue; diff --git a/keychain/securityd/SecItemServer.h b/keychain/securityd/SecItemServer.h index 0c163778..b8f82e3a 100644 --- a/keychain/securityd/SecItemServer.h +++ b/keychain/securityd/SecItemServer.h @@ -56,7 +56,7 @@ CFStringRef _SecServerBackupCopyUUID(CFDataRef backup, CFErrorRef *error); bool _SecServerBackupKeybagAdd(SecurityClient *client, CFDataRef passcode, CFDataRef *identifier, CFDataRef *pathinfo, CFErrorRef *error); bool _SecServerBackupKeybagDelete(CFDictionaryRef attributes, bool deleteAll, CFErrorRef *error); -bool _SecItemUpdateTokenItems(CFStringRef tokenID, CFArrayRef items, SecurityClient *client, CFErrorRef *error); +bool _SecItemUpdateTokenItemsForAccessGroups(CFStringRef tokenID, CFArrayRef accessGroups, CFArrayRef items, SecurityClient *client, CFErrorRef *error); CF_RETURNS_RETAINED CFArrayRef _SecServerKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *error); CF_RETURNS_RETAINED CFDictionaryRef _SecServerBackupSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error); @@ -71,10 +71,10 @@ bool _SecServerTransmogrifyToSyncBubble(CFArrayRef services, uid_t uid, Security bool _SecServerDeleteMUSERViews(SecurityClient *client, uid_t uid, CFErrorRef *error); #endif -#if TARGET_OS_IOS && !TARGET_OS_BRIDGE +#if SHAREDWEBCREDENTIALS bool _SecAddSharedWebCredential(CFDictionaryRef attributes, SecurityClient *client, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef domains, CFTypeRef *result, CFErrorRef *error); bool _SecCopySharedWebCredential(CFDictionaryRef query, SecurityClient *client, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef domains, CFTypeRef *result, CFErrorRef *error); -#endif /* TARGET_OS_IOS */ +#endif /* SHAREDWEBCREDENTIALS */ // Hack to log objects from inside SOS code void SecItemServerAppendItemDescription(CFMutableStringRef desc, CFDictionaryRef object); @@ -92,7 +92,6 @@ bool kc_with_custom_db(bool writeAndRead, bool usesItemTables, SecDbRef db, CFEr void SecKeychainDbForceClose(void); void SecKeychainDbReset(dispatch_block_t inbetween); - SOSDataSourceFactoryRef SecItemDataSourceFactoryGetDefault(void); /* FIXME: there is a specific type for keybag handle (keybag_handle_t) @@ -129,6 +128,8 @@ bool accessGroupsAllows(CFArrayRef accessGroups, CFStringRef accessGroup, Securi bool itemInAccessGroup(CFDictionaryRef item, CFArrayRef accessGroups); void SecKeychainChanged(void); +void deleteCorruptedItemAsync(SecDbConnectionRef dbt, CFStringRef tablename, sqlite_int64 rowid); + __END_DECLS #endif /* _SECURITYD_SECITEMSERVER_H_ */ diff --git a/keychain/securityd/SecKeybagSupport.c b/keychain/securityd/SecKeybagSupport.c index d526c73f..ee88f5d9 100644 --- a/keychain/securityd/SecKeybagSupport.c +++ b/keychain/securityd/SecKeybagSupport.c @@ -337,7 +337,7 @@ bool ks_decrypt_acl(aks_ref_key_t ref_key, CFDataRef encrypted_data, CFMutableDa aks_return, "decrypt")); CFPropertyListRef decoded_data = NULL; - der_decode_plist(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_data, NULL, der, der + der_len); + der_decode_plist(kCFAllocatorDefault, &decoded_data, NULL, der, der + der_len); require_action_quiet(decoded_data, out, SecError(errSecDecode, error, CFSTR("ks_crypt_acl: %x failed to '%s' item, Item can't be decrypted due to failed decode der, so drop the item."), aks_return, "decrypt")); if (CFGetTypeID(decoded_data) == CFDataGetTypeID()) { @@ -370,7 +370,7 @@ bool ks_delete_acl(aks_ref_key_t ref_key, CFDataRef encrypted_data, int aks_return = kAKSReturnSuccess; bool ok = false; - nrequire_action_quiet(CFEqual(SecAccessControlGetConstraint(access_control, kAKSKeyOpDelete), kCFBooleanTrue), out, ok = true); + nrequire_action_quiet(CFEqualSafe(SecAccessControlGetConstraint(access_control, kAKSKeyOpDelete), kCFBooleanTrue), out, ok = true); /* Verify that we have credential handle, otherwise generate proper error containing ACL and operation requested. */ if (!acm_context) { diff --git a/keychain/securityd/SecOTRRemote.m b/keychain/securityd/SecOTRRemote.m index cef0caf1..fcc4e564 100644 --- a/keychain/securityd/SecOTRRemote.m +++ b/keychain/securityd/SecOTRRemote.m @@ -64,7 +64,7 @@ CFDataRef SecOTRSessionCreateRemote_internal(CFDataRef publicAccountData, CFData privateKeyRef = SOSAccountCopyDeviceKey(privateAccount, error); require_quiet(privateKeyRef, fail); - privateIdentity = SecOTRFullIdentityCreateFromSecKeyRef(kCFAllocatorDefault, privateKeyRef, error); + privateIdentity = SecOTRFullIdentityCreateFromSecKeyRefSOS(kCFAllocatorDefault, privateKeyRef, error); require_quiet(privateIdentity, fail); CFReleaseNull(privateKeyRef); diff --git a/keychain/securityd/com.apple.secd.sb b/keychain/securityd/com.apple.secd.sb index 21f50f45..48c79e59 100644 --- a/keychain/securityd/com.apple.secd.sb +++ b/keychain/securityd/com.apple.secd.sb @@ -4,6 +4,9 @@ (import "system.sb") +(allow file-write-data + (literal "/dev/random")) + (allow file-read* file-write* (subpath "/private/var/db/mds") (regex #"^/private/var/folders/[^/]+/[^/]+/T(/|$)") diff --git a/keychain/securityd/entitlements.plist b/keychain/securityd/entitlements.plist index 02625012..05391bd2 100644 --- a/keychain/securityd/entitlements.plist +++ b/keychain/securityd/entitlements.plist @@ -2,6 +2,8 @@ + com.apple.private.cloudkit.notifyOnAccountWarmup + com.apple.private.dark-wake-push com.apple.private.accounts.allaccounts @@ -36,6 +38,8 @@ com.apple.private.cloudkit.supportservice + com.apple.private.cloudkit.spi + com.apple.private.appleaccount.app-hidden-from-icloud-settings com.apple.private.tcc.allow @@ -92,5 +96,7 @@ com.apple.symptom_diagnostics.report + com.apple.private.security.storage.Keychains + diff --git a/keychain/securityd/spi.c b/keychain/securityd/spi.c index 367f2274..f6a5745d 100644 --- a/keychain/securityd/spi.c +++ b/keychain/securityd/spi.c @@ -62,7 +62,7 @@ static struct securityd securityd_spi = { .sec_item_copy_parent_certificates = _SecItemCopyParentCertificates, .sec_item_certificate_exists = _SecItemCertificateExists, .sec_roll_keys = _SecServerRollKeysGlue, - .sec_item_update_token_items = _SecItemUpdateTokenItems, + .sec_item_update_token_items_for_access_groups = _SecItemUpdateTokenItemsForAccessGroups, .sec_delete_items_with_access_groups = _SecItemServerDeleteAllWithAccessGroups, #if SHAREDWEBCREDENTIALS .sec_add_shared_web_credential = _SecAddSharedWebCredential, @@ -72,6 +72,7 @@ static struct securityd securityd_spi = { .sec_keychain_backup_syncable = _SecServerBackupSyncable, .sec_keychain_restore_syncable = _SecServerRestoreSyncable, .sec_item_backup_copy_names = SecServerItemBackupCopyNames, + .sec_item_backup_ensure_copy_view = SecServerItemBackupEnsureCopyView, .sec_item_backup_handoff_fd = SecServerItemBackupHandoffFD, .sec_item_backup_set_confirmed_manifest = SecServerItemBackupSetConfirmedManifest, .sec_item_backup_restore = SecServerItemBackupRestore, @@ -80,24 +81,18 @@ static struct securityd securityd_spi = { .soscc_TryUserCredentials = SOSCCTryUserCredentials_Server, .soscc_SetUserCredentials = SOSCCSetUserCredentials_Server, .soscc_SetUserCredentialsAndDSID = SOSCCSetUserCredentialsAndDSID_Server, - .soscc_SetUserCredentialsAndDSIDWithAnalytics = SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server, .soscc_CanAuthenticate = SOSCCCanAuthenticate_Server, .soscc_PurgeUserCredentials = SOSCCPurgeUserCredentials_Server, .soscc_ThisDeviceIsInCircle = SOSCCThisDeviceIsInCircle_Server, .soscc_RequestToJoinCircle = SOSCCRequestToJoinCircle_Server, .soscc_RequestToJoinCircleAfterRestore = SOSCCRequestToJoinCircleAfterRestore_Server, - .soscc_RequestToJoinCircleAfterRestoreWithAnalytics = SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server, .soscc_SetToNew = SOSCCAccountSetToNew_Server, .soscc_ResetToOffering = SOSCCResetToOffering_Server, .soscc_ResetToEmpty = SOSCCResetToEmpty_Server, - .soscc_ResetToEmptyWithAnalytics = SOSCCResetToEmptyWithAnalytics_Server, .soscc_View = SOSCCView_Server, .soscc_ViewSet = SOSCCViewSet_Server, - .soscc_ViewSetWithAnalytics = SOSCCViewSetWithAnalytics_Server, .soscc_RemoveThisDeviceFromCircle = SOSCCRemoveThisDeviceFromCircle_Server, - .soscc_RemoveThisDeviceFromCircleWithAnalytics = SOSCCRemoveThisDeviceFromCircleWithAnalytics_Server, .soscc_RemovePeersFromCircle = SOSCCRemovePeersFromCircle_Server, - .soscc_RemovePeersFromCircleWithAnalytics = SOSCCRemovePeersFromCircleWithAnalytics_Server, .soscc_LoggedOutOfAccount = SOSCCLoggedOutOfAccount_Server, .soscc_BailFromCircle = SOSCCBailFromCircle_Server, .soscc_AcceptApplicants = SOSCCAcceptApplicants_Server, @@ -124,7 +119,6 @@ static struct securityd securityd_spi = { .soscc_SetNewPublicBackupKey = SOSCCSetNewPublicBackupKey_Server, .soscc_RegisterSingleRecoverySecret = SOSCCRegisterSingleRecoverySecret_Server, .soscc_WaitForInitialSync = SOSCCWaitForInitialSync_Server, - .soscc_WaitForInitialSyncWithAnalytics = SOSCCWaitForInitialSyncWithAnalytics_Server, .soscc_AccountHasPublicKey = SOSCCAccountHasPublicKey_Server, .soscc_SOSCCPeersHaveViewsEnabled = SOSCCPeersHaveViewsEnabled_Server, .soscc_RegisterRecoveryPublicKey = SOSCCRegisterRecoveryPublicKey_Server, diff --git a/keychain/tpctl/main.swift b/keychain/tpctl/main.swift index 5ba4a914..6f6e8833 100644 --- a/keychain/tpctl/main.swift +++ b/keychain/tpctl/main.swift @@ -1,7 +1,7 @@ import Foundation import os -let tplogDebug = OSLog(subsystem: "com.apple.security.trustedpeers", category: "debug") +let logger = Logger(subsystem: "com.apple.security.trustedpeers", category: "tpctl") // This should definitely use the ArgumentParser library from the Utility package. // However, right now that's not accessible from this code due to build system issues. @@ -223,7 +223,7 @@ while let arg = argIterator.next() { print("Error: --policy-secret data must be base-64") exitUsage(1) } - if nil == policySecrets { + if policySecrets == nil { policySecrets = [:] } policySecrets![name] = data @@ -270,7 +270,6 @@ while let arg = argIterator.next() { } voucher = voucherData voucherSig = voucherSigData - } else { guard let voucherBase64 = argIterator.next() else { print("Error: join needs a voucher") @@ -360,9 +359,7 @@ while let arg = argIterator.next() { permanentInfoSig = permanentInfoSigData stableInfo = stableInfoData stableInfoSig = stableInfoSigData - } else { - guard let peerIDString = argIterator.next() else { print("Error: vouch needs a peerID") print() @@ -488,14 +485,16 @@ func cleanDictionaryForJSON(_ d: [AnyHashable: Any]) -> [AnyHashable: Any] { // Bring up a connection to TrustedPeersHelper let connection = NSXPCConnection(serviceName: "com.apple.TrustedPeersHelper") + connection.remoteObjectInterface = TrustedPeersHelperSetupProtocol(NSXPCInterface(with: TrustedPeersHelperProtocol.self)) connection.resume() + let tpHelper = connection.synchronousRemoteObjectProxyWithErrorHandler { error in print("Unable to connect to TPHelper:", error) } as! TrustedPeersHelperProtocol for command in commands { switch command { case .dump: - os_log("dumping (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("dumping (\(container), \(context))") tpHelper.dump(withContainer: container, context: context) { reply, error in guard error == nil else { print("Error dumping:", error!) @@ -514,7 +513,7 @@ for command in commands { } case .depart: - os_log("departing (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("departing (\(container), \(context))") tpHelper.departByDistrustingSelf(withContainer: container, context: context) { error in guard error == nil else { print("Error departing:", error!) @@ -525,7 +524,7 @@ for command in commands { } case .distrust(let peerIDs): - os_log("distrusting %@ for (%@, %@)", log: tplogDebug, type: .default, peerIDs, container, context) + logger.log("distrusting \(peerIDs.description) for (\(container), \(context))") tpHelper.distrustPeerIDs(withContainer: container, context: context, peerIDs: peerIDs) { error in guard error == nil else { print("Error distrusting:", error!) @@ -534,15 +533,15 @@ for command in commands { print("Distrust successful") } - case .join(let voucher, let voucherSig): - os_log("joining (%@, %@)", log: tplogDebug, type: .default, container, context) + case let .join(voucher, voucherSig): + logger.log("joining (\(container), \(context))") tpHelper.join(withContainer: container, context: context, voucherData: voucher, voucherSig: voucherSig, ckksKeys: [], tlkShares: [], - preapprovedKeys: preapprovedKeys ?? []) { peerID, _, _, _, error in + preapprovedKeys: preapprovedKeys ?? []) { peerID, _, _, error in guard error == nil else { print("Error joining:", error!) return @@ -551,12 +550,12 @@ for command in commands { } case .establish: - os_log("establishing (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("establishing (\(container), \(context))") tpHelper.establish(withContainer: container, context: context, ckksKeys: [], tlkShares: [], - preapprovedKeys: preapprovedKeys ?? []) { peerID, _, error in + preapprovedKeys: preapprovedKeys ?? []) { peerID, _, _, error in guard error == nil else { print("Error establishing:", error!) return @@ -565,7 +564,7 @@ for command in commands { } case .healthInquiry: - os_log("healthInquiry (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("healthInquiry (\(container), \(context))") tpHelper.pushHealthInquiry(withContainer: container, context: context) { error in guard error == nil else { print("Error healthInquiry: \(String(describing: error))") @@ -575,19 +574,19 @@ for command in commands { } case .localReset: - os_log("local-reset (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("local-reset (\(container), \(context))") tpHelper.localReset(withContainer: container, context: context) { error in guard error == nil else { print("Error resetting:", error!) return } - os_log("local-reset (%@, %@): successful", log: tplogDebug, type: .default, container, context) + logger.log("local-reset (\(container), \(context)): successful") print("Local reset successful") } case .supportApp: - os_log("supportApp (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("supportApp (\(container), \(context))") tpHelper.getSupportAppInfo(withContainer: container, context: context) { data, error in guard error == nil else { @@ -608,7 +607,7 @@ for command in commands { } case .prepare: - os_log("preparing (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("preparing (\(container), \(context))") if machineID == nil { let anisetteController = AKAnisetteProvisioningController() @@ -623,6 +622,12 @@ for command in commands { let deviceInfo = OTDeviceInformationActualAdapter() + serialNumber = serialNumber ?? deviceInfo.serialNumber() + guard let serialNumber = serialNumber else { + print("failed to get serial number") + abort() + } + tpHelper.prepare(withContainer: container, context: context, epoch: epoch, @@ -631,12 +636,13 @@ for command in commands { bottleID: UUID().uuidString, modelID: modelID ?? deviceInfo.modelID(), deviceName: deviceName ?? deviceInfo.deviceName(), - serialNumber: serialNumber ?? deviceInfo.serialNumber(), + serialNumber: serialNumber, osVersion: osVersion ?? deviceInfo.osVersion(), policyVersion: nil, policySecrets: policySecrets, + syncUserControllableViews: .UNKNOWN, signingPrivKeyPersistentRef: nil, - encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, views, _, error in + encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, syncingPolicy, error in guard error == nil else { print("Error preparing:", error!) return @@ -649,7 +655,7 @@ for command in commands { "stableInfo": stableInfo!.base64EncodedString(), "stableInfoSig": stableInfoSig!.base64EncodedString(), "machineID": machineID!, - "views": Array(views ?? Set()), + "views": Array(syncingPolicy?.viewList ?? Set()), ] as [String: Any] do { print(try TPCTLObjectiveC.jsonSerialize(cleanDictionaryForJSON(result))) @@ -659,14 +665,15 @@ for command in commands { } case .update: - os_log("updating (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("updating (\(container), \(context))") tpHelper.update(withContainer: container, context: context, deviceName: deviceName, serialNumber: serialNumber, osVersion: osVersion, policyVersion: nil, - policySecrets: policySecrets) { _, error in + policySecrets: policySecrets, + syncUserControllableViews: nil) { _, _, error in guard error == nil else { print("Error updating:", error!) return @@ -676,7 +683,7 @@ for command in commands { } case .reset: - os_log("resetting (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("resetting (\(container), \(context))") tpHelper.reset(withContainer: container, context: context, resetReason: .userInitiatedReset) { error in guard error == nil else { print("Error during reset:", error!) @@ -687,7 +694,7 @@ for command in commands { } case .validate: - os_log("validate (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("validate (\(container), \(context))") tpHelper.validatePeers(withContainer: container, context: context) { reply, error in guard error == nil else { print("Error validating:", error!) @@ -706,7 +713,7 @@ for command in commands { } case .viableBottles: - os_log("viableBottles (%@, %@)", log: tplogDebug, type: .default, container, context) + logger.log("viableBottles (\(container), \(context))") tpHelper.fetchViableBottles(withContainer: container, context: context) { sortedBottleIDs, partialBottleIDs, error in guard error == nil else { print("Error fetching viable bottles:", error!) @@ -722,8 +729,8 @@ for command in commands { } } - case .vouch(let peerID, let permanentInfo, let permanentInfoSig, let stableInfo, let stableInfoSig): - os_log("vouching (%@, %@)", log: tplogDebug, type: .default, container, context) + case let .vouch(peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig): + logger.log("vouching (\(container), \(context))") tpHelper.vouch(withContainer: container, context: context, peerID: peerID, @@ -746,8 +753,8 @@ for command in commands { } } - case .vouchWithBottle(let bottleID, let entropy, let salt): - os_log("vouching with bottle (%@, %@)", log: tplogDebug, type: .default, container, context) + case let .vouchWithBottle(bottleID, entropy, salt): + logger.log("vouching with bottle (\(container), \(context))") tpHelper.vouchWithBottle(withContainer: container, context: context, bottleID: bottleID, @@ -766,8 +773,8 @@ for command in commands { } } - case .allow(let machineIDs, let performIDMS): - os_log("allow-listing (%@, %@)", log: tplogDebug, type: .default, container, context) + case let .allow(machineIDs, performIDMS): + logger.log("allow-listing (\(container), \(context))") var idmsDeviceIDs: Set = Set() var accountIsDemo: Bool = false diff --git a/libsecurity_smime/Security b/libsecurity_smime/Security deleted file mode 120000 index 945c9b46..00000000 --- a/libsecurity_smime/Security +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/libsecurity_smime/lib/CMSDecoder.c b/libsecurity_smime/lib/CMSDecoder.c index 8ac1228c..513932d2 100644 --- a/libsecurity_smime/lib/CMSDecoder.c +++ b/libsecurity_smime/lib/CMSDecoder.c @@ -223,7 +223,6 @@ OSStatus CMSDecoderUpdateMessage( case DS_Init: /* First time through; set up */ ASSERT(cmsDecoder->decoder == NULL); - ASSERT(cmsDecoder->arena == NULL); ortn = SecCmsDecoderCreate(NULL, NULL, NULL, NULL, NULL, NULL, &cmsDecoder->decoder); if(ortn) { ortn = cmsRtnToOSStatus(ortn); diff --git a/libsecurity_smime/lib/CMSEncoder.c b/libsecurity_smime/lib/CMSEncoder.c index 8fc6d1d9..1cc87e39 100644 --- a/libsecurity_smime/lib/CMSEncoder.c +++ b/libsecurity_smime/lib/CMSEncoder.c @@ -363,7 +363,7 @@ static OSStatus cmsSetupEncoder( { OSStatus ortn; - ASSERT(cmsEncoder->arena == NULL); + ASSERT(cmsEncoder->cmsMsg != NULL); ASSERT(cmsEncoder->encoder == NULL); cmsEncoder->encoderOut = CFDataCreateMutable(NULL, 0); diff --git a/libsecurity_smime/lib/CMSUtils.h b/libsecurity_smime/lib/CMSUtils.h index 25d5d8fd..bb34dd3c 100644 --- a/libsecurity_smime/lib/CMSUtils.h +++ b/libsecurity_smime/lib/CMSUtils.h @@ -30,7 +30,6 @@ #include #include -#include __BEGIN_DECLS @@ -62,13 +61,14 @@ OSStatus cmsRtnToOSStatusDefault(OSStatus smimeRtn, OSStatus defaultRtn); #define CFRELEASE(cfr) if(cfr != NULL) { CFRelease(cfr); } +#include +#define ASSERT(s) assert(s) + #define CMS_DEBUG 0 #if CMS_DEBUG -#define ASSERT(s) assert(s) #define CSSM_PERROR(s, r) cssmPerror(s, r) #define dprintf(args...) printf(args) #else -#define ASSERT(s) #define CSSM_PERROR(s, r) #define dprintf(args...) #endif diff --git a/libsecurity_smime/lib/cmsdigest.c b/libsecurity_smime/lib/cmsdigest.c index 9968af80..b511e686 100644 --- a/libsecurity_smime/lib/cmsdigest.c +++ b/libsecurity_smime/lib/cmsdigest.c @@ -34,7 +34,7 @@ /* * CMS digesting. */ -#include +#include #include "cmslocal.h" diff --git a/libsecurity_smime/lib/cmssiginfo.c b/libsecurity_smime/lib/cmssiginfo.c index c0d70ea9..2edf9680 100644 --- a/libsecurity_smime/lib/cmssiginfo.c +++ b/libsecurity_smime/lib/cmssiginfo.c @@ -469,7 +469,8 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAs SECITEM_FreeItem(&signature, PR_FALSE); - if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), pubkAlgTag, + SECOidTag sigAlgTag = SecCmsUtilMakeSignatureAlgorithm(digestalgtag, pubkAlgTag); + if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), sigAlgTag, NULL) != SECSuccess) goto loser; @@ -1131,21 +1132,18 @@ SecCmsSignerInfoGetSignerEmailAddress(SecCmsSignerInfoRef sinfo) SecCertificateRef signercert; CFStringRef emailAddress = NULL; - if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) - return NULL; + if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) { + return NULL; + } -#if USE_CDSA_CRYPTO - SecCertificateGetEmailAddress(signercert, &emailAddress); -#else CFArrayRef names = SecCertificateCopyRFC822Names(signercert); if (names) { - if (CFArrayGetCount(names) > 0) + if (CFArrayGetCount(names) > 0) { emailAddress = (CFStringRef)CFArrayGetValueAtIndex(names, 0); - if (emailAddress) - CFRetain(emailAddress); + } + CFRetainSafe(emailAddress); CFRelease(names); } -#endif return emailAddress; } diff --git a/libsecurity_smime/lib/crypto-embedded.c b/libsecurity_smime/lib/crypto-embedded.c index c816df52..8e9a4b9b 100644 --- a/libsecurity_smime/lib/crypto-embedded.c +++ b/libsecurity_smime/lib/crypto-embedded.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -231,35 +232,40 @@ SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef ce void *mark; mark = PORT_ArenaMark(pl); - CFDataRef serial_data = NULL; CFDataRef issuer_data = SecCertificateCopyIssuerSequence(cert); - if (!issuer_data) + CFDataRef serial_data = SecCertificateCopySerialNumberData(cert, NULL); + if (!issuer_data || !serial_data) { goto loser; - serial_data = SecCertificateCopySerialNumberData(cert, NULL); - if (!serial_data) - goto loser; - - SecAsn1Item serialNumber = { CFDataGetLength(serial_data), - (uint8_t *)CFDataGetBytePtr(serial_data) }; - SecAsn1Item issuer = { CFDataGetLength(issuer_data), - (uint8_t *)CFDataGetBytePtr(issuer_data) }; - - /* Allocate the SecCmsIssuerAndSN struct. */ + } + + SecAsn1Item serialNumber = { + .Length = CFDataGetLength(serial_data), + .Data = (uint8_t *)CFDataGetBytePtr(serial_data) + }; + SecAsn1Item issuer = { + .Length = CFDataGetLength(issuer_data), + .Data = (uint8_t *)CFDataGetBytePtr(issuer_data) + }; + + /* Allocate the SecCmsIssuerAndSN struct. */ certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN)); - if (certIssuerAndSN == NULL) - goto loser; + if (certIssuerAndSN == NULL) { + goto loser; + } /* Copy the issuer. */ certIssuerAndSN->derIssuer.Data = (uint8_t *) PORT_ArenaAlloc(pl, issuer.Length); - if (!certIssuerAndSN->derIssuer.Data) - goto loser; + if (!certIssuerAndSN->derIssuer.Data) { + goto loser; + } PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer.Data, issuer.Length); certIssuerAndSN->derIssuer.Length = issuer.Length; /* Copy the serialNumber. */ certIssuerAndSN->serialNumber.Data = (uint8_t *) PORT_ArenaAlloc(pl, serialNumber.Length); - if (!certIssuerAndSN->serialNumber.Data) - goto loser; + if (!certIssuerAndSN->serialNumber.Data) { + goto loser; + } PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber.Data, serialNumber.Length); certIssuerAndSN->serialNumber.Length = serialNumber.Length; @@ -267,14 +273,12 @@ SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef ce CFRelease(issuer_data); PORT_ArenaUnmark(pl, mark); - + return certIssuerAndSN; loser: - if (serial_data) - CFRelease(serial_data); - if (issuer_data) - CFRelease(issuer_data); + CFReleaseNull(serial_data); + CFReleaseNull(issuer_data); PORT_ArenaRelease(pl, mark); PORT_SetError(SEC_INTERNAL_ONLY); diff --git a/libsecurity_smime/security_smime b/libsecurity_smime/security_smime deleted file mode 120000 index 945c9b46..00000000 --- a/libsecurity_smime/security_smime +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/ntlm/NtlmGenerator.c b/ntlm/NtlmGenerator.c index 90762e16..f8fb24e2 100644 --- a/ntlm/NtlmGenerator.c +++ b/ntlm/NtlmGenerator.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include /* @@ -662,13 +662,15 @@ OSStatus _NtlmGeneratePasswordHashes( unsigned char hash[NTLM_DIGEST_LENGTH]; result = ntlmPasswordHash(password, hash); - if (result) + if (result) { return result; - - *ntlmHash = CFDataCreate(alloc, hash, sizeof(hash)); + } + + *ntlmHash = CFDataCreate(alloc, hash, sizeof(hash)); memset(hash, 0, sizeof(hash)); - if (*ntlmHash == NULL) + if (*ntlmHash == NULL) { result = errSecAllocate; + } static const UInt8 zero[NTLM_DIGEST_LENGTH] = { 0 }; *lmHash = CFDataCreate(NULL, zero, sizeof(zero)); diff --git a/ntlm/ntlmBlobPriv.c b/ntlm/ntlmBlobPriv.c index 5866c307..e6a28592 100644 --- a/ntlm/ntlmBlobPriv.c +++ b/ntlm/ntlmBlobPriv.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -183,12 +183,14 @@ OSStatus ntlmStringToLE( unsigned *ucodeLen) // RETURNED { CFIndex len = CFStringGetLength(pwd); - if (len > NTLM_MAX_STRING_LEN) + if (len > NTLM_MAX_STRING_LEN) { return errSecAllocate; - unsigned char *data = (unsigned char *)malloc(len * 2); - if (data == NULL) + } + unsigned char *data = (unsigned char *)malloc(len * 2); + if (data == NULL) { return errSecAllocate; - unsigned char *cp = data; + } + unsigned char *cp = data; CFIndex dex; for(dex=0; dexapplication_protocols == NULL) { + content->application_protocols = xpc_array_create(NULL, 0); + } + xpc_object_t tuple = xpc_array_create(NULL, 0); + if (tuple != NULL) { + xpc_array_set_string(tuple, XPC_ARRAY_APPEND, application_protocol); + xpc_array_set_uint64(tuple, XPC_ARRAY_APPEND, (uint64_t)specific_transport); + + xpc_array_append_value(content->application_protocols, tuple); + xpc_release(tuple); + } + return true; + }); +} + +xpc_object_t +sec_protocol_options_copy_transport_specific_application_protocol(sec_protocol_options_t options, sec_protocol_transport_t specific_transport) +{ + SEC_PROTOCOL_OPTIONS_VALIDATE(options, NULL); + + xpc_object_t filtered_application_protocols = xpc_array_create(NULL, 0); + + bool success = sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + xpc_object_t application_protocols = content->application_protocols; + if (application_protocols == NULL) { return false; } - CFRelease(serverName); - free(content->server_name); + size_t application_protocol_count = xpc_array_get_count(application_protocols); + for (size_t i = 0; i < application_protocol_count; i++) { + xpc_object_t application_protocol = xpc_array_get_value(application_protocols, i); + + if (xpc_get_type(application_protocol) == XPC_TYPE_STRING) { + xpc_array_set_string(filtered_application_protocols, XPC_ARRAY_APPEND, xpc_string_get_string_ptr(application_protocol)); + continue; + } + + if (xpc_get_type(application_protocol) == XPC_TYPE_ARRAY) { + uint64_t application_protocol_transport = xpc_array_get_uint64(application_protocol, 1); + if (application_protocol_transport != (uint64_t)specific_transport && specific_transport != sec_protocol_transport_any) { + continue; + } + + xpc_array_set_string(filtered_application_protocols, XPC_ARRAY_APPEND, xpc_array_get_string(application_protocol, 0)); + continue; + } + } + + return xpc_array_get_count(filtered_application_protocols) != 0; + }); + + if (!success) { + xpc_release(filtered_application_protocols); + filtered_application_protocols = NULL; + } + + return filtered_application_protocols; +} + +void +sec_protocol_options_set_tls_server_name(sec_protocol_options_t options, const char *server_name) +{ + SEC_PROTOCOL_OPTIONS_VALIDATE(options,); + SEC_PROTOCOL_OPTIONS_VALIDATE(server_name,); + + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + free(content->server_name); content->server_name = strdup(server_name); return true; }); @@ -787,6 +849,20 @@ sec_protocol_options_set_peer_authentication_required(sec_protocol_options_t opt }); } +void +sec_protocol_options_set_peer_authentication_optional(sec_protocol_options_t options, bool peer_authentication_optional) { + SEC_PROTOCOL_OPTIONS_VALIDATE(options,); + + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + content->peer_authentication_optional = peer_authentication_optional; + content->peer_authentication_override = true; + return true; + }); +} + void sec_protocol_options_set_key_update_block(sec_protocol_options_t options, sec_protocol_key_update_t update_block, dispatch_queue_t update_queue) { @@ -909,6 +985,31 @@ sec_protocol_options_set_tls_encryption_secret_update_block(sec_protocol_options }); } +void +sec_protocol_options_set_tls_encryption_level_update_block(sec_protocol_options_t options, sec_protocol_tls_encryption_level_update_t update_block, dispatch_queue_t update_queue) +{ + SEC_PROTOCOL_OPTIONS_VALIDATE(options,); + SEC_PROTOCOL_OPTIONS_VALIDATE(update_block,); + SEC_PROTOCOL_OPTIONS_VALIDATE(update_queue,); + + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + if (content->tls_encryption_level_update_block != NULL) { + Block_release(content->tls_encryption_level_update_block); + } + if (content->tls_encryption_level_update_queue != NULL) { + dispatch_release(content->tls_encryption_level_update_queue); + } + + content->tls_encryption_level_update_block = Block_copy(update_block); + content->tls_encryption_level_update_queue = update_queue; + dispatch_retain(content->tls_encryption_level_update_queue); + return true; + }); +} + void sec_protocol_options_set_session_state(sec_protocol_options_t options, dispatch_data_t session_state) { @@ -1131,21 +1232,7 @@ sec_protocol_options_tls_handshake_message_callback(sec_protocol_options_t optio } void -sec_protocol_options_set_tls_SIKE503_exchange_enabled(sec_protocol_options_t options, bool tls_SIKE503_exchange_enabled) -{ - SEC_PROTOCOL_OPTIONS_VALIDATE(options,); - - (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { - sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; - SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); - - content->tls_SIKE503_exchange_enabled = tls_SIKE503_exchange_enabled; - return true; - }); -} - -void -sec_protocol_options_set_tls_HRSS_exchange_enabled(sec_protocol_options_t options, bool tls_HRSS_exchange_enabled) +sec_protocol_options_set_eddsa_enabled(sec_protocol_options_t options, bool eddsa_enabled) { SEC_PROTOCOL_OPTIONS_VALIDATE(options,); @@ -1153,13 +1240,13 @@ sec_protocol_options_set_tls_HRSS_exchange_enabled(sec_protocol_options_t option sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); - content->tls_HRSS_exchange_enabled = tls_HRSS_exchange_enabled; + content->eddsa_enabled = eddsa_enabled; return true; }); } void -sec_protocol_options_set_eddsa_enabled(sec_protocol_options_t options, bool eddsa_enabled) +sec_protocol_options_set_tls_delegated_credentials_enabled(sec_protocol_options_t options, bool tls_delegated_credentials_enabled) { SEC_PROTOCOL_OPTIONS_VALIDATE(options,); @@ -1167,13 +1254,13 @@ sec_protocol_options_set_eddsa_enabled(sec_protocol_options_t options, bool edds sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); - content->eddsa_enabled = eddsa_enabled; + content->tls_delegated_credentials_enabled = tls_delegated_credentials_enabled; return true; }); } void -sec_protocol_options_set_tls_delegated_credentials_enabled(sec_protocol_options_t options, bool tls_delegated_credentials_enabled) +sec_protocol_options_set_tls_grease_enabled(sec_protocol_options_t options, bool tls_grease_enabled) { SEC_PROTOCOL_OPTIONS_VALIDATE(options,); @@ -1181,13 +1268,13 @@ sec_protocol_options_set_tls_delegated_credentials_enabled(sec_protocol_options_ sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); - content->tls_delegated_credentials_enabled = tls_delegated_credentials_enabled; + content->tls_grease_enabled = tls_grease_enabled; return true; }); } void -sec_protocol_options_set_tls_grease_enabled(sec_protocol_options_t options, bool tls_grease_enabled) +sec_protocol_options_set_allow_unknown_alpn_protos(sec_protocol_options_t options, bool allow_unknown_alpn_protos) { SEC_PROTOCOL_OPTIONS_VALIDATE(options,); @@ -1195,7 +1282,8 @@ sec_protocol_options_set_tls_grease_enabled(sec_protocol_options_t options, bool sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); - content->tls_grease_enabled = tls_grease_enabled; + content->allow_unknown_alpn_protos = allow_unknown_alpn_protos; + content->allow_unknown_alpn_protos_override = true; return true; }); } @@ -2122,9 +2210,8 @@ static const char *_options_bool_keys[] = { SEC_PROTOCOL_OPTIONS_KEY_enable_renegotiation, SEC_PROTOCOL_OPTIONS_KEY_enable_early_data, SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_required, + SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_optional, SEC_PROTOCOL_OPTIONS_KEY_certificate_compression_enabled, - SEC_PROTOCOL_OPTIONS_KEY_tls_SIKE503_exchange_enabled, - SEC_PROTOCOL_OPTIONS_KEY_tls_HRSS_exchange_enabled, SEC_PROTOCOL_OPTIONS_KEY_eddsa_enabled, SEC_PROTOCOL_OPTIONS_KEY_tls_delegated_credentials_enabled, SEC_PROTOCOL_OPTIONS_KEY_tls_grease_enabled, @@ -2214,9 +2301,8 @@ _serialize_options(xpc_object_t dictionary, sec_protocol_options_content_t optio xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_renegotiation)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(enable_early_data)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(peer_authentication_required)); + xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(peer_authentication_optional)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(certificate_compression_enabled)); - xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_SIKE503_exchange_enabled)); - xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_HRSS_exchange_enabled)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(eddsa_enabled)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_delegated_credentials_enabled)); xpc_dictionary_set_bool(dictionary, EXPAND_PARAMETER(tls_grease_enabled)); @@ -2291,16 +2377,12 @@ static struct _options_bool_key_setter { .setter_pointer = sec_protocol_options_set_peer_authentication_required, }, { - .key = SEC_PROTOCOL_OPTIONS_KEY_certificate_compression_enabled, - .setter_pointer = sec_protocol_options_set_tls_certificate_compression_enabled, - }, - { - .key = SEC_PROTOCOL_OPTIONS_KEY_tls_SIKE503_exchange_enabled, - .setter_pointer = sec_protocol_options_set_tls_SIKE503_exchange_enabled, + .key = SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_optional, + .setter_pointer = sec_protocol_options_set_peer_authentication_optional, }, { - .key = SEC_PROTOCOL_OPTIONS_KEY_tls_HRSS_exchange_enabled, - .setter_pointer = sec_protocol_options_set_tls_HRSS_exchange_enabled, + .key = SEC_PROTOCOL_OPTIONS_KEY_certificate_compression_enabled, + .setter_pointer = sec_protocol_options_set_tls_certificate_compression_enabled, }, { .key = SEC_PROTOCOL_OPTIONS_KEY_eddsa_enabled, @@ -2711,3 +2793,17 @@ sec_protocol_options_apply_config(sec_protocol_options_t options, xpc_object_t c return _apply_config_options(options, config); } + +bool +sec_protocol_options_set_tls_block_length_padding(sec_protocol_options_t options, sec_protocol_block_length_padding_t block_length_padding) +{ + SEC_PROTOCOL_METADATA_VALIDATE(options, false); + + return sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + content->tls_block_length_padding = block_length_padding; + return true; + }); +} diff --git a/protocol/SecProtocolConfiguration.h b/protocol/SecProtocolConfiguration.h index 6d8694d3..c57ebf5c 100644 --- a/protocol/SecProtocolConfiguration.h +++ b/protocol/SecProtocolConfiguration.h @@ -143,11 +143,14 @@ sec_protocol_configuration_tls_required(sec_protocol_configuration_t config); * @param host * A NULL-terminated C string containing the host endpoint to examine. * + * @param is_direct + * A flag which indicates if the given hostname is local (direct). + * * @return True if connections to the endpoint require TLS, and false otherwise. */ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) bool -sec_protocol_configuration_tls_required_for_host(sec_protocol_configuration_t config, const char *host); +sec_protocol_configuration_tls_required_for_host(sec_protocol_configuration_t config, const char *host, bool is_direct); /*! * @function sec_protocol_configuration_tls_required_for_address diff --git a/protocol/SecProtocolConfiguration.m b/protocol/SecProtocolConfiguration.m index a88816f1..5f31e234 100644 --- a/protocol/SecProtocolConfiguration.m +++ b/protocol/SecProtocolConfiguration.m @@ -11,7 +11,7 @@ #import #define MINIMUM_RSA_KEY_SIZE 2048 -#define MINIMUM_ECDSA_KEY_SIZE 2048 +#define MINIMUM_ECDSA_KEY_SIZE 256 #define MINIMUM_HASH_ALGORITHM kSecSignatureHashAlgorithmSHA256 #define MINIMUM_PROTOCOL kTLSProtocol12 @@ -187,7 +187,7 @@ sec_protocol_configuration_tls_required(sec_protocol_configuration_t config) } static bool -sec_protocol_configuration_tls_required_for_host_internal(sec_protocol_configuration_t config, const char *host, bool parent_domain) +sec_protocol_configuration_tls_required_for_host_internal(sec_protocol_configuration_t config, const char *host, bool parent_domain, bool is_direct) { xpc_object_t map = sec_protocol_configuration_get_map(config); if (map == nil) { @@ -195,6 +195,11 @@ sec_protocol_configuration_tls_required_for_host_internal(sec_protocol_configura return true; } + if (is_direct && xpc_dictionary_get_bool(map, kAllowsLocalNetworking)) { + // Local domains do not require TLS if the kAllowsLocalNetworking flag is set. + return false; + } + xpc_object_t domain_map = xpc_dictionary_get_dictionary(map, kExceptionDomains); if (domain_map == nil) { // Absent per-domain exceptions, use the default. @@ -205,7 +210,7 @@ sec_protocol_configuration_tls_required_for_host_internal(sec_protocol_configura if (entry == nil) { const char *parent_host = _find_parent_domain(host); if (parent_host != NULL) { - return sec_protocol_configuration_tls_required_for_host_internal(config, parent_host, true); + return sec_protocol_configuration_tls_required_for_host_internal(config, parent_host, true, is_direct); } return sec_protocol_configuration_tls_required(config); } @@ -222,9 +227,9 @@ sec_protocol_configuration_tls_required_for_host_internal(sec_protocol_configura } bool -sec_protocol_configuration_tls_required_for_host(sec_protocol_configuration_t config, const char *host) +sec_protocol_configuration_tls_required_for_host(sec_protocol_configuration_t config, const char *host, bool is_direct) { - return sec_protocol_configuration_tls_required_for_host_internal(config, host, false); + return sec_protocol_configuration_tls_required_for_host_internal(config, host, false, is_direct); } bool @@ -332,17 +337,21 @@ sec_protocol_configuration_set_ats_overrides(sec_protocol_configuration_t config #define BOOLEAN_FOR_KEY(dictionary, key, value, default) \ bool value = default; \ { \ - NSNumber *nsValue = [dictionary valueForKey:[[NSString alloc] initWithFormat:@"%s", key]]; \ - if (nsValue) { \ - value = [nsValue boolValue]; \ + if (dictionary[[[NSString alloc] initWithFormat:@"%s", key]]) { \ + NSNumber *nsValue = [dictionary valueForKey:[[NSString alloc] initWithFormat:@"%s", key]]; \ + if (nsValue) { \ + value = [nsValue boolValue]; \ + } \ } \ } #define STRING_FOR_KEY(dictionary, key, value, default) \ NSString *value = default; \ { \ - NSString *nsValue = [dictionary valueForKey:[[NSString alloc] initWithFormat:@"%s", key]]; \ - if (nsValue) { \ - value = nsValue; \ + if (dictionary[[[NSString alloc] initWithFormat:@"%s", key]]) { \ + NSString *nsValue = [dictionary valueForKey:[[NSString alloc] initWithFormat:@"%s", key]]; \ + if (nsValue) { \ + value = nsValue; \ + } \ } \ } @@ -381,13 +390,12 @@ sec_protocol_configuration_set_ats_overrides(sec_protocol_configuration_t config *stop = YES; } - xpc_object_t entry_map = xpc_dictionary_create(NULL, NULL, 0); - - BOOLEAN_FOR_KEY(entry_map, kExceptionAllowsInsecureHTTPLoads, allows_http, false); - BOOLEAN_FOR_KEY(entry_map, kIncludesSubdomains, includes_subdomains, false); - BOOLEAN_FOR_KEY(entry_map, kExceptionRequiresForwardSecrecy, requires_pfs, false); - STRING_FOR_KEY(entry_map, kExceptionMinimumTLSVersion, minimum_tls, @"TLSv1.2"); + BOOLEAN_FOR_KEY(entry, kExceptionAllowsInsecureHTTPLoads, allows_http, false); + BOOLEAN_FOR_KEY(entry, kIncludesSubdomains, includes_subdomains, false); + BOOLEAN_FOR_KEY(entry, kExceptionRequiresForwardSecrecy, requires_pfs, false); + STRING_FOR_KEY(entry, kExceptionMinimumTLSVersion, minimum_tls, @"TLSv1.2"); + xpc_object_t entry_map = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_bool(entry_map, kIncludesSubdomains, includes_subdomains); xpc_dictionary_set_bool(entry_map, kExceptionAllowsInsecureHTTPLoads, allows_http); xpc_dictionary_set_bool(entry_map, kExceptionRequiresForwardSecrecy, requires_pfs); diff --git a/protocol/SecProtocolConfigurationTest.m b/protocol/SecProtocolConfigurationTest.m index ef0b8aac..56a59317 100644 --- a/protocol/SecProtocolConfigurationTest.m +++ b/protocol/SecProtocolConfigurationTest.m @@ -350,16 +350,23 @@ protocol_string_to_version(const char *protocol) return (sec_protocol_options_t)_nw_protocol_create_options(mock_protocol_copy_definition()); } -- (void)testExampleFile:(NSURL *)path +static bool +isLocalTLD(NSString *host) { - NSDictionary *dictionary = [[NSDictionary alloc] init]; - sec_protocol_configuration_builder_t builder = sec_protocol_configuration_builder_create((__bridge CFDictionaryRef)dictionary, true); - sec_protocol_configuration_t configuration = sec_protocol_configuration_create_with_builder(builder); - XCTAssertTrue(configuration != nil, @"failed to build configuration"); - if (!configuration) { - return; + if ([host length] == 0) { + return false; + } + if ([host hasSuffix:@".local"] || [host hasSuffix:@".local."]) { + return true; + } + if ([host rangeOfString:@"."].location == NSNotFound) { + return true; } + return false; +} +- (void)testExampleFile:(NSURL *)path +{ NSData *exampleData = [[NSData alloc] initWithContentsOfURL:path]; NSDictionary *exampleATS = [NSJSONSerialization JSONObjectWithData:exampleData options:kNilOptions error:nil]; XCTAssertNotNil(exampleATS, @"Loading %@ failed", path); @@ -367,6 +374,24 @@ protocol_string_to_version(const char *protocol) return; } + sec_protocol_configuration_builder_t builder = sec_protocol_configuration_builder_create((__bridge CFDictionaryRef)exampleATS, true); + sec_protocol_configuration_t configuration = sec_protocol_configuration_create_with_builder(builder); + XCTAssertTrue(configuration != nil, @"failed to build configuration"); + if (!configuration) { + return; + } + + __block bool allows_local_networking = false; + [exampleATS enumerateKeysAndObjectsUsingBlock:^(id _key, id _obj, BOOL *stop) { + NSString *key = (NSString *)_key; + if ([key isEqualToString:@"NSAllowsLocalNetworking"]) { + NSNumber *value = (NSNumber *)_obj; + if (value) { + allows_local_networking = [value boolValue]; + } + } + }]; + [exampleATS enumerateKeysAndObjectsUsingBlock:^(id _key, id _obj, BOOL *stop) { NSString *key = (NSString *)_key; if ([key isEqualToString:@"NSExceptionDomains"]) { @@ -415,7 +440,15 @@ protocol_string_to_version(const char *protocol) } }); - XCTAssertTrue(allows_http != sec_protocol_configuration_tls_required_for_host(configuration, [domain cStringUsingEncoding:NSUTF8StringEncoding])); + bool is_direct = isLocalTLD(domain); + bool tls_required = sec_protocol_configuration_tls_required_for_host(configuration, [domain cStringUsingEncoding:NSUTF8StringEncoding], is_direct); + if (is_direct) { + // If the hostname is direct, then we permit it if the NSAllowsLocalNetworking exception is set. + XCTAssertTrue(allows_local_networking != tls_required); + } else { + // Otherwise, we require TLS it the NSExceptionAllowsInsecureHTTPLoads flag is set. + XCTAssertTrue(allows_http != tls_required); + } }]; } }]; diff --git a/protocol/SecProtocolHelper.m b/protocol/SecProtocolHelper.m index 307ea379..23736e46 100644 --- a/protocol/SecProtocolHelper.m +++ b/protocol/SecProtocolHelper.m @@ -98,16 +98,6 @@ static const struct tls_ciphersuite_definition tls_ciphersuite_definitions[] = { static const size_t tls_ciphersuite_definitions_length = \ sizeof(tls_ciphersuite_definitions) / sizeof(struct tls_ciphersuite_definition); -// Remove macro definitions -#undef CiphersuitesTLS13 -#undef CiphersuitesPFS -#undef CiphersuitesNonPFS -#undef CiphersuitesTLS10_3DES -#undef CiphersuitesTLS10 -#undef CiphersuitesDHE -#undef DefineTLSCiphersuiteGroupList -#undef DefineTLSCiphersuiteDefinition - const tls_ciphersuite_t * sec_protocol_helper_ciphersuite_group_to_ciphersuite_list(tls_ciphersuite_group_t group, size_t *list_count) { diff --git a/protocol/SecProtocolInternal.h b/protocol/SecProtocolInternal.h index 97fd5c0e..e97cfecb 100644 --- a/protocol/SecProtocolInternal.h +++ b/protocol/SecProtocolInternal.h @@ -27,18 +27,18 @@ #define CiphersuitesPFS \ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \ + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, \ + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, \ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, \ + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, \ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, \ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, \ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, \ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, \ - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, \ - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, \ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, \ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, \ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, \ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, \ - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, \ - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA #define CiphersuitesNonPFS \ TLS_RSA_WITH_AES_256_GCM_SHA384, \ @@ -115,18 +115,6 @@ sec_protocol_configuration_populate_secure_defaults(sec_protocol_configuration_t void sec_protocol_configuration_register_builtin_exceptions(sec_protocol_configuration_t configuration); -bool -sec_protocol_helper_ciphersuite_group_contains_ciphersuite(tls_ciphersuite_group_t group, tls_ciphersuite_t suite); - -tls_protocol_version_t -sec_protocol_helper_ciphersuite_minimum_TLS_version(tls_ciphersuite_t ciphersuite); - -tls_protocol_version_t -sec_protocol_helper_ciphersuite_maximum_TLS_version(tls_ciphersuite_t ciphersuite); - -const char * -sec_protocol_helper_get_ciphersuite_name(tls_ciphersuite_t ciphersuite); - const tls_key_exchange_group_t * sec_protocol_helper_tls_key_exchange_group_set_to_key_exchange_group_list(tls_key_exchange_group_set_t set, size_t *listSize); diff --git a/protocol/SecProtocolMetadata.h b/protocol/SecProtocolMetadata.h index 3a67ddb3..5b7448d0 100644 --- a/protocol/SecProtocolMetadata.h +++ b/protocol/SecProtocolMetadata.h @@ -135,7 +135,7 @@ sec_protocol_metadata_get_negotiated_protocol_version(sec_protocol_metadata_t me * * @return A `tls_ciphersuite_t`. */ -API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)) +API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) tls_ciphersuite_t sec_protocol_metadata_get_negotiated_tls_ciphersuite(sec_protocol_metadata_t metadata); @@ -151,8 +151,7 @@ sec_protocol_metadata_get_negotiated_tls_ciphersuite(sec_protocol_metadata_t met * @return A SSLCipherSuite. */ API_DEPRECATED_WITH_REPLACEMENT("sec_protocol_metadata_get_negotiated_tls_ciphersuite", - macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0)) -API_UNAVAILABLE(iosmac) + macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0), macCatalyst(13.0, 13.0)) SSLCipherSuite sec_protocol_metadata_get_negotiated_ciphersuite(sec_protocol_metadata_t metadata); diff --git a/protocol/SecProtocolOptions.h b/protocol/SecProtocolOptions.h index 616dac53..3d3deac8 100644 --- a/protocol/SecProtocolOptions.h +++ b/protocol/SecProtocolOptions.h @@ -129,8 +129,7 @@ sec_protocol_options_append_tls_ciphersuite(sec_protocol_options_t options, tls_ * @param ciphersuite * A SSLCipherSuite value. */ -API_DEPRECATED("Use sec_protocol_options_append_tls_ciphersuite", macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0)) -API_UNAVAILABLE(iosmac) +API_DEPRECATED("Use sec_protocol_options_append_tls_ciphersuite", macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0), macCatalyst(13.0, 13.0)) void sec_protocol_options_add_tls_ciphersuite(sec_protocol_options_t options, SSLCipherSuite ciphersuite); @@ -162,8 +161,7 @@ sec_protocol_options_append_tls_ciphersuite_group(sec_protocol_options_t options * @param group * A SSLCipherSuiteGroup value. */ -API_DEPRECATED("Use sec_protocol_options_append_tls_ciphersuite_group", macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0)) -API_UNAVAILABLE(iosmac) +API_DEPRECATED("Use sec_protocol_options_append_tls_ciphersuite_group", macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0), macCatalyst(13.0, 13.0)) void sec_protocol_options_add_tls_ciphersuite_group(sec_protocol_options_t options, SSLCiphersuiteGroup group); @@ -180,8 +178,7 @@ sec_protocol_options_add_tls_ciphersuite_group(sec_protocol_options_t options, S * A SSLProtocol enum value. */ API_DEPRECATED_WITH_REPLACEMENT("sec_protocol_options_set_min_tls_protocol_version", - macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0)) -API_UNAVAILABLE(iosmac) + macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0), macCatalyst(13.0, 13.0)) void sec_protocol_options_set_tls_min_version(sec_protocol_options_t options, SSLProtocol version); @@ -238,8 +235,7 @@ sec_protocol_options_get_default_min_dtls_protocol_version(void); * A SSLProtocol enum value. */ API_DEPRECATED_WITH_REPLACEMENT("sec_protocol_options_set_max_tls_protocol_version", - macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0)) -API_UNAVAILABLE(iosmac) + macos(10.14, 10.15), ios(12.0, 13.0), watchos(5.0, 6.0), tvos(12.0, 13.0), macCatalyst(13.0, 13.0)) void sec_protocol_options_set_tls_max_version(sec_protocol_options_t options, SSLProtocol version); @@ -303,14 +299,14 @@ sec_protocol_options_add_tls_application_protocol(sec_protocol_options_t options * @function sec_protocol_options_set_tls_server_name * * @abstract - * Set the server (domain) name to be used in the TLS SNI. This will override + * Set the server name to be used when verifying the peer's certificate. This will override * the server name obtained from the endpoint. * * @param options * A `sec_protocol_options_t` instance. * * @param server_name - * A NULL-terminated string carrying the server (domain) name. + * A NULL-terminated string carrying the server name. */ API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)) void @@ -553,6 +549,26 @@ API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)) void sec_protocol_options_set_peer_authentication_required(sec_protocol_options_t options, bool peer_authentication_required); +/*! + * @function sec_protocol_options_set_peer_authentication_optional + * + * @abstract + * When this is enabled, the endpoint requests the peer certificate, but if none is provided, the + * endpoint still proceeds with the connection. Default false for servers; always false for clients (this + * function is a no-op for clients). If peer_authentication_required is set to true via + * sec_protocol_options_set_peer_authentication_required(), peer_authentication_optional will be disregarded + * and the peer certificate will be required. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param peer_authentication_optional + * Flag to enable or disable requested peer authentication. + */ +SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +void +sec_protocol_options_set_peer_authentication_optional(sec_protocol_options_t options, bool peer_authentication_optional); + #ifdef __BLOCKS__ /*! diff --git a/protocol/SecProtocolPriv.h b/protocol/SecProtocolPriv.h index 25395fec..b3f1c28f 100644 --- a/protocol/SecProtocolPriv.h +++ b/protocol/SecProtocolPriv.h @@ -231,6 +231,59 @@ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) void sec_protocol_options_set_quic_transport_parameters(sec_protocol_options_t options, dispatch_data_t transport_parameters); +/*! + * @enum sec_protocol_transport_t + * + * @abstract An enumeration of the different transport protocols that can have specific security options. + */ +typedef enum { + sec_protocol_transport_any = 0, + sec_protocol_transport_tcp, + sec_protocol_transport_quic, +} sec_protocol_transport_t; + +#define SEC_PROTOCOL_HAS_TRANSPORT_SPECIFIC_ALPN 1 + +/*! + * @function sec_protocol_options_add_transport_specific_application_protocol + * + * @abstract + * Add an application protocol supported by clients of this protocol instance, specific + * to a transport protocol. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param application_protocol + * A NULL-terminated string defining the application protocol. + * + * @param specific_transport + * A specific transport to which to bind the application protocol. + */ +API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +void +sec_protocol_options_add_transport_specific_application_protocol(sec_protocol_options_t options, const char *application_protocol, sec_protocol_transport_t specific_transport); + +/*! + * @function sec_protocol_options_copy_transport_specific_application_protocol + * + * @abstract + * Return the application protocols configured by clients of this protocol instance, specific + * to a transport protocol if applicable. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param specific_transport + * A specific transport to which to bind the application protocol. + * + * @return An `xpc_object_t` instance carrying an array of application protocol strings, or nil. + */ +#define SEC_PROTOCOL_HAS_TRANSPORT_SPECIFIC_ALPN_GETTER 1 /* rdar://problem/63987477 */ +SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +SEC_RETURNS_RETAINED __nullable xpc_object_t +sec_protocol_options_copy_transport_specific_application_protocol(sec_protocol_options_t options, sec_protocol_transport_t specific_transport); + /*! * @enum sec_protocol_tls_encryption_level_t * @@ -282,6 +335,43 @@ sec_protocol_options_set_tls_encryption_secret_update_block(sec_protocol_options sec_protocol_tls_encryption_secret_update_t update_block, dispatch_queue_t update_queue); +/*! + * @block sec_protocol_tls_encryption_level_update_t + * + * @abstract + * Block to be invoked when the encryption level is updated. + * + * @param level + * The new `sec_protocol_tls_encryption_level_t`. + * + * @param is_write + * True if this is a write level and false if it's a read. + * + */ +typedef void (^sec_protocol_tls_encryption_level_update_t)(sec_protocol_tls_encryption_level_t level, bool is_write); + +/*! + * @function sec_protocol_options_set_tls_encryption_level_update_block + * + * @abstract + * Set the TLS encryption level update block. It is invoked whenever the encryption level is updated. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param update_block + * A `sec_protocol_tls_encryption_level_update_t` instance. + * + * @params update_queue + * A `dispatch_queue_t` on which the update block should be called. + */ +#define SEC_PROTOCOL_HAS_TLS_ENCRYPTION_LEVEL_UPDATE_BLOCK 1 /* rdar://problem/63986462 */ +SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +void +sec_protocol_options_set_tls_encryption_level_update_block(sec_protocol_options_t options, + sec_protocol_tls_encryption_level_update_t update_block, + dispatch_queue_t update_queue); + /*! * @block sec_protocol_private_key_complete_t * @@ -468,45 +558,6 @@ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) void sec_protocol_options_add_tls_key_exchange_group_set(sec_protocol_options_t options, SSLKeyExchangeGroupSet set); -/*! - * @function sec_protocol_options_set_tls_SIKE503_exchange_enabled - * - * @abstract - * Enable SIKE using P503 for TLS 1.3 key exchange. - * - * DO NOT DEPEND ON THIS SPI. IT IS FOR EXPERIMENTAL PURPOSES AND SUBJECT TO REMOVAL WITHOUT ADVANCE NOTICE. - * BUILD BREAKAGE ISSUES WILL BE SENT TO THE CALLING PROJECT. - * - * @param options - * A `sec_protocol_options_t` instance. - * - * @param tls_SIKE503_exchange_enabled - * Flag to enable SIKE with P503. - */ -#define SEC_PROTOCOL_HAS_PQ_TLS_HANDLES 1 -API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) -void -sec_protocol_options_set_tls_SIKE503_exchange_enabled(sec_protocol_options_t options, bool tls_SIKE503_exchange_enabled); - -/*! - * @function sec_protocol_options_set_tls_HRSS_exchange_enabled - * - * @abstract - * Enable HRSS for TLS 1.3 key exchange. - * - * DO NOT DEPEND ON THIS SPI. IT IS FOR EXPERIMENTAL PURPOSES AND SUBJECT TO REMOVAL WITHOUT ADVANCE NOTICE. - * BUILD BREAKAGE ISSUES WILL BE SENT TO THE CALLING PROJECT. - * - * @param options - * A `sec_protocol_options_t` instance. - * - * @param tls_HRSS_exchange_enabled - * Flag to enable HRSS. - */ -API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) -void -sec_protocol_options_set_tls_HRSS_exchange_enabled(sec_protocol_options_t options, bool tls_HRSS_exchange_enabled); - /*! * @function sec_protocol_options_set_eddsa_enabled * @@ -581,6 +632,23 @@ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) void sec_protocol_options_set_tls_grease_enabled(sec_protocol_options_t options, bool tls_grease_enabled); +/*! + * @function sec_protocol_options_set_allow_unknown_alpn_protos + * + * @abstract + * Configure clients to accept server ALPN values they did not advertise. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param allow_unknown_alpn_protos + * Flag to enable or disable the use of unknown ALPN values. + */ +#define SEC_PROTOCOL_HAS_ALLOW_UNKNOWN_ALPN_PROTOS_SETTER 1 /* rdar://problem/64449512 */ +SPI_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +void +sec_protocol_options_set_allow_unknown_alpn_protos(sec_protocol_options_t options, bool allow_unknown_alpn_protos); + /*! * @function sec_protocol_options_set_experiment_identifier * @@ -1171,8 +1239,96 @@ API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) const tls_ciphersuite_t * __nullable sec_protocol_helper_ciphersuite_group_to_ciphersuite_list(tls_ciphersuite_group_t group, size_t *list_count); +typedef CF_ENUM(uint16_t, sec_protocol_block_length_padding_t) { + SEC_PROTOCOL_BLOCK_LENGTH_PADDING_NONE = 0, + SEC_PROTOCOL_BLOCK_LENGTH_PADDING_DEFAULT = 16, +}; + +/*! + * @function sec_protocol_options_set_tls_block_length_padding + * + * @abstract + * Pad TLS messages to a multiple of the specified block length. By default, padding is disabled. + * + * @param options + * A `sec_protocol_options_t` instance. + * + * @param block_length_padding + * A sec_protocol_block_length_padding_t variable specifying the block length padding. Setting the block length padding to 0 disables padding. + * + * @return True if the padding policy has been successfully set, false otherwise. + */ +API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) +bool +sec_protocol_options_set_tls_block_length_padding(sec_protocol_options_t options, sec_protocol_block_length_padding_t block_length_padding); + +/*! + * @function sec_protocol_helper_ciphersuite_group_contains_ciphersuite + * + * @abstract + * This function is exposed for testing purposes only. It MUST NOT be called by clients. + * + * @param group + * A `tls_ciphersuite_group_t` instance. + * + * @param suite + * A `tls_ciphersuite_t` instance. + * + * @return True if the ciphersuite group contains the given ciphersuite, false otherwise. +*/ +API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +bool +sec_protocol_helper_ciphersuite_group_contains_ciphersuite(tls_ciphersuite_group_t group, tls_ciphersuite_t suite); + +/*! + * @function sec_protocol_helper_ciphersuite_minimum_TLS_version + * + * @abstract + * This function is exposed for testing purposes only. It MUST NOT be called by clients. + * + * @param ciphersuite + * A `tls_ciphersuite_t` instance. + * + * @return The `tls_protocol_version_t` pertaining to the minimum TLS version designated for the given ciphersuite. +*/ +API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +tls_protocol_version_t +sec_protocol_helper_ciphersuite_minimum_TLS_version(tls_ciphersuite_t ciphersuite); + +/*! + * @function sec_protocol_helper_ciphersuite_maximum_TLS_version + * + * @abstract + * This function is exposed for testing purposes only. It MUST NOT be called by clients. + * + * @param ciphersuite + * A `tls_ciphersuite_t` instance. + * + * @return The `tls_protocol_version_t` pertaining to the maximum TLS version designated for the given ciphersuite. +*/ +API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +tls_protocol_version_t +sec_protocol_helper_ciphersuite_maximum_TLS_version(tls_ciphersuite_t ciphersuite); + +/*! + * @function sec_protocol_helper_get_ciphersuite_name + * + * @abstract + * This function is exposed for testing purposes only. It MUST NOT be called by clients. + * + * @param ciphersuite + * A `tls_ciphersuite_t` instance. + * + * @return A string representation of the given ciphersuite, or NULL if it does not exist. +*/ +API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)) +const char * __nullable +sec_protocol_helper_get_ciphersuite_name(tls_ciphersuite_t ciphersuite); + #define SEC_PROTOCOL_HAS_MULTI_PSK_SUPPORT 1 +#define SEC_PROTOCOL_HAS_PEER_AUTHENTICATION_OPTIONAL 1 + struct sec_protocol_options_content { SSLProtocol min_version; SSLProtocol max_version; @@ -1195,6 +1351,8 @@ struct sec_protocol_options_content { dispatch_data_t quic_transport_parameters; sec_protocol_tls_encryption_secret_update_t tls_secret_update_block; dispatch_queue_t tls_secret_update_queue; + sec_protocol_tls_encryption_level_update_t tls_encryption_level_update_block; + dispatch_queue_t tls_encryption_level_update_queue; sec_protocol_session_update_t session_update_block; dispatch_queue_t session_update_queue; dispatch_data_t session_state; @@ -1246,13 +1404,16 @@ struct sec_protocol_options_content { unsigned enable_early_data : 1; unsigned enable_early_data_override : 1; unsigned peer_authentication_required : 1; + unsigned peer_authentication_optional : 1; unsigned peer_authentication_override : 1; unsigned certificate_compression_enabled : 1; - unsigned tls_SIKE503_exchange_enabled : 1; - unsigned tls_HRSS_exchange_enabled : 1; unsigned eddsa_enabled : 1; unsigned tls_delegated_credentials_enabled : 1; unsigned tls_grease_enabled : 1; + unsigned allow_unknown_alpn_protos : 1; + unsigned allow_unknown_alpn_protos_override : 1; + + sec_protocol_block_length_padding_t tls_block_length_padding; }; struct sec_protocol_metadata_content { diff --git a/protocol/SecProtocolTest.m b/protocol/SecProtocolTest.m index 4ae69401..bbfdc9c7 100644 --- a/protocol/SecProtocolTest.m +++ b/protocol/SecProtocolTest.m @@ -682,6 +682,24 @@ _sec_protocol_test_metadata_session_exporter(void *handle) }); } +- (void)test_sec_protocol_options_set_tls_encryption_level_update_block { + void (^update_block)(sec_protocol_tls_encryption_level_t, bool) = ^(__unused sec_protocol_tls_encryption_level_t level, __unused bool is_write) { + // pass + }; + + dispatch_queue_t update_queue = dispatch_queue_create("test_sec_protocol_options_set_tls_encryption_level_update_block_queue", DISPATCH_QUEUE_SERIAL); + + sec_protocol_options_t options = [self create_sec_protocol_options]; + sec_protocol_options_set_tls_encryption_level_update_block(options, update_block, update_queue); + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + XCTAssertTrue(content->tls_encryption_level_update_block == update_block); + XCTAssertTrue(content->tls_encryption_level_update_queue != nil); + return false; + }); +} + - (void)test_sec_protocol_options_set_local_certificates { sec_protocol_options_t options = [self create_sec_protocol_options]; @@ -730,6 +748,30 @@ _sec_protocol_test_metadata_session_exporter(void *handle) }); } +- (void)test_sec_protocol_options_set_peer_authentication_required { + sec_protocol_options_t options = [self create_sec_protocol_options]; + + sec_protocol_options_set_peer_authentication_required(options, true); + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + XCTAssertTrue(content->peer_authentication_required); + return true; + }); +} + +- (void)test_sec_protocol_options_set_peer_authentication_optional { + sec_protocol_options_t options = [self create_sec_protocol_options]; + + sec_protocol_options_set_peer_authentication_optional(options, true); + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + XCTAssertTrue(content->peer_authentication_optional); + return true; + }); +} + - (void)test_sec_protocol_options_are_equal { sec_protocol_options_t optionsA = [self create_sec_protocol_options]; sec_protocol_options_t optionsB = [self create_sec_protocol_options]; @@ -860,23 +902,95 @@ _sec_protocol_test_metadata_session_exporter(void *handle) XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB)); const char *application_protocolA = "h2"; - const char *application_protocolB = "h3"; sec_protocol_options_add_tls_application_protocol(optionsA, application_protocolA); XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB)); - sec_protocol_options_add_tls_application_protocol(optionsB, application_protocolB); + sec_protocol_options_add_tls_application_protocol(optionsB, application_protocolA); + XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB)); + + const char *application_protocolB = "h3"; + sec_protocol_options_add_transport_specific_application_protocol(optionsA, application_protocolB, + sec_protocol_transport_quic); XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB)); + sec_protocol_options_add_transport_specific_application_protocol(optionsB, application_protocolB, + sec_protocol_transport_quic); + XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB)); + sec_protocol_options_append_tls_ciphersuite(optionsB, 7331); XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB)); } +- (void)test_sec_protocol_options_copy_transport_specific_application_protocol { + sec_protocol_options_t options = [self create_sec_protocol_options]; + + const char *application_protocol_dummy = "dummy"; + const char *application_protocol_h2 = "h2"; + const char *application_protocol_h3 = "h3"; + + sec_protocol_options_add_transport_specific_application_protocol(options, application_protocol_h2, sec_protocol_transport_tcp); + xpc_object_t protocols = sec_protocol_options_copy_transport_specific_application_protocol(options, sec_protocol_transport_quic); + XCTAssertFalse(protocols != NULL); + if (protocols != NULL) { + return; + } + + sec_protocol_options_add_tls_application_protocol(options, application_protocol_dummy); + sec_protocol_options_add_transport_specific_application_protocol(options, application_protocol_h3, sec_protocol_transport_quic); + + for (sec_protocol_transport_t t = sec_protocol_transport_any; t <= sec_protocol_transport_quic; t++) { + protocols = sec_protocol_options_copy_transport_specific_application_protocol(options, t); + XCTAssertFalse(protocols == NULL); + if (protocols == NULL) { + return; + } + + const char *application_protocols_for_any[] = { application_protocol_h2, application_protocol_dummy, application_protocol_h3, }; + // application_protocols_for_tcp includes application_protocol_dummy because "dummy" isn't tied to any transport. + const char *application_protocols_for_tcp[] = { application_protocol_h2, application_protocol_dummy, }; + const char *application_protocols_for_quic[] = { application_protocol_dummy, application_protocol_h3, }; + + size_t count_of_application_protocols_for_transport[] = { + [sec_protocol_transport_any] = sizeof(application_protocols_for_any)/sizeof(application_protocols_for_any[0]), + [sec_protocol_transport_tcp] = sizeof(application_protocols_for_tcp)/sizeof(application_protocols_for_tcp[0]), + [sec_protocol_transport_quic] = sizeof(application_protocols_for_quic)/sizeof(application_protocols_for_quic[0]), + }; + + XCTAssertFalse(xpc_get_type(protocols) != XPC_TYPE_ARRAY); + if (xpc_get_type(protocols) != XPC_TYPE_ARRAY) { + return; + } + + size_t protocols_count = xpc_array_get_count(protocols); + XCTAssertFalse(protocols_count != count_of_application_protocols_for_transport[t]); + if (protocols_count != count_of_application_protocols_for_transport[t]) { + return; + } + + const char **application_protocols_for_transport[] = { + [sec_protocol_transport_any] = application_protocols_for_any, + [sec_protocol_transport_tcp] = application_protocols_for_tcp, + [sec_protocol_transport_quic] = application_protocols_for_quic, + }; + + for (size_t i = 0; i < protocols_count; i++) { + const char *protocol_name = xpc_array_get_string(protocols, i); + const char *expected_protocol_name = application_protocols_for_transport[t][i]; + bool protocol_match = (strcmp(protocol_name, expected_protocol_name) == 0); + + XCTAssertFalse(protocol_match == false); + if (protocol_match == false) { + return; + } + } + } +} + - (void)test_sec_protocol_options_set_tls_server_name { sec_protocol_options_t optionsA = [self create_sec_protocol_options]; sec_protocol_options_t optionsB = [self create_sec_protocol_options]; const char *server_nameA = "apple.com"; - const char *server_nameB = "127.0.0.1"; - const char *server_nameC = "example.com"; + const char *server_nameB = "example.com"; /* * Empty options should be equal. @@ -897,19 +1011,11 @@ _sec_protocol_test_metadata_session_exporter(void *handle) sec_protocol_options_set_tls_server_name(optionsB, server_nameA); XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB)); - /* - * Try to set the name to nameB in optionsB. - * It should fail since nameB is invalid. - * Options A, B should still be equal. - */ - sec_protocol_options_set_tls_server_name(optionsB, server_nameB); - XCTAssertTrue(sec_protocol_options_are_equal(optionsA, optionsB)); - /* * Change the current name in B. * Comparison should fail. */ - sec_protocol_options_set_tls_server_name(optionsB, server_nameC); + sec_protocol_options_set_tls_server_name(optionsB, server_nameB); XCTAssertFalse(sec_protocol_options_are_equal(optionsA, optionsB)); } @@ -1082,6 +1188,24 @@ _sec_protocol_test_metadata_session_exporter(void *handle) XCTAssertTrue(accessed, @"Expected sec_protocol_metadata_access_pre_shared_keys to traverse PSK list"); } +- (void)test_sec_protocol_options_set_tls_block_length_padding { + sec_protocol_options_t options = [self create_sec_protocol_options]; + + sec_protocol_block_length_padding_t expected_block_length_padding = SEC_PROTOCOL_BLOCK_LENGTH_PADDING_DEFAULT; + sec_protocol_options_set_tls_block_length_padding(options, expected_block_length_padding); + + __block sec_protocol_block_length_padding_t current_block_length_padding = SEC_PROTOCOL_BLOCK_LENGTH_PADDING_NONE; + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + + current_block_length_padding = content->tls_block_length_padding; + return true; + }); + + XCTAssertTrue(current_block_length_padding == expected_block_length_padding); +} + - (void)test_sec_protocol_experiment_identifier { sec_protocol_options_t options = [self create_sec_protocol_options]; @@ -1152,4 +1276,24 @@ _sec_protocol_test_metadata_session_exporter(void *handle) XCTAssertTrue(memcmp(uuid, copied_metadata, sizeof(copied_metadata)) == 0); } +- (void)test_sec_protocol_options_set_allow_unknown_alpn_protos { + sec_protocol_options_t options = [self create_sec_protocol_options]; + + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + XCTAssertFalse(content->allow_unknown_alpn_protos_override); + return true; + }); + + sec_protocol_options_set_allow_unknown_alpn_protos(options, true); + (void)sec_protocol_options_access_handle(options, ^bool(void *handle) { + sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle; + SEC_PROTOCOL_OPTIONS_VALIDATE(content, false); + XCTAssertTrue(content->allow_unknown_alpn_protos); + XCTAssertTrue(content->allow_unknown_alpn_protos_override); + return true; + }); +} + @end diff --git a/protocol/SecProtocolTypes.m b/protocol/SecProtocolTypes.m index b5258fff..558bb46a 100644 --- a/protocol/SecProtocolTypes.m +++ b/protocol/SecProtocolTypes.m @@ -84,11 +84,11 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_array, - (instancetype)init { - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->xpc_array = xpc_array_create(NULL, 0); + } else { return SEC_NIL_OUT_OF_MEMORY; } - self->xpc_array = xpc_array_create(NULL, 0); return self; } @@ -166,11 +166,11 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_identity, return SEC_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity)); + } else { return SEC_NIL_OUT_OF_MEMORY; } - self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity)); return self; } @@ -180,12 +180,12 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_identity, return SEC_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity)); + self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates)); + } else { return SEC_NIL_OUT_OF_MEMORY; } - self->identity = __DECONST(SecIdentityRef, CFRetainSafe(_identity)); - self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates)); return self; } @@ -202,16 +202,14 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_identity, return SEC_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates)); + self->sign_block = sign; + self->decrypt_block = decrypt; + self->operation_queue = queue; + } else { return SEC_NIL_OUT_OF_MEMORY; } - - self->certs = __DECONST(CFArrayRef, CFRetainSafe(certificates)); - self->sign_block = sign; - self->decrypt_block = decrypt; - self->operation_queue = queue; - return self; } @@ -354,11 +352,11 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_certificate, return SEC_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->certificate = __DECONST(SecCertificateRef, CFRetainSafe(_certificate)); + } else { return SEC_NIL_OUT_OF_MEMORY; } - self->certificate = __DECONST(SecCertificateRef, CFRetainSafe(_certificate)); return self; } @@ -403,11 +401,11 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_trust, return SEC_NIL_BAD_INPUT; } - self = [super init]; - if (self == nil) { + if ((self = [super init])) { + self->trust = __DECONST(SecTrustRef, CFRetainSafe(_trust)); + } else { return SEC_NIL_OUT_OF_MEMORY; } - self->trust = __DECONST(SecTrustRef, CFRetainSafe(_trust)); return self; } @@ -461,9 +459,9 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_protocol_configuration_builder, @implementation SEC_CONCRETE_CLASS_NAME(sec_protocol_configuration_builder) -- (id)init { - self = [super init]; - if (self) { +- (id)init +{ + if (self = [super init]) { CFBundleRef bundle = CFBundleGetMainBundle(); if (bundle != NULL) { CFTypeRef rawATS = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR(kATSInfoKey)); @@ -475,9 +473,10 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_protocol_configuration_builder, return self; } -- (id)initWithDictionary:(CFDictionaryRef)dict andInternalFlag:(bool)flag { - self = [super init]; - if (self) { +- (id)initWithDictionary:(CFDictionaryRef)dict + andInternalFlag:(bool)flag +{ + if ((self = [super init])) { self->dictionary = dict; CFRetainSafe(dict); self->is_apple = flag; @@ -519,8 +518,7 @@ SEC_OBJECT_IMPL_INTERNAL_OBJC(sec_protocol_configuration, @implementation SEC_CONCRETE_CLASS_NAME(sec_protocol_configuration) - (id)init { - self = [super init]; - if (self) { + if ((self = [super init])) { self->dictionary = xpc_dictionary_create(NULL, NULL, 0); } return self; diff --git a/protocol/test_data/example1.json b/protocol/test_data/example1.json index aa62c08e..1930362b 100644 --- a/protocol/test_data/example1.json +++ b/protocol/test_data/example1.json @@ -2,7 +2,7 @@ "NSAllowsArbitraryLoads": false, "NSAllowsArbitraryLoadsForMedia": false, "NSAllowsArbitraryLoadsInWebContent": false, - "NSAllowsLocalNetworking": false, + "NSAllowsLocalNetworking": true, "NSExceptionDomains": { "apple.com": { "NSIncludesSubdomains": true, @@ -45,6 +45,8 @@ "NSExceptionAllowsInsecureHTTPLoads": true, "NSExceptionMinimumTLSVersion": "TLSv1.2", "NSExceptionRequiresForwardSecrecy": false - } + }, + "example.local": { + } } -} \ No newline at end of file +} diff --git a/secacltests/secacltests-entitlements.plist b/secacltests/secacltests-entitlements.plist index c635aaf3..846bd4e3 100644 --- a/secacltests/secacltests-entitlements.plist +++ b/secacltests/secacltests-entitlements.plist @@ -18,5 +18,7 @@ com.apple.security.sos + com.apple.private.security.storage.Keychains + diff --git a/secdtests/secdtests-entitlements.plist b/secdtests/secdtests-entitlements.plist index d9ca668f..403823d9 100644 --- a/secdtests/secdtests-entitlements.plist +++ b/secdtests/secdtests-entitlements.plist @@ -16,13 +16,15 @@ com.apple.private.security.no-sandbox + com.apple.security.app-sandbox + keychain-cloud-circle com.apple.keystore.access-keychain-keys com.apple.keystore.device - com.apple.private.applecredentialmanager.allow + com.apple.keystore.lockassertion restore-keychain @@ -51,5 +53,7 @@ com.apple.ProtectedCloudStorage com.apple.security.ckks + com.apple.private.security.storage.Keychains + diff --git a/secdxctests/CDKeychainTests.m b/secdxctests/CDKeychainTests.m index 1a736d23..488deaba 100644 --- a/secdxctests/CDKeychainTests.m +++ b/secdxctests/CDKeychainTests.m @@ -90,7 +90,7 @@ _connection = [[SFKeychainServerFakeConnection alloc] init]; self.keychainPartialMock = OCMPartialMock(_keychain); - [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; + [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataWithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; [_keychain _registerItemTypeForTesting:[TestItemType itemType]]; } @@ -472,7 +472,7 @@ XCTAssertNotNil(keychain, @"should have been able to create a keychain instance"); self.keychainPartialMock = OCMPartialMock(keychain); - [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; + [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataWithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; SecCDKeychainAccessControlEntity* owner = [SecCDKeychainAccessControlEntity accessControlEntityWithType:SecCDKeychainAccessControlEntityTypeAccessGroup stringRepresentation:@"com.apple.token"]; diff --git a/secdxctests/KeychainAPITests.m b/secdxctests/KeychainAPITests.m index a68d4f2d..f2a61b5f 100644 --- a/secdxctests/KeychainAPITests.m +++ b/secdxctests/KeychainAPITests.m @@ -27,6 +27,7 @@ #import "CKKS.h" #import "SecDbKeychainItemV7.h" #import "SecItemPriv.h" +#include "SecItemInternal.h" #import "SecItemServer.h" #import "spi.h" #import "SecDbKeychainSerializedItemV7.h" @@ -41,8 +42,8 @@ #include #include #include - -void* testlist = NULL; +#include "der_plist.h" +#import "SecItemRateLimit_tests.h" #if USE_KEYSTORE @@ -54,8 +55,6 @@ void* testlist = NULL; + (void)setUp { [super setUp]; - SecCKKSDisable(); - securityd_init(NULL); } - (NSString*)nameOfTest @@ -152,6 +151,52 @@ void* testlist = NULL; XCTAssertEqual(errSecParam, SecItemDelete((CFDictionaryRef)attrs)); } +- (BOOL)passInternalAttributeToKeychainAPIsWithKey:(id)key value:(id)value { + NSDictionary* badquery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + key : value, + }; + NSDictionary* badupdate = @{key : value}; + + NSDictionary* okquery = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + }; + NSDictionary* okupdate = @{(id)kSecAttrService : @"DifferentService"}; + + if (SecItemAdd((__bridge CFDictionaryRef)badquery, NULL) != errSecParam) { + XCTFail("SecItemAdd did not return errSecParam"); + return NO; + } + if (SecItemCopyMatching((__bridge CFDictionaryRef)badquery, NULL) != errSecParam) { + XCTFail("SecItemCopyMatching did not return errSecParam"); + return NO; + } + if (SecItemUpdate((__bridge CFDictionaryRef)badquery, (__bridge CFDictionaryRef)okupdate) != errSecParam) { + XCTFail("SecItemUpdate with bad query did not return errSecParam"); + return NO; + } + if (SecItemUpdate((__bridge CFDictionaryRef)okquery, (__bridge CFDictionaryRef)badupdate) != errSecParam) { + XCTFail("SecItemUpdate with bad update did not return errSecParam"); + return NO; + } + if (SecItemDelete((__bridge CFDictionaryRef)badquery) != errSecParam) { + XCTFail("SecItemDelete did not return errSecParam"); + return NO; + } + return YES; +} + +// Expand this, rdar://problem/59297616 +- (void)testNotAllowedToPassInternalAttributes { + XCTAssert([self passInternalAttributeToKeychainAPIsWithKey:(__bridge NSString*)kSecAttrAppClipItem value:@YES], @"Expect errSecParam for 'clip' attribute"); +} + #pragma mark - Corruption Tests const uint8_t keychain_data[] = { @@ -280,6 +325,313 @@ static void SecDbTestCorruptionHandler(void) } } +- (void)testInetBinaryFields { + NSData* note = [@"OBVIOUS_NOTES_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + NSData* history = [@"OBVIOUS_HISTORY_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + NSData* client0 = [@"OBVIOUS_CLIENT0_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + NSData* client1 = [@"OBVIOUS_CLIENT1_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + NSData* client2 = [@"OBVIOUS_CLIENT2_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + NSData* client3 = [@"OBVIOUS_CLIENT3_DATA" dataUsingEncoding:NSUTF8StringEncoding]; + + NSData* originalPassword = [@"asdf" dataUsingEncoding:NSUTF8StringEncoding]; + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassInternetPassword, + (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlocked, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrDescription : @"desc", + (id)kSecAttrServer : @"server", + (id)kSecAttrAccount : @"test-account", + (id)kSecValueData : originalPassword, + (id)kSecDataInetExtraNotes : note, + (id)kSecDataInetExtraHistory : history, + (id)kSecDataInetExtraClientDefined0 : client0, + (id)kSecDataInetExtraClientDefined1 : client1, + (id)kSecDataInetExtraClientDefined2 : client2, + (id)kSecDataInetExtraClientDefined3 : client3, + + (id)kSecReturnAttributes : @YES, + } mutableCopy]; + + CFTypeRef cfresult = nil; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, &cfresult), errSecSuccess, "Should be able to add an item using new binary fields"); + NSDictionary* result = (NSDictionary*)CFBridgingRelease(cfresult); + XCTAssertNotNil(result, "Should have some sort of result"); + + XCTAssertNil(result[(id)kSecDataInetExtraNotes], "Notes field should not be returned as an attribute from add"); + XCTAssertNil(result[(id)kSecDataInetExtraHistory], "Notes field should not be returned as an attribute from add"); + + NSDictionary* queryFind = @{ + (id)kSecClass : (id)kSecClassInternetPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrAccount : @"test-account", + }; + + NSMutableDictionary* queryFindOneWithJustAttributes = [[NSMutableDictionary alloc] initWithDictionary:queryFind]; + queryFindOneWithJustAttributes[(id)kSecReturnAttributes] = @YES; + + NSMutableDictionary* queryFindAllWithJustAttributes = [[NSMutableDictionary alloc] initWithDictionary:queryFindOneWithJustAttributes]; + queryFindAllWithJustAttributes[(id)kSecMatchLimit] = (id)kSecMatchLimitAll; + + NSDictionary* queryFindOneWithAttributesAndData = @{ + (id)kSecClass : (id)kSecClassInternetPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecReturnAttributes : @YES, + (id)kSecReturnData: @YES, + (id)kSecAttrAccount : @"test-account", + }; + + NSDictionary* queryFindAllWithAttributesAndData = @{ + (id)kSecClass : (id)kSecClassInternetPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecReturnAttributes : @YES, + (id)kSecReturnData: @YES, + (id)kSecMatchLimit : (id)kSecMatchLimitAll, + (id)kSecAttrAccount : @"test-account", + }; + + /* Copy with a single record limite, but with attributes only */ + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)queryFindOneWithJustAttributes, &cfresult), errSecSuccess, "Should be able to find an item"); + + result = (NSDictionary*)CFBridgingRelease(cfresult); + XCTAssertNotNil(result, "Should have some sort of result"); + + XCTAssertNil(result[(id)kSecDataInetExtraNotes], "Notes field should not be returned as an attribute from copymatching when finding a single item"); + XCTAssertNil(result[(id)kSecDataInetExtraHistory], "Notes field should not be returned as an attribute from copymatching when finding a single item"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined0], "ClientDefined0 field should not be returned as an attribute from copymatching when finding a single item"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined1], "ClientDefined1 field should not be returned as an attribute from copymatching when finding a single item"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined2], "ClientDefined2 field should not be returned as an attribute from copymatching when finding a single item"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined3], "ClientDefined3 field should not be returned as an attribute from copymatching when finding a single item"); + + /* Copy with no limit, but with attributes only */ + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)queryFindAllWithJustAttributes, &cfresult), errSecSuccess, "Should be able to find an item"); + NSArray* arrayResult = (NSArray*)CFBridgingRelease(cfresult); + XCTAssertNotNil(arrayResult, "Should have some sort of result"); + XCTAssertTrue([arrayResult isKindOfClass:[NSArray class]], "Should have received an array back from copymatching"); + XCTAssertEqual(arrayResult.count, 1, "Array should have one element"); + + result = arrayResult[0]; + XCTAssertNil(result[(id)kSecDataInetExtraNotes], "Notes field should not be returned as an attribute from copymatching when finding all items"); + XCTAssertNil(result[(id)kSecDataInetExtraHistory], "Notes field should not be returned as an attribute from copymatching when finding all items"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined0], "ClientDefined0 field should not be returned as an attribute from copymatching when finding all items"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined1], "ClientDefined1 field should not be returned as an attribute from copymatching when finding all items"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined2], "ClientDefined2 field should not be returned as an attribute from copymatching when finding all items"); + XCTAssertNil(result[(id)kSecDataInetExtraClientDefined3], "ClientDefined3 field should not be returned as an attribute from copymatching when finding all items"); + + /* Copy with single-record limit, but with attributes and data */ + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)queryFindOneWithAttributesAndData, &cfresult), errSecSuccess, "Should be able to find an item"); + result = (NSDictionary*)CFBridgingRelease(cfresult); + XCTAssertNotNil(result, "Should have some sort of result"); + + XCTAssertEqualObjects(note, result[(id)kSecDataInetExtraNotes], "Notes field should be returned as data"); + XCTAssertEqualObjects(history, result[(id)kSecDataInetExtraHistory], "History field should be returned as data"); + XCTAssertEqualObjects(client0, result[(id)kSecDataInetExtraClientDefined0], "Client Defined 0 field should be returned as data"); + XCTAssertEqualObjects(client1, result[(id)kSecDataInetExtraClientDefined1], "Client Defined 1 field should be returned as data"); + XCTAssertEqualObjects(client2, result[(id)kSecDataInetExtraClientDefined2], "Client Defined 2 field should be returned as data"); + XCTAssertEqualObjects(client3, result[(id)kSecDataInetExtraClientDefined3], "Client Defined 3 field should be returned as data"); + + /* Copy with no limit, but with attributes and data */ + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)queryFindAllWithAttributesAndData, &cfresult), errSecSuccess, "Should be able to find an item"); + arrayResult = (NSArray*)CFBridgingRelease(cfresult); + XCTAssertNotNil(arrayResult, "Should have some sort of result"); + XCTAssertTrue([arrayResult isKindOfClass:[NSArray class]], "Should have received an array back from copymatching"); + XCTAssertEqual(arrayResult.count, 1, "Array should have one element"); + result = arrayResult[0]; + XCTAssertEqualObjects(note, result[(id)kSecDataInetExtraNotes], "Notes field should be returned as data"); + XCTAssertEqualObjects(history, result[(id)kSecDataInetExtraHistory], "History field should be returned as data"); + XCTAssertEqualObjects(client0, result[(id)kSecDataInetExtraClientDefined0], "Client Defined 0 field should be returned as data"); + XCTAssertEqualObjects(client1, result[(id)kSecDataInetExtraClientDefined1], "Client Defined 1 field should be returned as data"); + XCTAssertEqualObjects(client2, result[(id)kSecDataInetExtraClientDefined2], "Client Defined 2 field should be returned as data"); + XCTAssertEqualObjects(client3, result[(id)kSecDataInetExtraClientDefined3], "Client Defined 3 field should be returned as data"); + + /* Copy just looking for the password */ + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassInternetPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecReturnData: @YES, + (id)kSecAttrAccount : @"test-account", + }, &cfresult), errSecSuccess, "Should be able to find an item"); + + NSData* password = (NSData*)CFBridgingRelease(cfresult); + XCTAssertNotNil(password, "Should have some sort of password"); + XCTAssertTrue([password isKindOfClass:[NSData class]], "Password is a data"); + XCTAssertEqualObjects(originalPassword, password, "Should still be able to fetch the original password"); + + NSData* newHistoryContents = [@"gone" dataUsingEncoding:NSUTF8StringEncoding]; + + NSDictionary* updateQuery = @{ + (id)kSecDataInetExtraHistory : newHistoryContents, + }; + + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)queryFind, (__bridge CFDictionaryRef)updateQuery), errSecSuccess, "Should be able to update a history field"); + + // And find it again + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)queryFindOneWithAttributesAndData, &cfresult), errSecSuccess, "Should be able to find an item"); + result = (NSDictionary*)CFBridgingRelease(cfresult); + XCTAssertNotNil(result, "Should have some sort of result"); + + XCTAssertEqualObjects(note, result[(id)kSecDataInetExtraNotes], "Notes field should be returned as data"); + XCTAssertEqualObjects(newHistoryContents, result[(id)kSecDataInetExtraHistory], "History field should be updated"); + XCTAssertEqualObjects(client0, result[(id)kSecDataInetExtraClientDefined0], "Client Defined 0 field should be returned as data"); + XCTAssertEqualObjects(client1, result[(id)kSecDataInetExtraClientDefined1], "Client Defined 1 field should be returned as data"); + XCTAssertEqualObjects(client2, result[(id)kSecDataInetExtraClientDefined2], "Client Defined 2 field should be returned as data"); + XCTAssertEqualObjects(client3, result[(id)kSecDataInetExtraClientDefined3], "Client Defined 3 field should be returned as data"); +} + +// When this test starts failing, hopefully rdar://problem/60332379 got fixed +- (void)testBadDateCausesDERDecodeValidationError { + // Wonky time calculation hastily stolen from SecGregorianDateGetAbsoluteTime and tweaked + // As of right now this causes CFCalendarDecomposeAbsoluteTime with Zulu calendar to give a seemingly incorrect date which then causes DER date validation issues + CFAbsoluteTime absTime = (CFAbsoluteTime)(((-(1902 * 365) + -38) * 24 + 0) * 60 + -1) * 60 + 1; + absTime -= 0.0004; // Just to make sure the nanoseconds keep getting encoded/decoded properly + CFDateRef date = CFDateCreate(NULL, absTime); + + CFErrorRef error = NULL; + size_t plistSize = der_sizeof_plist(date, &error); + XCTAssert(error == NULL); + XCTAssertGreaterThan(plistSize, 0); + + // Encode without repair does not validate dates because that changes behavior I do not want to fiddle with + uint8_t* der = calloc(1, plistSize); + uint8_t* der_end = der + plistSize; + uint8_t* result = der_encode_plist(date, &error, der, der_end); + XCTAssert(error == NULL); + XCTAssertEqual(der, result); + + // ...but decoding does and will complain + CFPropertyListRef decoded = NULL; + XCTAssert(der_decode_plist(NULL, &decoded, &error, der, der_end) == NULL); + XCTAssert(error != NULL); + XCTAssertEqual(CFErrorGetDomain(error), kCFErrorDomainOSStatus); + NSString* description = CFBridgingRelease(CFErrorCopyDescription(error)); + XCTAssert([description containsString:@"Invalid date"]); + + CFReleaseNull(error); + free(der); +} + +// When this test starts failing, hopefully rdar://problem/60332379 got fixed +- (void)testBadDateWithDEREncodingRepairProducesDefaultValue { + // Wonky time calculation hastily stolen from SecGregorianDateGetAbsoluteTime and tweaked + // As of right now this causes CFCalendarDecomposeAbsoluteTime with Zulu calendar to give a seemingly incorrect date which then causes DER date validation issues + CFAbsoluteTime absTime = (CFAbsoluteTime)(((-(1902 * 365) + -38) * 24 + 0) * 60 + -1) * 60 + 1; + absTime -= 0.0004; // Just to make sure the nanoseconds keep getting encoded/decoded properly + CFDateRef date = CFDateCreate(NULL, absTime); + + CFErrorRef error = NULL; + size_t plistSize = der_sizeof_plist(date, &error); + XCTAssert(error == NULL); + XCTAssertGreaterThan(plistSize, 0); + + uint8_t* der = calloc(1, plistSize); + uint8_t* der_end = der + plistSize; + uint8_t* encoderesult = der_encode_plist_repair(date, &error, true, der, der_end); + XCTAssert(error == NULL); + XCTAssertEqual(der, encoderesult); + + CFPropertyListRef decoded = NULL; + const uint8_t* decoderesult = der_decode_plist(NULL, &decoded, &error, der, der_end); + XCTAssertEqual(der_end, decoderesult); + XCTAssertEqual(CFGetTypeID(decoded), CFDateGetTypeID()); + XCTAssertEqualWithAccuracy(CFDateGetAbsoluteTime(decoded), 0, 60 * 60 * 24); +} + +#pragma mark - SecItemRateLimit + +// This is not super accurate in BATS, so put some margin around what you need +- (void)sleepAlternativeForXCTest:(double)interval +{ + dispatch_semaphore_t localsema = dispatch_semaphore_create(0); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * interval), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + dispatch_semaphore_signal(localsema); + }); + dispatch_semaphore_wait(localsema, DISPATCH_TIME_FOREVER); +} + +- (void)testSecItemRateLimitTimePasses { + SecItemRateLimit* rl = [SecItemRateLimit getStaticRateLimit]; + [rl forceEnabled: true]; + + for (int idx = 0; idx < rl.roCapacity; ++idx) { + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + } + + for (int idx = 0; idx < rl.rwCapacity; ++idx) { + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + } + + [self sleepAlternativeForXCTest: 2]; + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + + [SecItemRateLimit resetStaticRateLimit]; +} + +- (void)testSecItemRateLimitResetAfterExceed { + SecItemRateLimit* rl = [SecItemRateLimit getStaticRateLimit]; + [rl forceEnabled: true]; + + for (int idx = 0; idx < rl.roCapacity; ++idx) { + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + } + XCTAssertFalse(isReadOnlyAPIRateWithinLimits()); + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + + for (int idx = 0; idx < rl.rwCapacity; ++idx) { + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + } + XCTAssertFalse(isModifyingAPIRateWithinLimits()); + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + + [SecItemRateLimit resetStaticRateLimit]; +} + +- (void)testSecItemRateLimitMultiplier { + SecItemRateLimit* rl = [SecItemRateLimit getStaticRateLimit]; + [rl forceEnabled: true]; + + int ro_iterations_before = 0; + for (; ro_iterations_before < rl.roCapacity; ++ro_iterations_before) { + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + } + XCTAssertFalse(isReadOnlyAPIRateWithinLimits()); + + int rw_iterations_before = 0; + for (; rw_iterations_before < rl.rwCapacity; ++rw_iterations_before) { + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + } + XCTAssertFalse(isModifyingAPIRateWithinLimits()); + + + int ro_iterations_after = 0; + for (; ro_iterations_after < rl.roCapacity; ++ro_iterations_after) { + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + } + XCTAssertFalse(isReadOnlyAPIRateWithinLimits()); + + int rw_iterations_after = 0; + for (; rw_iterations_after < rl.rwCapacity; ++rw_iterations_after) { + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + } + XCTAssertFalse(isModifyingAPIRateWithinLimits()); + + XCTAssertEqualWithAccuracy(rl.limitMultiplier * ro_iterations_before, ro_iterations_after, 1); + XCTAssertEqualWithAccuracy(rl.limitMultiplier * rw_iterations_before, rw_iterations_after, 1); + [SecItemRateLimit resetStaticRateLimit]; +} + +// We stipulate that this test is run on an internal release. +// If this were a platform binary limits would be enforced, but it should not be so they should not. +- (void)testSecItemRateLimitInternalPlatformBinariesOnly { + SecItemRateLimit* rl = [SecItemRateLimit getStaticRateLimit]; + + for (int idx = 0; idx < 3 * MAX(rl.roCapacity, rl.rwCapacity); ++idx) { + XCTAssertTrue(isReadOnlyAPIRateWithinLimits()); + XCTAssertTrue(isModifyingAPIRateWithinLimits()); + } + + [SecItemRateLimit resetStaticRateLimit]; +} + @end #endif diff --git a/secdxctests/KeychainAppClipTests.m b/secdxctests/KeychainAppClipTests.m new file mode 100644 index 00000000..2bbefecf --- /dev/null +++ b/secdxctests/KeychainAppClipTests.m @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2020 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@ + */ + +#import +#import +#include +#include + +#import "KeychainXCTest.h" + +#if USE_KEYSTORE +@interface KeychainAppClipTests : KeychainXCTest +@end + +@implementation KeychainAppClipTests { + // App Clips are only permitted to store items with agrp == appID, so we set and track it + NSString* _applicationIdentifier; +} + ++ (void)setUp { + [super setUp]; +} + +- (void)setUp { + [super setUp]; + SecSecurityClientAppClipToRegular(); + _applicationIdentifier = @"com.apple.security.appcliptests"; + SecSecurityClientSetApplicationIdentifier((__bridge CFStringRef)_applicationIdentifier); +} + ++ (void)tearDown { + SecSecurityClientAppClipToRegular(); + SecSecurityClientSetApplicationIdentifier(NULL); + [super tearDown]; +} + +# pragma mark - Test App Clip API Restrictions (SecItemAdd) + +- (void)testAppclipCanAddItem { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + }; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); +} + +- (void)testAppClipAddNoSyncAllowed { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrSynchronizable : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + }; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecRestrictedAPI); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +- (void)testAppClipAddNoAgrpAllowed { + SecSecurityClientRegularToAppClip(); + // By not explicitly setting entitlements we get the default set which is not permitted for an app clip + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + }; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecRestrictedAPI); + + SecSecurityClientAppClipToRegular(); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +# pragma mark - Test App Clip API Restrictions (SecItemUpdate) + +- (void)testAppClipCanUpdateItem { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + SecItemAdd((__bridge CFDictionaryRef)query, NULL); + + NSDictionary* update = @{ + (id)kSecValueData : [@"different" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrService : @"DifferentAppClipTestService", + }; + + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update), errSecSuccess); + query[(id)kSecAttrService] = @"DifferentAppClipTestService"; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); +} + +- (void)testAppClipUpdateNoSyncAllowed { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + SecItemAdd((__bridge CFDictionaryRef)query, NULL); + + NSDictionary* update = @{ + (id)kSecValueData : [@"different" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrSynchronizable : @YES, + }; + + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update), errSecRestrictedAPI); + query[(id)kSecAttrSynchronizable] = @YES; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +- (void)testAppClipUpdateNoAgrpAllowed { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + SecItemAdd((__bridge CFDictionaryRef)query, NULL); + + NSDictionary* update = @{ + (id)kSecValueData : [@"different" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrAccessGroup : @"someotheraccessgroup", + }; + + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update), errSecMissingEntitlement); + query[(id)kSecAttrAccessGroup] = @"someotheraccessgroup"; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecMissingEntitlement); +} + +# pragma mark - Test App Clip API Restrictions (SecItemCopyMatching) +// For now SICM doesn't care about sync, because there shouldn't be any items where (clip == 1 && sync == 1) + +- (void)testAppClipCopyMatchingNoAgrpsAllowed { + SecSecurityClientRegularToAppClip(); + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecReturnAttributes : @YES, + }; + + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecRestrictedAPI); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +# pragma mark - Test App Clip API Restrictions (SecItemDelete) + +- (void)testAppClipDeleteNoAgrpsAllowed { + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + }; + + XCTAssertEqual(SecItemDelete((__bridge CFDictionaryRef)query), errSecItemNotFound); + SecSecurityClientRegularToAppClip(); + XCTAssertEqual(SecItemDelete((__bridge CFDictionaryRef)query), errSecRestrictedAPI); +} + +# pragma mark - Test App Clip API Restrictions (Misc) + +- (void)testAppClipNoSecItemUpdateTokenItemsAllowed { + SecSecurityClientRegularToAppClip(); + // Don't bother setting it up, app clips aren't even welcome at the door. + XCTAssertEqual(SecItemUpdateTokenItemsForAccessGroups(NULL, (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], NULL), errSecRestrictedAPI); +} + +- (void)testAppClipCanPassAppIDAccessGroup { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrService : @"AppClipTestService", + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecReturnAttributes : @YES, + (id)kSecAttrAccessGroup : _applicationIdentifier, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + + NSDictionary* update = @{ + (id)kSecValueData : [@"betterpassword" dataUsingEncoding:NSUTF8StringEncoding], + }; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + query[(id)kSecValueData] = nil; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + query[(id)kSecReturnAttributes] = nil; + XCTAssertEqual(SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update), errSecSuccess); + XCTAssertEqual(SecItemDelete((__bridge CFDictionaryRef)query), errSecSuccess); +} + +# pragma mark - Test Item Deletion SPI + +- (void)testDeletionSPINoEntitlement { + XCTAssertEqual(SecItemDeleteKeychainItemsForAppClip((__bridge CFStringRef)@"nonexistent"), errSecMissingEntitlement); +} + +- (void)testDeletionSPINoItems { + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementPrivateAppClipDeletion, kCFBooleanTrue); + XCTAssertEqual(SecItemDeleteKeychainItemsForAppClip((__bridge CFStringRef)@"nonexistent"), errSecSuccess); +} + +- (void)testDeletionSPIDeleteAppClipItem { + // The SPI does not check if app clip, and the API does not check private entitlement + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementPrivateAppClipDeletion, kCFBooleanTrue); + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecReturnAttributes : @YES, + }; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemDeleteKeychainItemsForAppClip((__bridge CFStringRef)_applicationIdentifier), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +- (void)testDeletionSPILeaveRegularItemsAlone { + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementPrivateAppClipDeletion, kCFBooleanTrue); + NSString* agrp = @"com.apple.keychain.test.notanappclip"; + [self setEntitlements:@{ @"keychain-access-groups": @[agrp] } validated:YES]; + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecAttrAccessGroup : agrp, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding] + }; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemDeleteKeychainItemsForAppClip((__bridge CFStringRef)agrp), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); +} + +- (void)testDeletionSPILeaveOtherAppClipItemsAlone { + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + NSString* otherAppID = @"not-the-same-application-identifier"; + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementPrivateAppClipDeletion, kCFBooleanTrue); + + NSDictionary* query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecReturnAttributes : @YES, + }; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + [self setEntitlements:@{@"com.apple.application-identifier" : otherAppID} validated:YES]; + SecSecurityClientSetApplicationIdentifier((__bridge CFStringRef)otherAppID); + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + XCTAssertEqual(SecItemDeleteKeychainItemsForAppClip((__bridge CFStringRef)_applicationIdentifier), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + SecSecurityClientSetApplicationIdentifier((__bridge CFStringRef)_applicationIdentifier); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); +} + +@end +#endif diff --git a/secdxctests/KeychainBackupTests.m b/secdxctests/KeychainBackupTests.m new file mode 100644 index 00000000..666d3dd0 --- /dev/null +++ b/secdxctests/KeychainBackupTests.m @@ -0,0 +1,118 @@ +#import "KeychainXCTest.h" +#import +#import +#include +#include + +@interface KeychainBackupTests : KeychainXCTest +@end + + +@implementation KeychainBackupTests { + NSString* _applicationIdentifier; +} + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. + [super setUp]; + _applicationIdentifier = @"com.apple.security.backuptests"; + SecSecurityClientSetApplicationIdentifier((__bridge CFStringRef)_applicationIdentifier); +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +# pragma mark - Test OTA Backups + +// Code lovingly adapted from si-33-keychain-backup +#if USE_KEYSTORE +- (NSData*)createKeybagWithType:(keybag_handle_t)bag_type password:(NSData*)password +{ + keybag_handle_t handle = bad_keybag_handle; + kern_return_t bag_created = aks_create_bag(password ? password.bytes : NULL, password ? (int)password.length : 0, bag_type, &handle); + XCTAssertEqual(bag_created, kAKSReturnSuccess, @"Unable to create keybag"); + + void *bag = NULL; + int bagLen = 0; + kern_return_t bag_saved = aks_save_bag(handle, &bag, &bagLen); + XCTAssertEqual(bag_saved, kAKSReturnSuccess, @"Unable to save keybag"); + + NSData* bagData = [NSData dataWithBytes:bag length:bagLen]; + XCTAssertNotNil(bagData, @"Unable to create NSData from bag bytes"); + + return bagData; +} +#endif + +// All backup paths ultimately lead to SecServerCopyKeychainPlist which does the actual exporting, +// so this test ought to suffice for all backup configurations +- (void)testAppClipDoesNotBackup { + + // First add a "regular" item for each class, which we expect to be in the backup later + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecUseDataProtectionKeychain : @YES, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + } mutableCopy]; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassInternetPassword; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassCertificate; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassKey; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + // Switch to being an app clip, add another item for each class, which we expect not to find in the backup + SecSecurityClientRegularToAppClip(); + [self setEntitlements:@{@"com.apple.application-identifier" : _applicationIdentifier} validated:YES]; + + query[(id)kSecClass] = (id)kSecClassGenericPassword; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassInternetPassword; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassCertificate; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + query[(id)kSecClass] = (id)kSecClassKey; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + SecSecurityClientAppClipToRegular(); + SecAddLocalSecuritydXPCFakeEntitlement(kSecEntitlementRestoreKeychain, @YES); + + // Code lovingly adapted from si-33-keychain-backup + NSData* keybag; +#if USE_KEYSTORE + keybag = [self createKeybagWithType:kAppleKeyStoreBackupBag password:nil]; +#else + keybag = [NSData new]; +#endif + + NSData* data = CFBridgingRelease(_SecKeychainCopyBackup((__bridge CFDataRef)keybag, nil)); + + XCTAssert(data); + XCTAssertGreaterThan([data length], 42, @"Got empty dictionary"); + NSDictionary* keychain = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:nil error:nil]; + + // Only one item should be here for each class, which is the regular one. + XCTAssertEqual([keychain[@"genp"] count], 1); + XCTAssertEqual([keychain[@"inet"] count], 1); + XCTAssertEqual([keychain[@"cert"] count], 1); + XCTAssertEqual([keychain[@"keys"] count], 1); +} + +@end diff --git a/secdxctests/KeychainCryptoTests.m b/secdxctests/KeychainCryptoTests.m index bdf33b1b..3165c667 100644 --- a/secdxctests/KeychainCryptoTests.m +++ b/secdxctests/KeychainCryptoTests.m @@ -32,6 +32,7 @@ #import "spi.h" #import "SecDbKeychainSerializedItemV7.h" #import "SecDbKeychainSerializedMetadata.h" +#import "SecDbKeychainSerializedMetadataKey.h" #import "SecDbKeychainSerializedSecretData.h" #import "SecDbKeychainSerializedAKSWrappedKey.h" #import @@ -138,6 +139,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { SecAccessControlRef ac = NULL; NSDictionary* secretData = @{(id)kSecValueData : @"secret here"}; + CFDictionaryRef emptyDict = (__bridge CFDictionaryRef)@{}; ac = SecAccessControlCreate(NULL, &error); XCTAssertNotNil((__bridge id)ac, @"failed to create access control with error: %@", (__bridge id)error); @@ -145,16 +147,19 @@ static keyclass_t parse_keyclass(CFTypeRef value) { XCTAssertTrue(SecAccessControlSetProtection(ac, kSecAttrAccessibleWhenUnlocked, &error), @"failed to set access control protection with error: %@", error); XCTAssertNil((__bridge id)error, @"encountered error attempting to set access control protection: %@", (__bridge id)error); - XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, (__bridge CFDictionaryRef)@{}, NULL, &enc, true, &error), @"failed to encrypt data with error: %@", error); + XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, emptyDict, emptyDict, &enc, true, &error), @"failed to encrypt data with error: %@", error); XCTAssertTrue(enc != NULL, @"failed to get encrypted data from encryption function"); XCTAssertNil((__bridge id)error, @"encountered error attempting to encrypt data: %@", (__bridge id)error); CFReleaseNull(ac); CFMutableDictionaryRef attributes = NULL; uint32_t version = 0; + NSData* dummyACM = [NSData dataWithBytes:"dummy" length:5]; + const SecDbClass* class = kc_class_with_name(kSecClassGenericPassword); + NSArray* dummyArray = [NSArray array]; keyclass_t keyclass = 0; - XCTAssertTrue(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, NULL, enc, NULL, NULL, &attributes, &version, true, &keyclass, &error), @"failed to decrypt data with error: %@", error); + XCTAssertTrue(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, (__bridge CFDataRef _Nonnull)dummyACM, enc, class, (__bridge CFArrayRef)dummyArray, &attributes, &version, true, &keyclass, &error), @"failed to decrypt data with error: %@", error); XCTAssertNil((__bridge id)error, @"encountered error attempting to decrypt data: %@", (__bridge id)error); XCTAssertEqual(keyclass, key_class_ak, @"failed to get back the keyclass from decryption"); @@ -277,9 +282,9 @@ static keyclass_t parse_keyclass(CFTypeRef value) { NSError* error; SecDbKeychainItemV7* item = [[SecDbKeychainItemV7 alloc] initWithSecretAttributes:@{(id)kSecValueData : password} metadataAttributes:metadata tamperCheck:[[NSUUID UUID] UUIDString] keyclass:9]; [item encryptMetadataWithKeybag:0 error:&error]; - XCTAssertNil(error, @"Successfully encrypted metadata"); + XCTAssertNil(error, "error encrypting metadata with keybag 0"); [item encryptSecretDataWithKeybag:0 accessControl:SecAccessControlCreate(NULL, NULL) acmContext:nil error:&error]; - XCTAssertNil(error, @"Successfully encrypted secret data"); + XCTAssertNil(error, "error encrypting secret data with keybag 0"); SecDbKeychainSerializedItemV7* serializedItem = [[SecDbKeychainSerializedItemV7 alloc] init]; serializedItem.encryptedMetadata = item.encryptedMetadataBlob; serializedItem.encryptedSecretData = item.encryptedSecretDataBlob; @@ -341,6 +346,26 @@ static keyclass_t parse_keyclass(CFTypeRef value) { } - (void)trashMetadataClassAKey +{ + __block CFErrorRef cferror = NULL; + kc_with_dbt(true, &cferror, ^bool(SecDbConnectionRef dbt) { + CFStringRef sql = CFSTR("UPDATE metadatakeys SET data = ? WHERE keyclass = '6'"); + NSData* garbage = [@"super bad key" dataUsingEncoding:NSUTF8StringEncoding]; + SecDbPrepare(dbt, sql, &cferror, ^(sqlite3_stmt *stmt) { + SecDbBindObject(stmt, 1, (__bridge CFDataRef)garbage, &cferror); + SecDbStep(dbt, stmt, &cferror, NULL); + XCTAssertEqual(cferror, NULL, "Should be no error trashing class A metadatakey"); + CFReleaseNull(cferror); + }); + XCTAssertEqual(cferror, NULL, "Should be no error completing SecDbPrepare for trashing class A metadatakey"); + return true; + }); + CFReleaseNull(cferror); + + [[SecDbKeychainMetadataKeyStore sharedStore] dropClassAKeys]; +} + +- (void)deleteMetadataClassAKey { CFErrorRef cferror = NULL; @@ -356,32 +381,31 @@ static keyclass_t parse_keyclass(CFTypeRef value) { [[SecDbKeychainMetadataKeyStore sharedStore] dropClassAKeys]; } -- (void)checkDatabaseExistenceOfMetadataKey:(keyclass_t)keyclass shouldExist:(bool)shouldExist +- (void)checkDatabaseExistenceOfMetadataKey:(keyclass_t)keyclass shouldExist:(bool)shouldExist value:(NSData*)expectedData { CFErrorRef cferror = NULL; - + __block NSData* wrappedKey; kc_with_dbt(true, &cferror, ^bool(SecDbConnectionRef dbt) { __block CFErrorRef errref = NULL; NSString* sql = [NSString stringWithFormat:@"SELECT data, actualKeyclass FROM metadatakeys WHERE keyclass = %d", keyclass]; __block bool ok = true; - __block bool keyExists = false; ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &errref, ^(sqlite3_stmt *stmt) { ok &= SecDbStep(dbt, stmt, &errref, ^(bool *stop) { - NSData* wrappedKeyData = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)]; - NSMutableData* unwrappedKeyData = [NSMutableData dataWithLength:wrappedKeyData.length]; - - keyExists = !!unwrappedKeyData; + wrappedKey = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)]; }); }); XCTAssertTrue(ok, "Should have completed all operations correctly"); - XCTAssertEqual(errref, NULL, "Should be no error deleting class A metadatakey"); + XCTAssertEqual(errref, NULL, "Should be no error trying to find class A metadatakey"); if(shouldExist) { - XCTAssertTrue(keyExists, "Metadata class key should exist"); + XCTAssertNotNil(wrappedKey, "Metadata class key should exist"); + if (expectedData) { + XCTAssertEqualObjects(wrappedKey, expectedData); + } } else { - XCTAssertFalse(keyExists, "Metadata class key should not exist"); + XCTAssertNil(wrappedKey, "Metadata class key should not exist"); } CFReleaseNull(errref); return true; @@ -400,7 +424,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { OSStatus result = SecItemAdd((__bridge CFDictionaryRef)item, NULL); XCTAssertEqual(result, 0, @"failed to add test item to keychain"); - [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:true]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:true value:nil]; NSMutableDictionary* dataQuery = item.mutableCopy; [dataQuery removeObjectForKey:(id)kSecValueData]; @@ -413,7 +437,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { CFReleaseNull(foundItem); [self trashMetadataClassAKey]; - [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:false]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:true value:[@"super bad key" dataUsingEncoding:NSUTF8StringEncoding]]; /* when metadata corrupted, we should not find the item */ result = SecItemCopyMatching((__bridge CFDictionaryRef)dataQuery, &foundItem); @@ -421,7 +445,46 @@ static keyclass_t parse_keyclass(CFTypeRef value) { CFReleaseNull(foundItem); // Just calling SecItemCopyMatching shouldn't have created a new metadata key - [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:false]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:true value:[@"super bad key" dataUsingEncoding:NSUTF8StringEncoding]]; + + /* CopyMatching will delete corrupt pre-emptively */ + result = SecItemDelete((__bridge CFDictionaryRef)dataQuery); + XCTAssertEqual(result, -25300, @"corrupt item was not deleted for us"); +} + +- (void)testKeychainDeletionCopyMatching +{ + NSDictionary* item = @{ (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecValueData : [@"password" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecAttrAccount : @"TestAccount", + (id)kSecAttrService : @"TestService", + (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlocked, + (id)kSecUseDataProtectionKeychain : @YES }; + + OSStatus result = SecItemAdd((__bridge CFDictionaryRef)item, NULL); + XCTAssertEqual(result, 0, @"failed to add test item to keychain"); + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:true value:nil]; + + NSMutableDictionary* dataQuery = item.mutableCopy; + [dataQuery removeObjectForKey:(id)kSecValueData]; + dataQuery[(id)kSecReturnData] = @(YES); + + CFTypeRef foundItem = NULL; + + result = SecItemCopyMatching((__bridge CFDictionaryRef)dataQuery, &foundItem); + XCTAssertEqual(result, 0, @"failed to find the data for the item we just added in the keychain"); + CFReleaseNull(foundItem); + + [self deleteMetadataClassAKey]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:false value:nil]; + + /* when metadata corrupted, we should not find the item */ + result = SecItemCopyMatching((__bridge CFDictionaryRef)dataQuery, &foundItem); + XCTAssertEqual(result, errSecItemNotFound, @"failed to find the data for the item we just added in the keychain"); + CFReleaseNull(foundItem); + + // Just calling SecItemCopyMatching shouldn't have created a new metadata key + [self checkDatabaseExistenceOfMetadataKey:key_class_ak shouldExist:false value:nil]; /* CopyMatching will delete corrupt pre-emptively */ result = SecItemDelete((__bridge CFDictionaryRef)dataQuery); @@ -508,6 +571,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { self.allowDecryption = NO; NSDictionary* secretData = @{(id)kSecValueData : @"secret here"}; + CFDictionaryRef emptyDict = (__bridge CFDictionaryRef)@{}; ac = SecAccessControlCreate(NULL, &error); XCTAssertNotNil((__bridge id)ac, @"failed to create access control with error: %@", (__bridge id)error); @@ -515,16 +579,19 @@ static keyclass_t parse_keyclass(CFTypeRef value) { XCTAssertTrue(SecAccessControlSetProtection(ac, kSecAttrAccessibleWhenUnlocked, &error), @"failed to set access control protection with error: %@", error); XCTAssertNil((__bridge id)error, @"encountered error attempting to set access control protection: %@", (__bridge id)error); - XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, (__bridge CFDictionaryRef)@{}, NULL, &enc, true, &error), @"failed to encrypt data with error: %@", error); + XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, emptyDict, emptyDict, &enc, true, &error), @"failed to encrypt data with error: %@", error); XCTAssertTrue(enc != NULL, @"failed to get encrypted data from encryption function"); XCTAssertNil((__bridge id)error, @"encountered error attempting to encrypt data: %@", (__bridge id)error); CFReleaseNull(ac); CFMutableDictionaryRef attributes = NULL; uint32_t version = 0; + NSData* dummyACM = [NSData dataWithBytes:"dummy" length:5]; + const SecDbClass* class = kc_class_with_name(kSecClassGenericPassword); + NSArray* dummyArray = [NSArray array]; keyclass_t keyclass = 0; - XCTAssertNoThrow(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, NULL, enc, NULL, NULL, &attributes, &version, true, &keyclass, &error), @"unexpected exception when decryption fails"); + XCTAssertNoThrow(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, (__bridge CFDataRef _Nonnull)dummyACM, enc, class, (__bridge CFArrayRef)dummyArray, &attributes, &version, true, &keyclass, &error), @"unexpected exception when decryption fails"); XCTAssertEqual(keyclass, key_class_ak, @"failed to get back the keyclass when decryption failed"); self.allowDecryption = YES; @@ -744,18 +811,18 @@ static keyclass_t parse_keyclass(CFTypeRef value) { NSString* otherAccount = @"OtherAccount"; NSString* thirdAccount = @"ThirdAccount"; [self addTestItemExpecting:errSecSuccess account:testAccount accessible:(id)kSecAttrAccessibleAfterFirstUnlock]; - [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true]; - [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:false]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true value:nil]; + [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:false value:nil]; // This should fail, and not create a CKU metadata key [self addTestItemExpecting:errSecDuplicateItem account:testAccount accessible:(id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; - [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true]; - [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:false]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true value:nil]; + [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:false value:nil]; // But successfully creating a new CKU item should create the key [self addTestItemExpecting:errSecSuccess account:otherAccount accessible:(id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; - [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true]; - [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:true]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true value:nil]; + [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:true value:nil]; // Drop all metadata key caches [SecDbKeychainMetadataKeyStore resetSharedStore]; @@ -765,8 +832,8 @@ static keyclass_t parse_keyclass(CFTypeRef value) { // Adding another CKU item now should be fine [self addTestItemExpecting:errSecSuccess account:thirdAccount accessible:(id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; - [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true]; - [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:true]; + [self checkDatabaseExistenceOfMetadataKey:key_class_ck shouldExist:true value:nil]; + [self checkDatabaseExistenceOfMetadataKey:key_class_cku shouldExist:true value:nil]; // Drop all metadata key caches once more, to ensure we can find all three items from the persisted keys [SecDbKeychainMetadataKeyStore resetSharedStore]; @@ -796,6 +863,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { CFErrorRef error = NULL; NSDictionary* secretData = @{(id)kSecValueData : @"secret here"}; + CFDictionaryRef emptyDict = (__bridge CFDictionaryRef)@{}; ac = SecAccessControlCreate(NULL, &error); XCTAssertNotNil((__bridge id)ac, @"failed to create access control with error: %@", (__bridge id)error); @@ -803,7 +871,7 @@ static keyclass_t parse_keyclass(CFTypeRef value) { XCTAssertTrue(SecAccessControlSetProtection(ac, accessibility, &error), @"failed to set access control protection with error: %@", error); XCTAssertNil((__bridge id)error, @"encountered error attempting to set access control protection: %@", (__bridge id)error); - XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, (__bridge CFDictionaryRef)@{}, NULL, &enc, true, &error), @"failed to encrypt data with error: %@", error); + XCTAssertTrue(ks_encrypt_data(KEYBAG_DEVICE, ac, NULL, (__bridge CFDictionaryRef)secretData, emptyDict, emptyDict, &enc, true, &error), @"failed to encrypt data with error: %@", error); XCTAssertTrue(enc != NULL, @"failed to get encrypted data from encryption function"); XCTAssertNil((__bridge id)error, @"encountered error attempting to encrypt data: %@", (__bridge id)error); CFReleaseNull(ac); @@ -824,7 +892,11 @@ static keyclass_t parse_keyclass(CFTypeRef value) { XCTAssertNil((__bridge id)error, @"encountered error attempting to set access control protection: %@", (__bridge id)error); keyclass_t keyclass = 0; - XCTAssertTrue(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, NULL, (__bridge CFDataRef)encryptedData, NULL, NULL, &attributes, &version, false, &keyclass, &error), @"failed to decrypt data with error: %@", error); + NSData* dummyACM = [NSData dataWithBytes:"dummy" length:5]; + const SecDbClass* class = kc_class_with_name(kSecClassGenericPassword); + NSArray* dummyArray = [NSArray array]; + + XCTAssertTrue(ks_decrypt_data(KEYBAG_DEVICE, kAKSKeyOpDecrypt, &ac, (__bridge CFDataRef _Nonnull)dummyACM, (__bridge CFDataRef)encryptedData, class, (__bridge CFArrayRef)dummyArray, &attributes, &version, false, &keyclass, &error), @"failed to decrypt data with error: %@", error); XCTAssertNil((__bridge id)error, @"encountered error attempting to decrypt data: %@", (__bridge id)error); XCTAssertEqual(keyclass & key_class_last, parse_keyclass(accessibility), @"failed to get back the keyclass from decryption"); @@ -881,13 +953,27 @@ static keyclass_t parse_keyclass(CFTypeRef value) { __block CFErrorRef error = NULL; __block bool ok = true; ok &= kc_with_dbt(true, &error, ^bool(SecDbConnectionRef dbt) { - NSString* sql = [NSString stringWithFormat:@"UPDATE metadatakeys SET actualKeyclass = %d WHERE keyclass = %d", 0, key_class_ak]; - ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &error, ^(sqlite3_stmt* stmt) { - ok &= SecDbStep(dbt, stmt, &error, ^(bool* stop) { - // woohoo + if (checkV12DevEnabled()) { // item is in new format, turn it into an old format item + NSString* sql = [NSString stringWithFormat:@"SELECT metadatakeydata FROM metadatakeys WHERE keyclass = %d", key_class_ak]; + __block NSData* key; + ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &error, ^(sqlite3_stmt* stmt) { + ok &= SecDbStep(dbt, stmt, &error, ^(bool *stop) { + NSData* wrappedKey = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)]; + SecDbKeychainSerializedMetadataKey* mdkdata = [[SecDbKeychainSerializedMetadataKey alloc] initWithData:wrappedKey]; + key = mdkdata.akswrappedkey; + }); }); - }); - + sql = [NSString stringWithFormat:@"UPDATE metadatakeys SET actualKeyclass = 0, data = ?, metadatakeydata = ? WHERE keyclass = %d", key_class_ak]; + ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &error, ^(sqlite3_stmt *stmt) { + ok &= SecDbBindBlob(stmt, 1, key.bytes, key.length, SQLITE_TRANSIENT, &error); + ok &= SecDbStep(dbt, stmt, &error, NULL); + }); + } else { + NSString* sql = [NSString stringWithFormat:@"UPDATE metadatakeys SET actualKeyclass = %d WHERE keyclass = %d", 0, key_class_ak]; + ok &= SecDbPrepare(dbt, (__bridge CFStringRef)sql, &error, ^(sqlite3_stmt* stmt) { + ok &= SecDbStep(dbt, stmt, &error, NULL); + }); + } return ok; }); diff --git a/secdxctests/KeychainEntitlementsTest.m b/secdxctests/KeychainEntitlementsTest.m index d5be9242..b72a6c5d 100644 --- a/secdxctests/KeychainEntitlementsTest.m +++ b/secdxctests/KeychainEntitlementsTest.m @@ -23,6 +23,7 @@ #import #import +#import #import "KeychainXCTest.h" @@ -39,7 +40,18 @@ // Application with no keychain-related entitlements at all, but CopyMatching must work in order to support // backward compatibility with smart-card-enabled macos applications (com.apple.token AG is added automatically in this case). [self setEntitlements:@{} validated:false]; - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { +#if TARGET_OS_OSX + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); +#else + // On non-macOS targets, token items must be explicitly enabled, and that requires entitlements. + // But since this test has no entitlements, it will always fail with errSecMissingEntitlement. + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecMissingEntitlement); +#endif + } else { + // If tokens are not enabled, this situation really means that there is an entitlement problem. + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecMissingEntitlement); + } // However, write access is declined for such application. XCTAssertEqual(SecItemAdd((CFDictionaryRef)params, NULL), errSecMissingEntitlement); @@ -120,8 +132,12 @@ (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrLabel: @"label", (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken, }; - [self setEntitlements:@{ @"com.apple.application-identifier": (id)kSecAttrAccessGroupToken } validated:YES]; - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + [self setEntitlements:@{ @"keychain-access-groups": @[ (id)kSecAttrAccessGroupToken ] } validated:YES]; + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + } else { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecMissingEntitlement); + } XCTAssertEqual(SecItemAdd((CFDictionaryRef)params, NULL), errSecMissingEntitlement); XCTAssertEqual(SecItemDelete((CFDictionaryRef)params), errSecMissingEntitlement); } @@ -134,8 +150,12 @@ (id)kSecAttrLabel: @"label", }; [self setEntitlements:@{ @"com.apple.security.application-groups": @[@"com.apple.test-app-groups"] } validated:NO]; - // Invalid access group entitlement should still allow querying com.apple.token - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + // Invalid access group entitlement should still allow querying com.apple.token, if tokens are enabled + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + } else { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecMissingEntitlement); + } // But write-access is forbidden, XCTAssertEqual(SecItemAdd((CFDictionaryRef)params, NULL), errSecMissingEntitlement); @@ -150,47 +170,66 @@ XCTAssertEqual(SecItemAdd((CFDictionaryRef)params, NULL), errSecMissingEntitlement); XCTAssertEqual(SecItemDelete((CFDictionaryRef)params), errSecMissingEntitlement); - // Explicitly referring to com.apple.token should work fine too. params = @{ (id)kSecUseDataProtectionKeychain: @YES, (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrLabel: @"label", (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken, }; - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + } else { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecMissingEntitlement); + } } #endif // TARGET_OS_OSX - (void)testTokenItemsGroup { NSDictionary *params; + [self setEntitlements:@{ +#if TARGET_OS_OSX + @"com.apple.application-identifier": @"com.apple.test-app-identifier", +#else + @"application-identifier": @"com.apple.test-app-identifier", +#endif + @"keychain-access-groups": @[ @"com.apple.token" ], + } validated:YES]; + // Add token items for testing into the keychain. NSArray *tokenItems = @[ @{ (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken, (id)kSecAttrLabel: @"label", } ]; - XCTAssertEqual(SecItemUpdateTokenItems(@"com.apple.testtoken", (__bridge CFArrayRef)tokenItems), errSecSuccess); - - [self setEntitlements:@{ @"com.apple.application-identifier": @"com.apple.test-app-identifier" } validated:YES]; + XCTAssertEqual(SecItemUpdateTokenItemsForAccessGroups(@"com.apple.testtoken", (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], (__bridge CFArrayRef)tokenItems), errSecSuccess); - // Query without explicit access group, should find item on macOS and not find it on iOS. + // Query should find items, because we have token access group in entitlements. params = @{ (id)kSecUseDataProtectionKeychain: @YES, (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrLabel: @"label", }; + if (os_feature_enabled(CryptoTokenKit, UseTokens)) { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecSuccess); + } else { + XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); + } + #if TARGET_OS_IPHONE + // Not having access group in entitlements will not find items. + [self setEntitlements:@{ + @"application-identifier": @"com.apple.test-app-identifier", + } validated:YES]; XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecItemNotFound); -#else - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecSuccess); #endif - // Query with explicit AG should work the same on both platforms. - params = @{ (id)kSecUseDataProtectionKeychain: @YES, - (id)kSecClass: (id)kSecClassGenericPassword, - (id)kSecAttrLabel: @"label", - (id)kSecAttrAccessGroup: (id)kSecAttrAccessGroupToken, }; - XCTAssertEqual(SecItemCopyMatching((CFDictionaryRef)params, NULL), errSecSuccess); - // Delete all test token items. - SecItemUpdateTokenItems(@"com.apple.testtoken", (__bridge CFArrayRef)@[]); + [self setEntitlements:@{ +#if TARGET_OS_OSX + @"com.apple.application-identifier": @"com.apple.test-app-identifier", +#else + @"application-identifier": @"com.apple.test-app-identifier", +#endif + @"keychain-access-groups": @[ @"com.apple.token" ], + } validated:YES]; + SecItemUpdateTokenItemsForAccessGroups(@"com.apple.testtoken", (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], (__bridge CFArrayRef)@[]); } - (void)testEntitlementForExplicitAccessGroupLacking { diff --git a/secdxctests/KeychainXCTest.h b/secdxctests/KeychainXCTest.h index 4e1e27d9..4335da6a 100644 --- a/secdxctests/KeychainXCTest.h +++ b/secdxctests/KeychainXCTest.h @@ -48,7 +48,7 @@ typedef enum { @property keyclass_t keyclassUsedForAKSDecryption; @property SFAESKeySpecifier* keySpecifier; -@property SFAESKey* fakeAKSKey; +@property NSData* fakeAKSKey; @property id keychainPartialMock; @@ -56,7 +56,7 @@ typedef enum { - (void)setEntitlements:(NSDictionary *)entitlements validated:(BOOL)validated; -- (NSData*)getDatabaseKeyDataithError:(NSError**)error; +- (NSData*)getDatabaseKeyDataWithError:(NSError**)error; @end diff --git a/secdxctests/KeychainXCTest.m b/secdxctests/KeychainXCTest.m index bab2a47c..1ac55ceb 100644 --- a/secdxctests/KeychainXCTest.m +++ b/secdxctests/KeychainXCTest.m @@ -27,6 +27,7 @@ #import "CKKS.h" #import "SecDbKeychainItemV7.h" #import "SecDbKeychainMetadataKeyStore.h" +#import "SecDbBackupManager_Internal.h" #import "SecAKSObjCWrappers.h" #import "SecItemPriv.h" #import "SecTaskPriv.h" @@ -44,6 +45,19 @@ #import #import #import +#include +#include +#include +#include +#include +#include "CheckV12DevEnabled.h" + +void* testlist = NULL; + +// TODO: Switch to '1' closer to deployment, but leave at '0' for now to test not breaking people +static int testCheckV12DevEnabled(void) { + return 0; +} #if USE_KEYSTORE @@ -118,6 +132,7 @@ @implementation KeychainXCTest { id _keychainPartialMock; CFArrayRef _originalAccessGroups; + bool _simcrashenabled; } @synthesize keychainPartialMock = _keychainPartialMock; @@ -125,14 +140,16 @@ + (void)setUp { [super setUp]; - SecCKKSDisable(); + // Do not want test code to be allowed to init real keychain! + secd_test_setup_temp_keychain("keychaintestthrowaway", NULL); securityd_init(NULL); } - (void)setUp { - __security_simulatecrash_enable(true); + _simcrashenabled = __security_simulatecrash_enabled(); + __security_simulatecrash_enable(false); [super setUp]; @@ -146,8 +163,6 @@ self.keySpecifier = [[SFAESKeySpecifier alloc] initWithBitSize:SFAESKeyBitSize256]; [self setNewFakeAKSKey:[NSData dataWithBytes:"1234567890123456789012345678901" length:32]]; - - [SecDbKeychainMetadataKeyStore resetSharedStore]; self.mockSecDbKeychainItemV7 = OCMClassMock([SecDbKeychainItemV7 class]); [[[self.mockSecDbKeychainItemV7 stub] andCall:@selector(decryptionOperation) onObject:self] decryptionOperation]; @@ -162,18 +177,28 @@ id refKeyMock = OCMClassMock([SecAKSRefKey class]); [[[refKeyMock stub] andCall:@selector(alloc) onObject:[FakeAKSRefKey class]] alloc]; + checkV12DevEnabled = testCheckV12DevEnabled; NSArray* partsOfName = [self.name componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" ]"]]; + // Calls SecKeychainDbReset which also resets metadata keys and backup manager secd_test_setup_temp_keychain([partsOfName[1] UTF8String], NULL); _originalAccessGroups = SecAccessGroupsGetCurrent(); + SecResetLocalSecuritydXPCFakeEntitlements(); } - (void)tearDown { [self.mockSecDbKeychainItemV7 stopMocking]; [self.mockSecAKSObjCWrappers stopMocking]; + [self resetEntitlements]; SecAccessGroupsSetCurrent(_originalAccessGroups); + __security_simulatecrash_enable(_simcrashenabled); + + [super tearDown]; +} ++ (void)tearDown { + SecResetLocalSecuritydXPCFakeEntitlements(); [super tearDown]; } @@ -189,13 +214,52 @@ - (bool)setNewFakeAKSKey:(NSData*)newKeyData { - NSError* error = nil; - self.fakeAKSKey = [[SFAESKey alloc] initWithData:newKeyData specifier:self.keySpecifier error:&error]; - XCTAssertNil(error, "Should be no error making a fake AKS key"); - XCTAssertNotNil(self.fakeAKSKey, "Should have received a fake AKS key"); + self.fakeAKSKey = newKeyData; return true; } +- (NSData*)wrapKey:(NSData*)plaintextKey withKey:(NSData*)wrappingKey +{ + const struct ccmode_ecb *ecb_mode = ccaes_ecb_encrypt_mode(); + ccecb_ctx_decl(ccecb_context_size(ecb_mode), key); + NSMutableData* wrappedKey = [NSMutableData dataWithLength:ccwrap_wrapped_size(plaintextKey.length)]; + + ccecb_init(ecb_mode, key, wrappingKey.length, wrappingKey.bytes); + + size_t obytes = 0; + int wrap_status = ccwrap_auth_encrypt(ecb_mode, key, plaintextKey.length, plaintextKey.bytes, + &obytes, wrappedKey.mutableBytes); + if (wrap_status == 0) { + assert(obytes == wrappedKey.length); + } else { + wrappedKey = nil; + } + + ccecb_ctx_clear(ccecb_context_size(ecb_mode), key); + return wrappedKey; +} + +- (NSData*)unwrapKey:(NSData*)ciphertextKey withKey:(NSData*)wrappingKey +{ + const struct ccmode_ecb *ecb_mode = ccaes_ecb_decrypt_mode(); + ccecb_ctx_decl(ccecb_context_size(ecb_mode), key); + NSMutableData *unwrappedKey = [NSMutableData dataWithLength:ccwrap_unwrapped_size(ciphertextKey.length)]; + + ccecb_init(ecb_mode, key, wrappingKey.length, wrappingKey.bytes); + + size_t obytes = 0; + int status = ccwrap_auth_decrypt(ecb_mode, key, ciphertextKey.length, ciphertextKey.bytes, + &obytes, unwrappedKey.mutableBytes); + if (status == 0) { + assert(obytes == (size_t)[unwrappedKey length]); + } else { + unwrappedKey = nil; + } + + ccecb_ctx_clear(ccecb_context_size(ecb_mode), key); + return unwrappedKey; +} + - (bool)fakeAKSEncryptWithKeybag:(keybag_handle_t)keybag keyclass:(keyclass_t)keyclass plaintext:(NSData*)plaintext @@ -209,36 +273,25 @@ } return false; } - - uint32_t keyLength = (uint32_t)plaintext.length; - const uint8_t* keyBytes = plaintext.bytes; - - NSData* dataToEncrypt = [NSData dataWithBytes:keyBytes length:keyLength]; - NSError* localError = nil; - - SFAuthenticatedEncryptionOperation* encryptionOperation = [[SFAuthenticatedEncryptionOperation alloc] initWithKeySpecifier:self.keySpecifier]; - encryptionOperation.authenticationCodeLength = 8; - SFAuthenticatedCiphertext* ciphertext = [encryptionOperation encrypt:dataToEncrypt withKey:self.fakeAKSKey error:&localError]; - - if (error) { - *error = localError; + + if (keybag == KEYBAG_DEVICE) { + XCTAssertLessThanOrEqual(ciphertextOut.length, APPLE_KEYSTORE_MAX_SYM_WRAPPED_KEY_LEN); + } else { // this'll do for now: assume non-device bags are asymmetric backup bags + XCTAssertLessThanOrEqual(ciphertextOut.length, APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN); } - if (ciphertext) { - void* wrappedKeyMutableBytes = ciphertextOut.mutableBytes; - memcpy(wrappedKeyMutableBytes, ciphertext.ciphertext.bytes, 32); - memcpy(wrappedKeyMutableBytes + 32, ciphertext.initializationVector.bytes, 32); - memcpy(wrappedKeyMutableBytes + 64, ciphertext.authenticationCode.bytes, 8); - + NSData* wrappedKey = [self wrapKey:plaintext withKey:self.fakeAKSKey]; + if (ciphertextOut.length >= wrappedKey.length) { + memcpy(ciphertextOut.mutableBytes, wrappedKey.bytes, wrappedKey.length); + ciphertextOut.length = wrappedKey.length; // simulate ks_crypt behavior if (self.simulateRolledAKSKey && outKeyclass) { *outKeyclass = keyclass | (key_class_last + 1); } else if (outKeyclass) { *outKeyclass = keyclass; } - return true; - } - else { + } else { + XCTFail(@"output buffer too small for wrapped key"); return false; } } @@ -261,49 +314,30 @@ // let's make decryption fail like it would if this were an old metadata key entry made with a generational AKS key, but we didn't store that info in the database return false; } - - const uint8_t* wrappedKeyBytes = ciphertextIn.bytes; - - NSData* ciphertextData = [NSData dataWithBytes:wrappedKeyBytes length:32]; - NSData* ivData = [NSData dataWithBytes:wrappedKeyBytes + 32 length:32]; - NSData* authCodeData = [NSData dataWithBytes:wrappedKeyBytes + 64 length:8]; - SFAuthenticatedCiphertext* ciphertext = [[SFAuthenticatedCiphertext alloc] initWithCiphertext:ciphertextData authenticationCode:authCodeData initializationVector:ivData]; - - NSError* localError = nil; - - SFAuthenticatedEncryptionOperation* encryptionOperation = [[SFAuthenticatedEncryptionOperation alloc] initWithKeySpecifier:self.keySpecifier]; - encryptionOperation.authenticationCodeLength = 8; - NSData* decryptedData = [encryptionOperation decrypt:ciphertext withKey:self.fakeAKSKey error:&localError]; - - // in real securityd, we go through AKS rather than SFCryptoServices - // we need to translate the error for proper handling - if ([localError.domain isEqualToString:SFCryptoServicesErrorDomain] && localError.code == SFCryptoServicesErrorDecryptionFailed) { - if (!self.simulateRolledAKSKey && keyclass > key_class_last) { - // for this case we want to simulate what happens when we try decrypting with a rolled keyclass on a device which has never been rolled, which is it ends up with a NotPermitted error from AKS which the security layer translates as locked keybag - localError = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecInteractionNotAllowed userInfo:nil]; - } - else { - localError = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecDecode userInfo:nil]; - } - } - - if (error) { - *error = localError; - } - + self.keyclassUsedForAKSDecryption = keyclass; - if (decryptedData && decryptedData.length <= plaintext.length) { - memcpy(plaintext.mutableBytes, decryptedData.bytes, decryptedData.length); - plaintext.length = decryptedData.length; + NSData* unwrappedKey = [self unwrapKey:ciphertextIn withKey:self.fakeAKSKey]; + if (unwrappedKey && plaintext.length >= unwrappedKey.length) { + memcpy(plaintext.mutableBytes, unwrappedKey.bytes, unwrappedKey.length); + plaintext.length = unwrappedKey.length; // simulate ks_crypt behavior self.didAKSDecrypt = YES; return true; - } - else { + } else if (unwrappedKey) { + XCTFail(@"output buffer too small for unwrapped key"); + return false; + } else { + if (error && !self.simulateRolledAKSKey && keyclass > key_class_last) { + // for this case we want to simulate what happens when we try decrypting with a rolled keyclass on a device which has never been rolled, which is it ends up with a NotPermitted error from AKS which the security layer translates as locked keybag + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecInteractionNotAllowed userInfo:nil]; + } + else if (error) { + *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:errSecDecode userInfo:nil]; + } return false; } } -- (NSData*)getDatabaseKeyDataithError:(NSError**)error +- (NSData*)getDatabaseKeyDataWithError:(NSError**)error { if (_lockState == LockStateUnlocked) { return [NSData dataWithBytes:"1234567890123456789012345678901" length:32]; @@ -319,8 +353,7 @@ // Mock SecTask entitlement retrieval API, so that we can test access group entitlement parsing code in SecTaskCopyAccessGroups() static NSDictionary *currentEntitlements = nil; -static BOOL currentEntitlementsValidated = false; -static NSArray *currentAccessGroups = nil; +static BOOL currentEntitlementsValidated = YES; CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlement, CFErrorRef *error) { id value = currentEntitlements[(__bridge id)entitlement]; @@ -338,8 +371,13 @@ Boolean SecTaskEntitlementsValidated(SecTaskRef task) { currentEntitlements = entitlements; currentEntitlementsValidated = validated; id task = CFBridgingRelease(SecTaskCreateFromSelf(kCFAllocatorDefault)); - currentAccessGroups = CFBridgingRelease(SecTaskCopyAccessGroups((__bridge SecTaskRef)task)); - SecAccessGroupsSetCurrent((__bridge CFArrayRef)currentAccessGroups); + NSArray *currentAccessGroups = CFBridgingRelease(SecTaskCopyAccessGroups((__bridge SecTaskRef)task)); + SecAccessGroupsSetCurrent((__bridge CFArrayRef)currentAccessGroups); // SetCurrent retains the access groups +} + +- (void)resetEntitlements { + currentEntitlements = nil; + currentEntitlementsValidated = YES; } @end diff --git a/secdxctests/SFCredentialStoreTests.m b/secdxctests/SFCredentialStoreTests.m index 62aa116e..cda02311 100644 --- a/secdxctests/SFCredentialStoreTests.m +++ b/secdxctests/SFCredentialStoreTests.m @@ -121,7 +121,7 @@ { [super setUp]; self.keychainPartialMock = OCMPartialMock([(SFKeychainServer*)[[self.class serverProxyWithError:nil] server] _keychain]); - [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; + [[[[self.keychainPartialMock stub] andCall:@selector(getDatabaseKeyDataWithError:) onObject:self] ignoringNonObjectArgs] _onQueueGetDatabaseKeyDataWithError:NULL]; _credentialStore = [[SFCredentialStore alloc] _init]; } diff --git a/secdxctests/secdxctests-entitlements.plist b/secdxctests/secdxctests-entitlements.plist new file mode 100644 index 00000000..0614e949 --- /dev/null +++ b/secdxctests/secdxctests-entitlements.plist @@ -0,0 +1,33 @@ + + + + + com.apple.application-identifier + com.apple.secdxctests + application-identifier + com.apple.secdxctests + com.apple.keystore.access-keychain-keys + + com.apple.keystore.lockassertion + + com.apple.private.associated-domains + + com.apple.private.necp.match + + com.apple.mkb.usersession.info + + seatbelt-profiles + + securityd + + com.apple.security.app-sandbox + + com.apple.security.get-task-allow + + keychain-access-groups + + SecDbBackupManager-UnitTests + + + + diff --git a/sectask/SecEntitlements.h b/sectask/SecEntitlements.h index 9dd2005d..46b854ff 100644 --- a/sectask/SecEntitlements.h +++ b/sectask/SecEntitlements.h @@ -47,10 +47,11 @@ __BEGIN_DECLS Note that iOS and macOS uses different value for the same constant. */ +#define kSecEntitlementAppleApplicationIdentifier CFSTR("com.apple.application-identifier") +#define kSecEntitlementBasicApplicationIdentifier CFSTR("application-identifier") #if TARGET_OS_IPHONE -#define kSecEntitlementApplicationIdentifier CFSTR("application-identifier") +#define kSecEntitlementApplicationIdentifier kSecEntitlementBasicApplicationIdentifier #else -#define kSecEntitlementAppleApplicationIdentifier CFSTR("com.apple.application-identifier") #define kSecEntitlementApplicationIdentifier kSecEntitlementAppleApplicationIdentifier #endif @@ -151,6 +152,9 @@ __BEGIN_DECLS /* Entitlement to allow use of CKKS plaintext fields */ #define kSecEntitlementPrivateCKKSPlaintextFields CFSTR("com.apple.private.ckks.plaintextfields") +/* Entitlement to allow use of inet expansion fields */ +#define kSecEntitlementPrivateInetExpansionFields CFSTR("com.apple.private.keychain.inet_expansion_fields") + /* Entitlement to allow use of CKKS 'current item' changing SPI */ #define kSecEntitlementPrivateCKKSWriteCurrentItemPointers CFSTR("com.apple.private.ckks.currentitempointers_write") @@ -165,12 +169,24 @@ __BEGIN_DECLS /* Entitlement to allow executing keychain control actions */ #define kSecEntitlementKeychainControl CFSTR("com.apple.private.keychain.keychaincontrol") +/* Entitlement to allow deletion of app clip keychain items */ +#define kSecEntitlementPrivateAppClipDeletion CFSTR("com.apple.private.keychain.appclipdeletion") + +/* Entitlements to allow executing SecItemUpdateTokenItemsForAccessGroups SPI */ +#define kSecEntitlementUpdateTokenItems CFSTR("com.apple.private.keychain.allow-update-tokens") + +/* Entitlement to control access to login keychain master key stashing (loginwindow) */ +#define kSecEntitlementPrivateStash CFSTR("com.apple.private.securityd.stash") + #if __OBJC__ /* Entitlement to control use of OT */ #define kSecEntitlementPrivateOctagon @"com.apple.private.octagon" /* Entitlement to control use of Escrow Update */ #define kSecEntitlementPrivateEscrowRequest @"com.apple.private.escrow-update" + +/* Entitlement for macOS securityd to connect to stash agent */ +#define kSecEntitlementPrivateStashService @"com.apple.private.securityd.stash-agent-client" #endif __END_DECLS diff --git a/sectask/SecTask.c b/sectask/SecTask.c index a73416c7..4b38f13d 100644 --- a/sectask/SecTask.c +++ b/sectask/SecTask.c @@ -25,6 +25,7 @@ #include "SecTaskPriv.h" #include +#include #include #include @@ -237,46 +238,44 @@ static bool SecTaskLoadEntitlements(SecTaskRef task, CFErrorRef *error) uint32_t bufferlen; int ret; - ret = csops_task(task, CS_OPS_ENTITLEMENTS_BLOB, &header, sizeof(header)); /* Any other combination means no entitlements */ - if (ret == -1) { - if (errno != ERANGE) { + if (ret == -1) { + if (errno != ERANGE) { int entitlementErrno = errno; - uint32_t cs_flags = -1; + uint32_t cs_flags = -1; if (-1 == csops_task(task, CS_OPS_STATUS, &cs_flags, sizeof(cs_flags))) { syslog(LOG_NOTICE, "Failed to get cs_flags, error=%d", errno); } - if (cs_flags != 0) { // was signed - - pid_t pid; - audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL); - syslog(LOG_NOTICE, "SecTaskLoadEntitlements failed error=%d cs_flags=%x, pid=%d", entitlementErrno, cs_flags, pid); // to ease diagnostics - - CFStringRef description = SecTaskCopyDebugDescription(task); - char *descriptionBuf = NULL; - CFIndex descriptionSize = CFStringGetLength(description) * 4; - descriptionBuf = (char *)malloc(descriptionSize); - if (!CFStringGetCString(description, descriptionBuf, descriptionSize, kCFStringEncodingUTF8)) { - descriptionBuf[0] = 0; - } - - syslog(LOG_NOTICE, "SecTaskCopyDebugDescription: %s", descriptionBuf); - CFReleaseNull(description); - free(descriptionBuf); - } - task->lastFailure = entitlementErrno; // was overwritten by csops_task(CS_OPS_STATUS) above - - // EINVAL is what the kernel says for unsigned code, so we'll have to let that pass - if (entitlementErrno == EINVAL) { - task->entitlementsLoaded = true; - return true; - } - ret = entitlementErrno; // what really went wrong - goto out; // bail out - } + if (cs_flags != 0) { // was signed + pid_t pid; + audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL); + syslog(LOG_NOTICE, "SecTaskLoadEntitlements failed error=%d cs_flags=%x, pid=%d", entitlementErrno, cs_flags, pid); // to ease diagnostics + + CFStringRef description = SecTaskCopyDebugDescription(task); + char *descriptionBuf = NULL; + CFIndex descriptionSize = CFStringGetLength(description) * 4; + descriptionBuf = (char *)malloc(descriptionSize); + if (!CFStringGetCString(description, descriptionBuf, descriptionSize, kCFStringEncodingUTF8)) { + descriptionBuf[0] = 0; + } + + syslog(LOG_NOTICE, "SecTaskCopyDebugDescription: %s", descriptionBuf); + CFReleaseNull(description); + free(descriptionBuf); + } + task->lastFailure = entitlementErrno; // was overwritten by csops_task(CS_OPS_STATUS) above + + // EINVAL is what the kernel says for unsigned code, so we'll have to let that pass + if (entitlementErrno == EINVAL) { + task->entitlementsLoaded = true; + return true; + } + ret = entitlementErrno; // what really went wrong + goto out; // bail out + } bufferlen = ntohl(header.length); /* check for insane values */ if (bufferlen > 1024 * 1024 || bufferlen < 8) { @@ -298,10 +297,17 @@ static bool SecTaskLoadEntitlements(SecTaskRef task, CFErrorRef *error) entitlements = (CFMutableDictionaryRef) CFPropertyListCreateWithData(kCFAllocatorDefault, data, kCFPropertyListMutableContainers, NULL, error); CFReleaseNull(data); - if((entitlements==NULL) || (CFGetTypeID(entitlements)!=CFDictionaryGetTypeID())){ + if ((entitlements==NULL) || (CFGetTypeID(entitlements)!=CFDictionaryGetTypeID())){ ret = EDOM; // don't use EINVAL here; it conflates problems with syscall error returns goto out; } + + bool entitlementsModified = updateCatalystEntitlements(entitlements); + if (entitlementsModified) { + pid_t pid; + audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL); + secinfo("SecTask", "Fixed catalyst entitlements for process %d", pid); + } } task->entitlements = entitlements ? CFRetain(entitlements) : NULL; diff --git a/sectask/SecTask.h b/sectask/SecTask.h index c1bf28a0..5a14de3c 100644 --- a/sectask/SecTask.h +++ b/sectask/SecTask.h @@ -127,7 +127,7 @@ CFStringRef SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error); */ uint32_t SecTaskGetCodeSignStatus(SecTaskRef task) - API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0), iosmac(11.0)) SPI_AVAILABLE(macos(10.5)); + API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0), macCatalyst(11.0)) SPI_AVAILABLE(macos(10.5)); CF_IMPLICIT_BRIDGING_DISABLED diff --git a/sectask/SystemEntitlements.h b/sectask/SystemEntitlements.h new file mode 100644 index 00000000..c8544290 --- /dev/null +++ b/sectask/SystemEntitlements.h @@ -0,0 +1,17 @@ +#ifndef SystemEntitlements_h +#define SystemEntitlements_h + +/* + This file collects entitlements defined on the platform and in use by Security. + */ + +#include + +__BEGIN_DECLS + +/* Entitlement denoting client task is an App Clip */ +#define kSystemEntitlementOnDemandInstallCapable CFSTR("com.apple.developer.on-demand-install-capable") + +__END_DECLS + +#endif /* SystemEntitlements_h */ diff --git a/securityd/etc/com.apple.securityd.sb b/securityd/etc/com.apple.securityd.sb index 26672e55..1045cdb8 100644 --- a/securityd/etc/com.apple.securityd.sb +++ b/securityd/etc/com.apple.securityd.sb @@ -50,7 +50,8 @@ (global-name "com.apple.PowerManagement.control") (global-name "com.apple.security.syspolicy") (global-name "com.apple.security.agent") - (global-name "com.apple.security.agent.login")) + (global-name "com.apple.security.agent.login") + (global-name "com.apple.security.KeychainStasher")) (allow ipc-posix-shm (ipc-posix-name "com.apple.AppleDatabaseChanged") diff --git a/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj b/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj index 43ebb292..4d89a2bc 100644 --- a/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj +++ b/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj @@ -347,7 +347,7 @@ 189D462D166AC95C001D8533 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1120; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = Apple; }; buildConfigurationList = 189D4630166AC95C001D8533 /* Build configuration list for PBXProject "securityd_service" */; @@ -433,7 +433,7 @@ 1843240F1714797D00196B52 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++2a"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -441,7 +441,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; COMBINE_HIDPI_IMAGES = YES; EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu2x; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -455,7 +455,7 @@ 184324101714797D00196B52 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++2a"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -464,7 +464,7 @@ COMBINE_HIDPI_IMAGES = YES; ENABLE_NS_ASSERTIONS = NO; EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu2x; GCC_WARN_UNDECLARED_SELECTOR = YES; INSTALL_PATH = /usr/local/lib; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -619,14 +619,14 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = /usr/libexec/UserEventAgent; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++2a"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu2x; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -644,7 +644,7 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = /usr/libexec/UserEventAgent; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++2a"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -652,7 +652,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; COMBINE_HIDPI_IMAGES = YES; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu2x; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; diff --git a/securityd/securityd_service/securityd_service/main.c b/securityd/securityd_service/securityd_service/main.c index 496e3a05..be7d6e0e 100644 --- a/securityd/securityd_service/securityd_service/main.c +++ b/securityd/securityd_service/securityd_service/main.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -1356,9 +1356,7 @@ bool check_signature(xpc_connection_t connection) { #if !(DEBUG || RC_BUILDIT_YES) audit_token_t token; - xpc_connection_get_audit_token(connection, &token); - SecTaskRef task = SecTaskCreateWithAuditToken(NULL, token); if (task == NULL) { os_log(OS_LOG_DEFAULT, "failed getting SecTaskRef of the client"); @@ -1368,7 +1366,6 @@ bool check_signature(xpc_connection_t connection) uint32_t flags = SecTaskGetCodeSignStatus(task); /* check if valid and platform binary, but not platform path */ - if ((flags & (CS_VALID | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) != (CS_VALID | CS_PLATFORM_BINARY)) { if (SecIsInternalRelease()) { if ((flags & (CS_DEBUGGED | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) != (CS_DEBUGGED | CS_PLATFORM_BINARY)) { @@ -1383,18 +1380,19 @@ bool check_signature(xpc_connection_t connection) } } - CFStringRef signingIdentity = SecTaskCopySigningIdentifier(task, NULL); + CFStringRef signingIdentifier = SecTaskCopySigningIdentifier(task, NULL); CFRelease(task); - if (signingIdentity == NULL) { - os_log(OS_LOG_DEFAULT, "client have no code sign identity"); + if (signingIdentifier == NULL) { + os_log(OS_LOG_DEFAULT, "client has no code signing identifier"); return false; } - bool res = CFEqual(signingIdentity, CFSTR("com.apple.securityd")); - CFRelease(signingIdentity); + bool res = CFEqual(signingIdentifier, CFSTR("com.apple.securityd")); + CFRelease(signingIdentifier); - if (!res) - os_log(OS_LOG_DEFAULT, "client is not not securityd"); + if (!res) { + os_log(OS_LOG_DEFAULT, "client is not securityd"); + } return res; #else diff --git a/securityd/securityd_service/securityd_service/securityd_service_client.c b/securityd/securityd_service/securityd_service/securityd_service_client.c index fa8f8a10..ab0c1b1c 100644 --- a/securityd/securityd_service/securityd_service/securityd_service_client.c +++ b/securityd/securityd_service/securityd_service/securityd_service_client.c @@ -325,7 +325,7 @@ done: } int -service_client_stash_get_key(service_context_t *context, void ** key, int * key_len) +service_client_stash_get_key(service_context_t *context, void ** key, size_t * key_len) { int rc = KB_GeneralError; xpc_object_t message = NULL; @@ -347,7 +347,7 @@ service_client_stash_get_key(service_context_t *context, void ** key, int * key_ if (data) { *key = calloc(1u, data_len); memcpy(*key, data, data_len); - *key_len = (int)data_len; + *key_len = data_len; } } diff --git a/securityd/securityd_service/securityd_service/securityd_service_client.h b/securityd/securityd_service/securityd_service/securityd_service_client.h index 293216fc..bd8f8c4d 100644 --- a/securityd/securityd_service/securityd_service/securityd_service_client.h +++ b/securityd/securityd_service/securityd_service/securityd_service_client.h @@ -44,7 +44,7 @@ int service_client_kb_unwrap_key(service_context_t *context, const void *wrapped int service_client_stash_set_key(service_context_t *context, const void * key, int key_len); int service_client_stash_load_key(service_context_t *context, const void * key, int key_len); -int service_client_stash_get_key(service_context_t *context, void ** key, int * key_len); +int service_client_stash_get_key(service_context_t *context, void ** key, size_t * key_len); #if defined(__cplusplus) } diff --git a/securityd/src/ccaudit_extensions.cpp b/securityd/src/ccaudit_extensions.cpp index 155c8072..eb061d35 100644 --- a/securityd/src/ccaudit_extensions.cpp +++ b/securityd/src/ccaudit_extensions.cpp @@ -8,7 +8,7 @@ */ #include -#include +#include #include // vsnprintf() #include // va_start(), et al. #include diff --git a/securityd/src/credential.cpp b/securityd/src/credential.cpp index fbd703a1..3da55c7f 100644 --- a/securityd/src/credential.cpp +++ b/securityd/src/credential.cpp @@ -132,10 +132,11 @@ CredentialImpl::merge(const CredentialImpl &other) { // try to ensure that the credentials are the same type assert(mRight == other.mRight); - if (mRight) + if (mRight) { assert(mName == other.mName); - else + } else { assert(mUid == other.mUid); + } if (other.mValid && (!mValid || mCreationTime < other.mCreationTime)) { diff --git a/securityd/src/kcdatabase.cpp b/securityd/src/kcdatabase.cpp index 170a43cf..bcdec021 100644 --- a/securityd/src/kcdatabase.cpp +++ b/securityd/src/kcdatabase.cpp @@ -37,6 +37,10 @@ // is locked or when the Session dies, whichever happens earlier. // There is (as yet) no global-scope Database object for Keychain databases. // + +#define __STDC_WANT_LIB_EXT1__ 1 +#include + #include "kcdatabase.h" #include "agentquery.h" #include "kckey.h" @@ -44,6 +48,7 @@ #include "session.h" #include "notifications.h" #include "SecRandom.h" +#include "keychainstasherinterface.h" #include // @@@ 4003540 workaround #include // for default owner ACLs #include @@ -875,32 +880,66 @@ void KeychainDatabase::makeUnlocked(const AccessCredentials *cred, bool unlockKe assert(mValidData); } -// -// Invoke the securityd_service to retrieve the keychain master -// key from the AppleFDEKeyStore. -// +/** + Invoke securityd_service to load the keybag and retrieve the masterkey. + Also load masterkey from KeychainStasher and compare to make sure new stash works properly + */ void KeychainDatabase::stashDbCheck() -{ +{ + secnotice("KCdb", "Loading stashed key"); CssmAutoData masterKey(Allocator::standard(Allocator::sensitive)); CssmAutoData encKey(Allocator::standard(Allocator::sensitive)); - // Fetch the key - int rc = 0; - void * stash_key = NULL; - int stash_key_len = 0; + // We're going to double-load during transition + void* s_key = NULL; + size_t s_keylen = 0; service_context_t context = common().session().get_current_service_context(); - rc = service_client_stash_get_key(&context, &stash_key, &stash_key_len); - if (rc == 0) { - if (stash_key) { - masterKey.copy(CssmData((void *)stash_key,stash_key_len)); - memset(stash_key, 0, stash_key_len); - free(stash_key); - } + // SIDE EFFECT: loads the user's keybag + int servicerc = service_client_stash_get_key(&context, &s_key, &s_keylen); + if (servicerc != KB_Success) { + secerror("KCdb: failed to load stash from securityd_service: %d", servicerc); } else { - secnotice("KCdb", "failed to get stash from securityd_service: %d", (int)rc); - CssmError::throwMe(rc); + secnotice("KCdb", "securityd_service claims get_key success"); } - + + void* a_key = NULL; + size_t a_keylen = 0; + OSStatus agentrc = loadKeyFromStashAgent(common().session().originatorUid(), &a_key, &a_keylen); + if (agentrc != errSecSuccess) { + secerror("KCdb: failed to load stash from KeychainStasher: %d", (int)agentrc); + } else { + secnotice("KCdb", "KeychainStasher claims loadKey success"); + } + + void* key = NULL; + size_t keylen = 0; + if (servicerc != KB_Success && agentrc != errSecSuccess) { + __security_simulatecrash(CFSTR("Both old and new stashes failed to load"), __sec_exception_code_BadStash); + CssmError::throwMe(servicerc); // For now + } else if (servicerc == KB_Success && agentrc == errSecSuccess) { + if (s_keylen != a_keylen || a_keylen == 0) { + __security_simulatecrash(CFSTR("Stashed key lengths disagree or are zero"), __sec_exception_code_BadStash); + } else if (cc_cmp_safe(a_keylen, a_key, s_key) != 0) { + __security_simulatecrash(CFSTR("Keybytes disagree"), __sec_exception_code_BadStash); + } + + key = a_key; + keylen = a_keylen; + memset_s(s_key, s_keylen, 0, s_keylen); + free(s_key); + } else if (servicerc == KB_Success) { + key = s_key; + keylen = s_keylen; + } else if (agentrc == errSecSuccess) { + key = a_key; + keylen = a_keylen; + } + + masterKey.copy(CssmData(key, keylen)); + memset_s(key, keylen, 0, keylen); + free(key); + + secnotice("KCdb", "Retrieved stashed key, will establish"); { StLock _(common()); @@ -914,8 +953,9 @@ void KeychainDatabase::stashDbCheck() hdr.blobFormat(CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING); common().setup(mBlob, key); - if (!decode()) + if (!decode()) { CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); + } common().get_encryption_key(encKey); } @@ -934,11 +974,11 @@ void KeychainDatabase::stashDbCheck() // void KeychainDatabase::stashDb() { + secnotice("KCdb", "Let's stash a key"); CssmAutoData data(Allocator::standard(Allocator::sensitive)); { StLock _(common()); - if (!common().isValid()) { CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); } @@ -946,10 +986,28 @@ void KeychainDatabase::stashDb() CssmKey key = common().masterKey(); data.copy(key.keyData()); } - + + // We're going to double-stash during transition service_context_t context = common().session().get_current_service_context(); - int rc = service_client_stash_set_key(&context, data.data(), (int)data.length()); - if (rc != 0) CssmError::throwMe(rc); + int servicerc = service_client_stash_set_key(&context, data.data(), (int)data.length()); + if (servicerc != KB_Success) { + secerror("KCdb: securityd_service stash failed: %d", servicerc); + } else { + secnotice("KCdb", "securityd_service claims successful stash"); + } + + OSStatus agentrc = stashKeyWithStashAgent(common().session().originatorUid(), data.data(), data.length()); + if (agentrc != errSecSuccess) { + secerror("KCdb: KeychainStasher stash failed: %d", (int)agentrc); + } else { + secnotice("KCdb", "KeychainStasher claims successful stash"); + } + + if (servicerc != KB_Success && agentrc != errSecSuccess) { + __security_simulatecrash(CFSTR("Both old and new stash mechanisms failed"), __sec_exception_code_BadStash); + CssmError::throwMe(servicerc); // For now + } + secnotice("KCdb", "Key stashed"); } // diff --git a/securityd/src/keychainstasherinterface.h b/securityd/src/keychainstasherinterface.h new file mode 100644 index 00000000..bac7bb55 --- /dev/null +++ b/securityd/src/keychainstasherinterface.h @@ -0,0 +1,15 @@ +#ifndef keychainstasherinterface_h +#define keychainstasherinterface_h + +#ifdef __cplusplus +extern "C" { +#endif + +OSStatus stashKeyWithStashAgent(uid_t client, void const* keybytes, size_t keylen); +OSStatus loadKeyFromStashAgent(uid_t client, void** keybytes, size_t* keylen); + +#ifdef __cplusplus +} +#endif + +#endif /* keychainstasherinterface_h */ diff --git a/securityd/src/keychainstasherinterface.m b/securityd/src/keychainstasherinterface.m new file mode 100644 index 00000000..dfb30b0e --- /dev/null +++ b/securityd/src/keychainstasherinterface.m @@ -0,0 +1,88 @@ +#import +#import +#import + +#include "utilities/debugging.h" + +#import "KeychainStasherProtocol.h" +#import "keychainstasherinterface.h" + +NSString* const KeychainStasherMachServiceName = @"com.apple.security.KeychainStasher"; + +OSStatus stashKeyWithStashAgent(uid_t client, void const* keybytes, size_t keylen) { + if (!keybytes || keylen == 0) { + secerror("KeychainStasherInterface: No or truncated key, won't stash"); + return errSecParam; + } + + secnotice("KeychainStasherInterface", "Reaching out to agent to stash key"); + __block OSStatus result = errSecInternalError; + @autoreleasepool { + NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:KeychainStasherMachServiceName options:0]; + [connection _setTargetUserIdentifier: client]; + connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)]; + [connection resume]; + + id proxy = [connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { + secerror("KeychainStasherInterface: errorhandler for agent called: %@", error); + result = errSecIO; + }]; + + NSData* key = [NSData _newZeroingDataWithBytes:keybytes length:keylen]; + [proxy stashKey:key withReply:^(NSError* error) { + if (error) { + secerror("KeychainStasherInterface: agent failed to stash key: %@", error); + result = (int)error.code; + } else { + result = errSecSuccess; + } + }]; + + [connection invalidate]; + } + + if (result == errSecSuccess) { + secnotice("KeychainStasherInterface", "Successfully stashed key"); + } + return result; +} + +OSStatus loadKeyFromStashAgent(uid_t client, void** keybytes, size_t* keylen) { + if (!keybytes || !keylen) { + secerror("KeychainStasherInterface: No outparams for key, won't load"); + return errSecParam; + } + + secnotice("KeychainStasherInterface", "Reaching out to agent to retrieve key"); + __block OSStatus result = errSecInternalError; + @autoreleasepool { + NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:KeychainStasherMachServiceName options:0]; + [connection _setTargetUserIdentifier: client]; + connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(KeychainStasherProtocol)]; + [connection resume]; + + id proxy = [connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { + secerror("KeychainStasherInterface: errorhandler for agent called: %@", error); + result = errSecIO; + }]; + + [proxy loadKeyWithReply:^(NSData *key, NSError *error) { + if (!key) { + secerror("KeychainStasherInterface: agent failed to load key: %@", error); + result = (int)error.code; + return; + } + *keybytes = calloc(1, key.length); + memcpy(*keybytes, key.bytes, key.length); + *keylen = key.length; + result = errSecSuccess; + }]; + + [connection invalidate]; + } + + if (result == errSecSuccess) { + secnotice("KeychainStasherInterface", "Successfully loaded key"); + } + return result; +} diff --git a/securityd/src/main.cpp b/securityd/src/main.cpp index e94f68b1..d2035631 100644 --- a/securityd/src/main.cpp +++ b/securityd/src/main.cpp @@ -30,7 +30,6 @@ #include "server.h" #include "session.h" #include "notifications.h" -#include "pcscmonitor.h" #include "auditevents.h" #include "self.h" #include "util.h" @@ -66,11 +65,8 @@ // static void usage(const char *me) __attribute__((noreturn)); static void handleSignals(int sig); -static PCSCMonitor::ServiceLevel scOptions(const char *optionString); -static bool legacyTokensEnabled(void); static Port gMainServerPort; -PCSCMonitor *gPCSC; // @@ -87,7 +83,7 @@ int main(int argc, char *argv[]) // tell the keychain (client) layer to turn off the server interface SecKeychainSetServerMode(); - const char *params[] = {"LEGACY_TOKENS_ENABLED", legacyTokensEnabled() ? "YES" : "NO", NULL}; + const char *params[] = {"LEGACY_TOKENS_ENABLED", "NO", NULL}; char* errorbuf = NULL; if (sandbox_init_with_parameters("com.apple.securityd", SANDBOX_NAMED, params, &errorbuf)) { seccritical("SecServer: unable to enter sandbox: %{public}s", errorbuf); @@ -101,32 +97,24 @@ int main(int argc, char *argv[]) // program arguments (preset to defaults) bool debugMode = false; - bool doFork = false; - bool reExecute = false; int workerTimeout = 0; int maxThreads = 0; bool waitForClients = true; bool mdsIsInstalled = false; - const char *tokenCacheDir = "/var/db/TokenCache"; - const char *smartCardOptions = getenv("SMARTCARDS"); uint32_t keychainAclDefault = CSSM_ACL_KEYCHAIN_PROMPT_INVALID | CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED; unsigned int verbose = 0; // check for the Installation-DVD environment and modify some default arguments if found if (access("/etc/rc.cdrom", F_OK) == 0) { // /etc/rc.cdrom exists secnotice("SecServer", "starting in installmode"); - smartCardOptions = "off"; // needs writable directories that aren't } // parse command line arguments extern char *optarg; extern int optind; int arg; - while ((arg = getopt(argc, argv, "c:dE:ims:t:T:uvWX")) != -1) { + while ((arg = getopt(argc, argv, ":dE:im:t:T:uvW")) != -1) { switch (arg) { - case 'c': - tokenCacheDir = optarg; - break; case 'd': debugMode = true; break; @@ -139,9 +127,6 @@ int main(int argc, char *argv[]) case 'm': mdsIsInstalled = true; break; - case 's': - smartCardOptions = optarg; - break; case 't': if ((maxThreads = atoi(optarg)) < 0) maxThreads = 0; @@ -159,10 +144,6 @@ int main(int argc, char *argv[]) case 'v': verbose++; break; - case 'X': - doFork = true; - reExecute = true; - break; default: usage(argv[0]); } @@ -197,12 +178,8 @@ int main(int argc, char *argv[]) } // turn into a properly diabolical daemon unless debugMode is on - if (!debugMode && getppid() != 1) { - if (!Daemon::incarnate(doFork)) - exit(1); // can't daemonize - - if (reExecute && !Daemon::executeSelf(argv)) - exit(1); // can't self-execute + if (!debugMode && getppid() != 1 && !Daemon::incarnate(false)) { + exit(1); // can't daemonize } // arm signal handlers; code below may generate signals we want to see @@ -253,10 +230,7 @@ int main(int argc, char *argv[]) server.floatingThread(true); server.waitForClients(waitForClients); server.verbosity(verbose); - - // create a smartcard monitor to manage external token devices - gPCSC = new PCSCMonitor(server, tokenCacheDir, scOptions(smartCardOptions)); - + // create the RootSession object (if -d, give it graphics and tty attributes) RootSession rootSession(debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0, server); @@ -292,9 +266,7 @@ int main(int argc, char *argv[]) static void usage(const char *me) { fprintf(stderr, "Usage: %s [-dwX]" - "\n\t[-c tokencache] smartcard token cache directory" "\n\t[-e equivDatabase] path to code equivalence database" - "\n\t[-s off|on|conservative|aggressive] smartcard operation level" "\n\t[-t maxthreads] [-T threadTimeout] server thread control" "\n", me); exit(2); @@ -303,44 +275,6 @@ static void usage(const char *me) const CFStringRef kTKSmartCardPreferencesDomain = CFSTR("com.apple.security.smartcard"); const CFStringRef kTKLegacyTokendPreferencesKey = CFSTR("Legacy"); -static bool legacyTokensEnabled() { - bool result = false; - CFPropertyListRef value = CFPreferencesCopyValue(kTKLegacyTokendPreferencesKey, kTKSmartCardPreferencesDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - if (value) { - if (CFEqual(value, kCFBooleanTrue)) { - result = true; - } - CFRelease(value); - } - return result; -} - -// -// Translate strings (e.g. "conservative") into PCSCMonitor service levels -// -static PCSCMonitor::ServiceLevel scOptions(const char *optionString) -{ - if (!legacyTokensEnabled()) - return PCSCMonitor::forcedOff; - - if (optionString) - if (!strcmp(optionString, "off")) - return PCSCMonitor::forcedOff; - else if (!strcmp(optionString, "on")) - return PCSCMonitor::externalDaemon; - else if (!strcmp(optionString, "conservative")) - return PCSCMonitor::externalDaemon; - else if (!strcmp(optionString, "aggressive")) - return PCSCMonitor::externalDaemon; - else if (!strcmp(optionString, "external")) - return PCSCMonitor::externalDaemon; - else - usage("securityd"); - else - return PCSCMonitor::externalDaemon; -} - - // // Handle signals. // We send ourselves a message (through the "self" service), so actual diff --git a/securityd/src/notifications.cpp b/securityd/src/notifications.cpp index 1efed3a5..2b846445 100644 --- a/securityd/src/notifications.cpp +++ b/securityd/src/notifications.cpp @@ -109,33 +109,6 @@ void Listener::sendNotification(Notification *message) } } - -// -// Handle a port death or deallocation by removing all Listeners using that port. -// Returns true iff we had one. -// -bool Listener::remove(Port port) -{ - typedef ListenerMap::iterator Iterator; - StLock _(setLock); - pair range = listeners.equal_range(port); - if (range.first == range.second) - return false; // not one of ours - - assert(range.first != listeners.end()); - secinfo("notify", "remove port %d", port.port()); -#if !defined(NDEBUG) - for (Iterator it = range.first; it != range.second; it++) { - assert(it->first == port); - secinfo("notify", "%p listener removed", it->second.get()); - } -#endif //NDEBUG - listeners.erase(range.first, range.second); - port.destroy(); - return true; // got it -} - - // // Notification message objects // diff --git a/securityd/src/notifications.h b/securityd/src/notifications.h index 4fd7f303..0097f34d 100644 --- a/securityd/src/notifications.h +++ b/securityd/src/notifications.h @@ -74,7 +74,6 @@ public: NotificationEvent event, const CssmData &data); static void notify(NotificationDomain domain, NotificationEvent event, uint32 sequence, const CssmData &data, audit_token_t auditToken); - static bool remove(Port port); const NotificationDomain domain; const NotificationMask events; diff --git a/securityd/src/process.cpp b/securityd/src/process.cpp index 9ab05df8..496bff88 100644 --- a/securityd/src/process.cpp +++ b/securityd/src/process.cpp @@ -69,6 +69,9 @@ Process::Process(TaskPort taskPort, const ClientSetupInfo *info, const CommonCri CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); } + // This is a "retain", matched by the deallocate call in ~Process + mTaskPort.modRefs(MACH_PORT_RIGHT_SEND, 1); + // 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. diff --git a/securityd/src/securityd.entitlements b/securityd/src/securityd.entitlements index f569603b..c825c108 100644 --- a/securityd/src/securityd.entitlements +++ b/securityd/src/securityd.entitlements @@ -10,5 +10,7 @@ com.apple.private.security.storage.SystemKeychain + com.apple.private.securityd.stash-agent-client + diff --git a/securityd/src/server.cpp b/securityd/src/server.cpp index d510615c..81fb8fce 100644 --- a/securityd/src/server.cpp +++ b/securityd/src/server.cpp @@ -37,7 +37,6 @@ #include #include #include -#include "pcscmonitor.h" #include "agentquery.h" @@ -330,11 +329,8 @@ kern_return_t self_server_handleSignal(mach_port_t sport, #endif //DEBUGDUMP case SIGUSR2: - { - extern PCSCMonitor *gPCSC; - gPCSC->startSoftTokens(); - break; - } + fprintf(stderr, "securityd ignoring SIGUSR2 received"); + break; default: assert(false); @@ -509,6 +505,8 @@ bool Server::inDarkWake() // void Server::loadCssm(bool mdsIsInstalled) { + try { + if (!mCssm->isActive()) { StLock _(*this); xpc_transaction_begin(); @@ -525,6 +523,23 @@ void Server::loadCssm(bool mdsIsInstalled) } xpc_transaction_end(); } + } catch (const UnixError& err) { + secerror("load cssm failed: %s", err.what()); + if (err.unixError() == ENOSPC) { + _exit(1); + } else { + abort(); + } + } catch (const MacOSError& err) { + secerror("load cssm failed: %s", err.what()); + abort(); + } catch (const CommonError& err) { + secerror("load cssm failed: %d/%d", (int)err.osStatus(), err.unixError()); + abort(); + } catch (const std::exception& err) { + secerror("load cssm failed: %s", err.what()); + abort(); + } } diff --git a/securityd/src/token.cpp b/securityd/src/token.cpp index c9d2f5d5..f6aaaf05 100644 --- a/securityd/src/token.cpp +++ b/securityd/src/token.cpp @@ -41,7 +41,6 @@ #include #include #include -#include using namespace MDSClient; @@ -436,15 +435,6 @@ void Token::notify(NotificationEvent event) free (data.data()); } -static void mt_log_ctk_tokend(const char *signature, const char *signature2) -{ - msgtracer_log_with_keys("com.apple.ctk.tokend", ASL_LEVEL_NOTICE, - "com.apple.message.signature", signature, - "com.apple.message.signature2", signature2, - "com.apple.message.summarize", "YES", - NULL); -} - // // Choose a token daemon for our card. // @@ -503,7 +493,6 @@ RefPointer Token::chooseTokend() identifiers.append(";"); identifiers.append(*i); } - mt_log_ctk_tokend(identifiers.c_str(), chosenIdentifier.c_str()); return leader; } diff --git a/securityd/src/transition.cpp b/securityd/src/transition.cpp index ff606b4c..b2bd64d1 100644 --- a/securityd/src/transition.cpp +++ b/securityd/src/transition.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -65,7 +66,7 @@ #define BEGIN_IPCN *rcode = CSSM_OK; try { #define BEGIN_IPC(name) BEGIN_IPCN RefPointer connRef(&Server::connection(replyPort, auditToken)); \ Connection &connection __attribute__((unused)) = *connRef; \ - secinfo("SecServer", "request entry " #name " (pid:%d ession:%d)", connection.process().pid(), connection.session().sessionId()); + secinfo("SecServer", "request entry " #name " (pid:%d session:%d)", connection.process().pid(), connection.session().sessionId()); #define END_IPC(base) END_IPCN(base) Server::requestComplete(*rcode); return KERN_SUCCESS; #define END_IPCN(base) secinfo("SecServer", "request return: %d", *(rcode)); \ @@ -244,6 +245,7 @@ kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, ClientSetupInfo END_IPCN(CSSM) if (*rcode) Syslog::notice("setup(%s) failed rcode=%d", identity ? identity : "", *rcode); + mach_port_deallocate(mach_task_self(), taskPort); return KERN_SUCCESS; } @@ -256,6 +258,7 @@ kern_return_t ucsp_server_setupThread(UCSP_ARGS, mach_port_t taskPort) END_IPCN(CSSM) if (*rcode) Syslog::notice("setupThread failed rcode=%d", *rcode); + mach_port_deallocate(mach_task_self(), taskPort); return KERN_SUCCESS; } @@ -735,7 +738,7 @@ static void check_stash_entitlement(Process & proc) } require(entitlements != NULL, done); - if (CFDictionaryGetValueIfPresent(entitlements, CFSTR("com.apple.private.securityd.stash"), &value)) { + if (CFDictionaryGetValueIfPresent(entitlements, kSecEntitlementPrivateStash, &value)) { if (CFGetTypeID(value) && CFBooleanGetTypeID()) { entitled = CFBooleanGetValue((CFBooleanRef)value); } diff --git a/sslViewer/SSLViewer.c b/sslViewer/SSLViewer.c index 3cd0381e..a9d405d8 100644 --- a/sslViewer/SSLViewer.c +++ b/sslViewer/SSLViewer.c @@ -778,23 +778,26 @@ static void showPeerTrust(SecTrustRef peerTrust, bool verbose) { if (info && CFDictionaryGetCount(info)) { showInfo(info); } - if (info) + if (info) { CFRelease(info); + } - numCerts = SecTrustGetCertificateCount(peerTrust); - for(i=0; i +#import +#import + +#if TARGET_OS_OSX +#include +#include +#include +#endif #if TARGET_OS_SIMULATOR @@ -61,9 +69,41 @@ int main(int argc, char** argv) @end +static void securityuploadd_sandbox(void) +{ +#if TARGET_OS_OSX + // Enter the sandbox on macOS + char homeDir[PATH_MAX] = {}; + struct passwd* pwd = getpwuid(getuid()); + if (pwd == NULL) { + secerror("Failed to get home directory for user: %d", errno); + exit(EXIT_FAILURE); + } + + if (realpath(pwd->pw_dir, homeDir) == NULL) { + strlcpy(homeDir, pwd->pw_dir, sizeof(homeDir)); + } + + const char *sandbox_params[] = { + "HOME", homeDir, + NULL + }; + + char *sberror = NULL; + secerror("initializing securityuploadd sandbox with HOME=%s", homeDir); + if (sandbox_init_with_parameters("com.apple.securityuploadd", SANDBOX_NAMED, sandbox_params, &sberror) != 0) { + secerror("Failed to enter securityuploadd sandbox: %{public}s", sberror); + exit(EXIT_FAILURE); + } +#endif +} + int main(int argc, const char *argv[]) { secnotice("lifecycle", "supd lives!"); + [NSError _setFileNameLocalizationEnabled:NO]; + securityuploadd_sandbox(); + ServiceDelegate *delegate = [ServiceDelegate new]; // kick the singleton so it can register its xpc activity handler diff --git a/supd/securityuploadd-Entitlements.plist b/supd/securityuploadd-Entitlements.plist index ee1cb751..b359175e 100644 --- a/supd/securityuploadd-Entitlements.plist +++ b/supd/securityuploadd-Entitlements.plist @@ -14,5 +14,7 @@ com.apple.security.network.client + com.apple.private.security.storage.SFAnalytics + diff --git a/supd/supd.h b/supd/supd.h index 9e4bf941..84fbd9e5 100644 --- a/supd/supd.h +++ b/supd/supd.h @@ -51,10 +51,14 @@ + (NSString*)databasePathForPCS; + (NSString*)databasePathForLocal; + (NSString*)databasePathForTrust; -+ (NSString*)databasePathForTrustdHealth; -+ (NSString*)databasePathForTLS; ++ (NSString*)databasePathForNetworking; + (NSString*)databasePathForSignIn; + (NSString*)databasePathForCloudServices; + +#if TARGET_OS_OSX ++ (NSString*)databasePathForRootTrust; ++ (NSString*)databasePathForRootNetworking; +#endif @end @interface SFAnalyticsReporter : NSObject diff --git a/supd/supd.m b/supd/supd.m index 9fe33d87..e084d76e 100644 --- a/supd/supd.m +++ b/supd/supd.m @@ -43,6 +43,7 @@ #if TARGET_OS_OSX #include "dirhelper_priv.h" +#include #endif #if TARGET_OS_OSX @@ -59,6 +60,8 @@ #import #import +#import "utilities/simulatecrash_assert.h" + NSString* const SFAnalyticsSplunkTopic = @"topic"; NSString* const SFAnalyticsClientId = @"clientId"; @@ -341,18 +344,18 @@ _isiCloudAnalyticsEnabled() deviceAnalytics:YES iCloudAnalytics:NO]]; } else if ([topicName isEqualToString:SFAnalyticsTopicTrust]) { -#if TARGET_OS_OSX - _set_user_dir_suffix("com.apple.trustd"); // supd needs to read trustd's cache dir for these -#endif [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForTrust] name:@"trust" deviceAnalytics:YES iCloudAnalytics:NO]]; - [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForTrustdHealth] - name:@"trustdHealth" deviceAnalytics:YES iCloudAnalytics:NO]]; - [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForTLS] - name:@"tls" deviceAnalytics:YES iCloudAnalytics:NO]]; - #if TARGET_OS_OSX - _set_user_dir_suffix(NULL); // set back to the default cache dir + [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForRootTrust] + name:@"rootTrust" deviceAnalytics:YES iCloudAnalytics:NO]]; +#endif + } else if ([topicName isEqualToString:SFAnalyticsTopicNetworking]) { + [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForNetworking] + name:@"networking" deviceAnalytics:YES iCloudAnalytics:NO]]; +#if TARGET_OS_OSX + [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForRootNetworking] + name:@"rootNetworking" deviceAnalytics:YES iCloudAnalytics:NO]]; #endif } else if ([topicName isEqualToString:SFAnalyticsTopicTransparency]) { [clients addObject:[[SFAnalyticsClient alloc] initWithStorePath:[self.class databasePathForTransparency] @@ -890,48 +893,50 @@ participatingClients:(NSMutableArray**)clients accountID = accountAltDSID(); } for (SFAnalyticsClient* client in self->_topicClients) { - if (!force && [client requireDeviceAnalytics] && !_isDeviceAnalyticsEnabled()) { - // Client required device analytics, yet the user did not opt in. - secnotice("getLoggingJSON", "Client '%@' requires device analytics yet user did not opt in.", [client name]); - continue; - } - if (!force && [client requireiCloudAnalytics] && !_isiCloudAnalyticsEnabled()) { - // Client required iCloud analytics, yet the user did not opt in. - secnotice("getLoggingJSON", "Client '%@' requires iCloud analytics yet user did not opt in.", [client name]); - continue; - } - - SFAnalyticsSQLiteStore* store = [SFAnalyticsSQLiteStore storeWithPath:client.storePath schema:SFAnalyticsTableSchema]; - - if (upload) { - NSDate* uploadDate = store.uploadDate; - if (!force && uploadDate && [[NSDate date] timeIntervalSinceDate:uploadDate] < _secondsBetweenUploads) { - secnotice("json", "ignoring client '%@' for %@ because last upload too recent: %@", - client.name, _internalTopicName, uploadDate); + @autoreleasepool { + if (!force && [client requireDeviceAnalytics] && !_isDeviceAnalyticsEnabled()) { + // Client required device analytics, yet the user did not opt in. + secnotice("getLoggingJSON", "Client '%@' requires device analytics yet user did not opt in.", [client name]); continue; } - - if (force) { - secnotice("json", "client '%@' for topic '%@' force-included", client.name, _internalTopicName); - } else { - secnotice("json", "including client '%@' for topic '%@' for upload", client.name, _internalTopicName); + if (!force && [client requireiCloudAnalytics] && !_isiCloudAnalyticsEnabled()) { + // Client required iCloud analytics, yet the user did not opt in. + secnotice("getLoggingJSON", "Client '%@' requires iCloud analytics yet user did not opt in.", [client name]); + continue; } - [localClients addObject:client]; - } - NSMutableDictionary* healthSummary = [self healthSummaryWithName:client.name store:store uuid:linkedUUID]; - if (healthSummary) { - if (ckdeviceID) { - healthSummary[SFAnalyticsDeviceID] = ckdeviceID; + SFAnalyticsSQLiteStore* store = [SFAnalyticsSQLiteStore storeWithPath:client.storePath schema:SFAnalyticsTableSchema]; + + if (upload) { + NSDate* uploadDate = store.uploadDate; + if (!force && uploadDate && [[NSDate date] timeIntervalSinceDate:uploadDate] < _secondsBetweenUploads) { + secnotice("json", "ignoring client '%@' for %@ because last upload too recent: %@", + client.name, _internalTopicName, uploadDate); + continue; + } + + if (force) { + secnotice("json", "client '%@' for topic '%@' force-included", client.name, _internalTopicName); + } else { + secnotice("json", "including client '%@' for topic '%@' for upload", client.name, _internalTopicName); + } + [localClients addObject:client]; } - if (accountID) { - healthSummary[SFAnalyticsAltDSID] = accountID; + + NSMutableDictionary* healthSummary = [self healthSummaryWithName:client.name store:store uuid:linkedUUID]; + if (healthSummary) { + if (ckdeviceID) { + healthSummary[SFAnalyticsDeviceID] = ckdeviceID; + } + if (accountID) { + healthSummary[SFAnalyticsAltDSID] = accountID; + } + [localHealthSummaries addObject:healthSummary]; } - [localHealthSummaries addObject:healthSummary]; - } - [hardFailures addObject:store.hardFailures]; - [softFailures addObject:store.softFailures]; + [hardFailures addObject:store.hardFailures]; + [softFailures addObject:store.softFailures]; + } } if (upload && [localClients count] == 0) { @@ -1255,33 +1260,50 @@ participatingClients:(NSMutableArray**)clients return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory((__bridge CFStringRef)@"Analytics/localkeychain.db") path]; } -+ (NSString*)databasePathForTrustdHealth ++ (NSString*)databasePathForTrust { #if TARGET_OS_IPHONE - return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/trustd_health_analytics.db")) path]; + return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/trust_analytics.db")) path]; #else - return [(__bridge_transfer NSURL*)SecCopyURLForFileInUserCacheDirectory(CFSTR("Analytics/trustd_health_analytics.db")) path]; + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:@"trust_analytics"]; #endif } -+ (NSString*)databasePathForTrust +#if TARGET_OS_OSX ++ (NSUUID *)rootUUID { -#if TARGET_OS_IPHONE - return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/trust_analytics.db")) path]; -#else - return [(__bridge_transfer NSURL*)SecCopyURLForFileInUserCacheDirectory(CFSTR("Analytics/trust_analytics.db")) path]; + uuid_t rootUuid; + int ret = mbr_uid_to_uuid(0, rootUuid); + if (ret != 0) { + return nil; + } + return [[NSUUID alloc] initWithUUIDBytes:rootUuid]; +} #endif + +#if TARGET_OS_OSX ++ (NSString*)databasePathForRootTrust +{ + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:@"trust_analytics" uuid:[SFAnalyticsTopic rootUUID]]; } +#endif -+ (NSString*)databasePathForTLS ++ (NSString*)databasePathForNetworking { #if TARGET_OS_IPHONE - return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/TLS_analytics.db")) path]; + return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/networking_analytics.db")) path]; #else - return [(__bridge_transfer NSURL*)SecCopyURLForFileInUserCacheDirectory(CFSTR("Analytics/TLS_analytics.db")) path]; + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:@"networking_analytics"]; #endif } +#if TARGET_OS_OSX ++ (NSString*)databasePathForRootNetworking +{ + return [SFAnalytics defaultProtectedAnalyticsDatabasePath:@"networking_analytics" uuid:[SFAnalyticsTopic rootUUID]]; +} +#endif + + (NSString*)databasePathForSignIn { return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/signin_metrics.db")) path]; diff --git a/supdctl/main.m b/supdctl/main.m index 2920fd4c..5ce0e43d 100644 --- a/supdctl/main.m +++ b/supdctl/main.m @@ -30,8 +30,6 @@ /* Internal Topic Names */ NSString* const SFAnalyticsTopicKeySync = @"KeySyncTopic"; -NSString* const SFAnalyticsTopicTrust = @"TrustTopic"; -NSString* const SFAnalyticsTopicTransparency = @"TransparencyTopic"; static void nsprintf(NSString *fmt, ...) NS_FORMAT_FUNCTION(1, 2); static void nsprintf(NSString *fmt, ...) diff --git a/tests/SecDbBackupTests/Entitlements.plist b/tests/SecDbBackupTests/SecDbBackupTests-Entitlements.plist similarity index 93% rename from tests/SecDbBackupTests/Entitlements.plist rename to tests/SecDbBackupTests/SecDbBackupTests-Entitlements.plist index f63472fe..7f63b7f3 100644 --- a/tests/SecDbBackupTests/Entitlements.plist +++ b/tests/SecDbBackupTests/SecDbBackupTests-Entitlements.plist @@ -28,5 +28,7 @@ SecDbBackupManager-UnitTests + com.apple.private.security.storage.Keychains + diff --git a/tests/SecDbBackupTests/SecDbBackupTests.m b/tests/SecDbBackupTests/SecDbBackupTests.m index cb8d0e72..ad5f3e41 100644 --- a/tests/SecDbBackupTests/SecDbBackupTests.m +++ b/tests/SecDbBackupTests/SecDbBackupTests.m @@ -1,11 +1,4 @@ -// -// SecDbBackupTests.m -// Security -// -// Created by Wouter de Groot on 2018-12-12. -// - -#import +#import "SecDbBackupTestsBase.h" #import "keychain/securityd/SecDbBackupManager.h" #if !SECDB_BACKUPS_ENABLED @@ -20,77 +13,29 @@ #import "keychain/securityd/SecDbBackupManager_Internal.h" -#import "CKKS.h" -#import -#import "spi.h" -#import "SecItemServer.h" + #import #include "utilities/der_plist.h" #include -@interface SecDbBackupTests : XCTestCase +@interface SecDbBackupTests : SecDbBackupTestsBase @end SecDbBackupManager* _manager; -NSString* _uuidstring; - -@implementation SecDbBackupTests { - NSString* _testHomeDirectory; -} -static int testCheckV12DevEnabled(void) { - return 1; -} +@implementation SecDbBackupTests + (void)setUp { [super setUp]; - checkV12DevEnabled = testCheckV12DevEnabled; - SecCKKSDisable(); -#if OCTAGON - SecCKKSTestSetDisableSOS(true); -#endif - _uuidstring = [[NSUUID UUID] UUIDString]; } + (void)tearDown { - SetCustomHomeURL(NULL); - SecKeychainDbReset(NULL); - resetCheckV12DevEnabled(); + [super tearDown]; } - (void)setUp { [super setUp]; - - NSString* testName = [self.name componentsSeparatedByString:@" "][1]; - testName = [testName stringByReplacingOccurrencesOfString:@"]" withString:@""]; - secnotice("secdbbackuptest", "Beginning test %@", testName); - - // Make a new fake keychain - NSError* error; - _testHomeDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@/%@/", _uuidstring, testName]]; - - NSLog(@"%@", _testHomeDirectory); - - [[NSFileManager defaultManager] createDirectoryAtPath:_testHomeDirectory - withIntermediateDirectories:YES - attributes:nil - error:&error]; - // No XCTAssert in class method - if (error) { - NSLog(@"Could not make directory at %@", _testHomeDirectory); - } - - SetCustomHomeURLString((__bridge CFStringRef)_testHomeDirectory); - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - securityd_init(NULL); - }); - SecKeychainDbReset(NULL); - - // Actually load the database. - kc_with_dbt(true, NULL, ^bool (SecDbConnectionRef dbt) { return false; }); - [SecDbBackupManager resetManager]; _manager = [SecDbBackupManager manager]; } @@ -359,9 +304,9 @@ static int testCheckV12DevEnabled(void) { void* aksunwrappedbytes = NULL; size_t aksunwrappedlen = 0; XCTAssertEqual(aks_ref_key_decrypt(refkey, NULL, 0, kcsk.aksWrappedKey.bytes, kcsk.aksWrappedKey.length, &aksunwrappedbytes, &aksunwrappedlen), kAKSReturnSuccess, @"Successfully unwrapped KCSK private key"); - SFECKeyPair* aksunwrapped = [_manager ECKeyPairFromDerBytes:aksunwrappedbytes length:aksunwrappedlen error:&error]; + SFECKeyPair* aksunwrapped = [_manager getECKeyPairFromDERBytes:aksunwrappedbytes length:aksunwrappedlen error:&error]; XCTAssertNil(error, @"No error reconstructing AKS backup key"); - XCTAssert(aksunwrapped, @"Got key from ECKeyPairFromDerBytes"); + XCTAssert(aksunwrapped, @"Got key from getECKeyPairFromDERBytes"); aks_ref_key_free(&refkey); // Verify backupWrappedKey @@ -428,7 +373,7 @@ static int testCheckV12DevEnabled(void) { - (void)testWrapItemKey { SFAESKey* randomKey = [self randomAESKey]; NSError* error; - SecDbBackupWrappedItemKey* itemKey = [_manager wrapItemKey:randomKey forKeyclass:key_class_akpu error:&error]; + SecDbBackupWrappedKey* itemKey = [_manager wrapItemKey:randomKey forKeyclass:key_class_akpu error:&error]; XCTAssertNil(itemKey, @"Do not expect result wrapping to akpu"); XCTAssertEqual(error.code, SecDbBackupInvalidArgument, @"Expect invalid argument error wrapping to akpu"); @@ -437,7 +382,22 @@ static int testCheckV12DevEnabled(void) { XCTAssertNil(error, @"No error wrapping item to ak"); XCTAssertEqualObjects(itemKey.baguuid, _manager.bagIdentity.baguuid, @"item wrapped under expected bag uuid"); - // TODO: implement decryption and test it here + // TODO: implement decryption and test it +} + +- (void)testWrapMetadataKey { + SFAESKey* randomKey = [self randomAESKey]; + NSError* error; + SecDbBackupWrappedKey* itemKey = [_manager wrapMetadataKey:randomKey forKeyclass:key_class_akpu error:&error]; + XCTAssertNil(itemKey, @"Do not expect result wrapping to akpu"); + XCTAssertEqual(error.code, SecDbBackupInvalidArgument, @"Expect invalid argument error wrapping to akpu"); + + error = nil; + itemKey = [_manager wrapMetadataKey:randomKey forKeyclass:key_class_ak error:&error]; + XCTAssertNil(error, @"No error wrapping item to ak"); + XCTAssertEqualObjects(itemKey.baguuid, _manager.bagIdentity.baguuid, @"item wrapped under expected bag uuid"); + + // TODO: implement decryption and test it } // Does not inspect the item because it's encrypted and no code yet built to do recovery. diff --git a/tests/SecDbBackupTests/SecDbBackupTests.plist b/tests/SecDbBackupTests/SecDbBackupTests.plist deleted file mode 100644 index 817e23d9..00000000 --- a/tests/SecDbBackupTests/SecDbBackupTests.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - - BATSConfigVersion - 0.1.0 - Project - Security - Tests - - - TestName - SecDbBackupTests - WorkingDirectory - /AppleInternal/XCTests/com.apple.security/ - ShowSubtestResults - - Timeout - 1200 - Command - - BATS_XCTEST_CMD SecDbBackupTests.xctest - - - - - diff --git a/tests/SecDbBackupTests/SecDbBackupTestsBase.h b/tests/SecDbBackupTests/SecDbBackupTestsBase.h new file mode 100644 index 00000000..c356c5ed --- /dev/null +++ b/tests/SecDbBackupTests/SecDbBackupTestsBase.h @@ -0,0 +1,19 @@ +#ifndef SecDbBackupTestsBase_h +#define SecDbBackupTestsBase_h + +#import + +// This isn't inheritance-based data hiding, this whole class is for convenience building tests +#import "keychain/securityd/CheckV12DevEnabled.h" +#import "CKKS.h" +#import +#import "spi.h" +#import "SecItemServer.h" + +@interface SecDbBackupTestsBase : XCTestCase + ++ (void)setV12Development:(BOOL)newState; + +@end + +#endif /* SecDbBackupTestsBase_h */ diff --git a/tests/SecDbBackupTests/SecDbBackupTestsBase.m b/tests/SecDbBackupTests/SecDbBackupTestsBase.m new file mode 100644 index 00000000..d99092e7 --- /dev/null +++ b/tests/SecDbBackupTests/SecDbBackupTestsBase.m @@ -0,0 +1,74 @@ +#import "SecDbBackupTestsBase.h" + +static int checkV12DevEnabledOn(void) { + return 1; +} + +static int checkV12DevEnabledOff(void) { + return 0; +} + +NSString* _uuidstring; + +@implementation SecDbBackupTestsBase { + NSString* _testHomeDirectory; +} + ++ (void)setV12Development:(BOOL)newState { + if (newState) { + checkV12DevEnabled = checkV12DevEnabledOn; + } else { + checkV12DevEnabled = checkV12DevEnabledOff; + } +} + ++ (void)setUp { + [super setUp]; + checkV12DevEnabled = checkV12DevEnabledOn; + SecCKKSDisable(); +#if OCTAGON + SecCKKSTestSetDisableSOS(true); +#endif + _uuidstring = [[NSUUID UUID] UUIDString]; +} + +- (void)setUp { + NSString* testName = [self.name componentsSeparatedByString:@" "][1]; + testName = [testName stringByReplacingOccurrencesOfString:@"]" withString:@""]; + secnotice("secdbbackuptest", "Beginning test %@", testName); + + // Make a new fake keychain + NSError* error; + _testHomeDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@/%@/", _uuidstring, testName]]; + + NSLog(@"%@", _testHomeDirectory); + + [[NSFileManager defaultManager] createDirectoryAtPath:_testHomeDirectory + withIntermediateDirectories:YES + attributes:nil + error:&error]; + + XCTAssertNil(error, "Could not make directory at %@", _testHomeDirectory); + + SetCustomHomeURLString((__bridge CFStringRef)_testHomeDirectory); + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + securityd_init(NULL); + }); + SecKeychainDbReset(NULL); + + // Actually load the database. + kc_with_dbt(true, NULL, ^bool (SecDbConnectionRef dbt) { return false; }); +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + ++ (void)tearDown { + SetCustomHomeURL(NULL); + SecKeychainDbReset(NULL); + resetCheckV12DevEnabled(); +} + +@end diff --git a/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.h b/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.h new file mode 100644 index 00000000..25b7f009 --- /dev/null +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.h @@ -0,0 +1,16 @@ +#import + +#if TARGET_OS_OSX + +#import +@interface AppDelegate : NSObject +@end + +#else + +#import +@interface AppDelegate : UIResponder +@property (strong, nonatomic) UIWindow *window; +@end + +#endif diff --git a/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.m b/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.m new file mode 100644 index 00000000..febafd36 --- /dev/null +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/AppDelegate.m @@ -0,0 +1,25 @@ +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + +#if TARGET_OS_OSX + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {} +- (void)applicationWillTerminate:(NSNotification *)aNotification {} + +#else + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {return YES;} +- (void)applicationWillResignActive:(UIApplication *)application {} +- (void)applicationDidEnterBackground:(UIApplication *)application {} +- (void)applicationWillEnterForeground:(UIApplication *)application {} +- (void)applicationDidBecomeActive:(UIApplication *)application {} +- (void)applicationWillTerminate:(UIApplication *)application {} + +#endif + +@end diff --git a/KeychainEntitledTestApp_mac/Assets.xcassets/AppIcon.appiconset/Contents.json b/tests/TestHostBinaries/KeychainEntitledTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from KeychainEntitledTestApp_mac/Assets.xcassets/AppIcon.appiconset/Contents.json rename to tests/TestHostBinaries/KeychainEntitledTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/KeychainEntitledTestApp_mac/Info.plist b/tests/TestHostBinaries/KeychainEntitledTestApp/Info.plist similarity index 89% rename from KeychainEntitledTestApp_mac/Info.plist rename to tests/TestHostBinaries/KeychainEntitledTestApp/Info.plist index 8a4ebbf1..5315cf87 100644 --- a/KeychainEntitledTestApp_mac/Info.plist +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/Info.plist @@ -20,9 +20,14 @@ 1.0 CFBundleVersion 1 + UIRequiresFullScreen + +#import +#if TARGET_OS_OSX LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSPrincipalClass NSApplication +#endif diff --git a/tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.h b/tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.h new file mode 100644 index 00000000..8f765126 --- /dev/null +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.h @@ -0,0 +1,15 @@ +#import + +#if TARGET_OS_OSX + +#import +@interface ViewController : NSViewController +@end + +#else + +#import +@interface ViewController : UIViewController +@end + +#endif diff --git a/KeychainEntitledTestApp_mac/ViewController.m b/tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.m similarity index 50% rename from KeychainEntitledTestApp_mac/ViewController.m rename to tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.m index 452e7570..ab623ad2 100644 --- a/KeychainEntitledTestApp_mac/ViewController.m +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/ViewController.m @@ -1,27 +1,25 @@ -// -// ViewController.m -// KeychainEntitledTestApp_mac -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// - #import "ViewController.h" -@implementation ViewController +#if TARGET_OS_OSX +@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; - - // Do any additional setup after loading the view. } - - - (void)setRepresentedObject:(id)representedObject { [super setRepresentedObject:representedObject]; - - // Update the view, if already loaded. } +@end +#else +@implementation ViewController +- (void)viewDidLoad { + [super viewDidLoad]; +} +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + } @end + +#endif diff --git a/KeychainEntitledTestApp_ios/main.m b/tests/TestHostBinaries/KeychainEntitledTestApp/main.m similarity index 54% rename from KeychainEntitledTestApp_ios/main.m rename to tests/TestHostBinaries/KeychainEntitledTestApp/main.m index d553ece5..80e84daa 100644 --- a/KeychainEntitledTestApp_ios/main.m +++ b/tests/TestHostBinaries/KeychainEntitledTestApp/main.m @@ -1,10 +1,14 @@ -// -// main.m -// KeychainEntitledTestApp_ios -// -// Copyright (c) 2017 Apple Inc. All rights reserved. -// -// +#import + +#if TARGET_OS_OSX + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} + +#else #import #import "AppDelegate.h" @@ -14,3 +18,5 @@ int main(int argc, char * argv[]) { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } + +#endif diff --git a/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist b/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements similarity index 65% rename from keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist rename to tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements index 46c3d41e..8e213a9f 100644 --- a/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner-Entitlements.plist +++ b/tests/TestHostBinaries/KeychainEntitledTestRunner.entitlements @@ -22,11 +22,26 @@ aps-environment serverPreferred - keychain-access-groups + keychain-access-groups com.apple.security.ckks + SecDbBackupManager-UnitTests keychain-cloud-circle + com.apple.security.app-sandbox + + com.apple.security.get-task-allow + + com.apple.keystore.access-keychain-keys + + com.apple.keystore.lockassertion + + com.apple.private.associated-domains + + com.apple.private.necp.match + + com.apple.mkb.usersession.info + diff --git a/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner.m b/tests/TestHostBinaries/KeychainEntitledTestRunner/KeychainEntitledTestRunner.m similarity index 91% rename from keychain/ckks/tests/testrunner/KeychainEntitledTestRunner.m rename to tests/TestHostBinaries/KeychainEntitledTestRunner/KeychainEntitledTestRunner.m index cf5cbc56..98d37667 100644 --- a/keychain/ckks/tests/testrunner/KeychainEntitledTestRunner.m +++ b/tests/TestHostBinaries/KeychainEntitledTestRunner/KeychainEntitledTestRunner.m @@ -26,8 +26,7 @@ @implementation TestRunner - (instancetype)initWithBundlePath:(NSString *)path andTestNames:(NSArray *)names { - self = [super init]; - if (self) { + if ((self = [super init])) { NSError *error = nil; _bundle = [NSBundle bundleWithPath:path]; @@ -115,9 +114,9 @@ [self testLogWithFormat:@"Test Suite '%@' started at %@\n", testSuite.name, [self.dateFormatter stringFromDate:testSuite.testRun.startDate]]; } -- (void)testSuite:(XCTestSuite *)testSuite didFailWithDescription:(NSString *)description inFile:(nullable NSString *)filePath atLine:(NSUInteger)lineNumber -{ - [self testLogWithFormat:@"%@:%lu: error: %@ : %@\n", ((nil != filePath) ? filePath : @""), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testSuite.name, description]; +- (void)testSuite:(XCTestSuite *)testSuite didRecordIssue:(XCTIssue *)issue { + [self testLogWithFormat:@"(%@)%@:%lu: error: %@", testSuite.name, issue.sourceCodeContext.location.fileURL, + issue.sourceCodeContext.location.lineNumber, issue.compactDescription]; } - (void)testSuiteDidFinish:(XCTestSuite *)testSuite @@ -139,9 +138,8 @@ [self testLogWithFormat:@"Test Case '%@' started.\n", testCase.name]; } -- (void)testCase:(XCTestCase *)testCase didFailWithDescription:(NSString *)description inFile:(nullable NSString *)filePath atLine:(NSUInteger)lineNumber -{ - [self testLogWithFormat:@"%@:%lu: error: %@ : %@\n", ((nil != filePath) ? filePath : @""), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testCase.name, description]; +- (void)testCase:(XCTestCase *)testCase didRecordIssue:(XCTIssue *)issue { + [self testLogWithFormat:@"(%@)%@:%lu error: %@\n%@", testCase.name, issue.sourceCodeContext.location.fileURL, issue.sourceCodeContext.location.lineNumber, issue.detailedDescription, issue.sourceCodeContext.callStack]; } - (void)testCaseDidFinish:(XCTestCase *)testCase diff --git a/tests/TrustTests/DaemonTests/PersonalizationTests.m b/tests/TrustTests/DaemonTests/PersonalizationTests.m new file mode 100644 index 00000000..b73d06d4 --- /dev/null +++ b/tests/TrustTests/DaemonTests/PersonalizationTests.m @@ -0,0 +1,19 @@ +// +// PersonalizationTests.m +// Security +// +// + +#import +#import +#import "trust/trustd/personalization.h" + +#import "TrustDaemonTestCase.h" + +@interface PersonalizationTests: TrustDaemonTestCase +@end + +@implementation PersonalizationTests + + +@end diff --git a/tests/TrustTests/DaemonTests/TrustDaemonTestCase.h b/tests/TrustTests/DaemonTests/TrustDaemonTestCase.h index 95ac24f0..ba0a45fc 100644 --- a/tests/TrustTests/DaemonTests/TrustDaemonTestCase.h +++ b/tests/TrustTests/DaemonTests/TrustDaemonTestCase.h @@ -21,7 +21,6 @@ * @APPLE_LICENSE_HEADER_END@ * */ - #ifndef _TRUSTTESTS_DAEMON_TESTCASE_H_ #define _TRUSTTESTS_DAEMON_TESTCASE_H_ diff --git a/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m b/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m new file mode 100644 index 00000000..2a80ae64 --- /dev/null +++ b/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m @@ -0,0 +1,409 @@ +/* +* Copyright (c) 2011-2019 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@ +*/ + +#include +#import +#import +#include +#include +#include +#include +#include +#include + +#import "../TestMacroConversions.h" +#import "TrustEvaluationTestCase.h" + +#import "AllowlistBlocklistTests_data.h" + +@interface BlocklistTests :TrustEvaluationTestCase +@end + +@implementation BlocklistTests + +- (void)validate_one_cert:(uint8_t *)data length:(size_t)len chain_length:(int)chain_length trustResult:(SecTrustResultType)trust_result +{ + SecTrustRef trust = NULL; + SecCertificateRef cert = NULL, root = NULL; + SecPolicyRef policy = SecPolicyCreateSSL(false, NULL); + CFArrayRef certs = NULL; + + isnt(cert = SecCertificateCreateWithBytes(NULL, data, len), + NULL, "create cert"); + isnt(root = SecCertificateCreateWithBytes(NULL, UTNHardware_cer, sizeof(UTNHardware_cer)), NULL); + certs = CFArrayCreate(NULL, (const void **)&cert, 1, NULL); + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), + "create trust with single cert"); + ok_status(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)@[(__bridge id)root])); + + SecTrustResultType trustResult; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is(SecTrustGetCertificateCount(trust), chain_length, "cert count"); + is_status(trustResult, trust_result, "correct trustResult"); + CFRelease(trust); + CFRelease(policy); + CFRelease(certs); + CFRelease(cert); + CFReleaseNull(root); +} + +- (void)testBlocklistedCerts +{ + [self validate_one_cert:Global_Trustee_cer length:sizeof(Global_Trustee_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:login_yahoo_com_1_cer length:sizeof(login_yahoo_com_1_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + + /* this is the root, which isn't ok for ssl and fails here, but at the + same time it proves that kSecTrustResultFatalTrustFailure isn't + returned for policy failures that aren't blocklisting */ + [self validate_one_cert:login_yahoo_com_2_cer length:sizeof(login_yahoo_com_2_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:addons_mozilla_org_cer length:sizeof(addons_mozilla_org_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:login_yahoo_com_cer length:sizeof(login_yahoo_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:login_live_com_cer length:sizeof(login_live_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:mail_google_com_cer length:sizeof(mail_google_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:login_skype_com_cer length:sizeof(login_skype_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; + [self validate_one_cert:www_google_com_cer length:sizeof(www_google_com_cer) chain_length:2 trustResult:kSecTrustResultFatalTrustFailure]; +} + +@end + +@interface AllowlistTests : TrustEvaluationTestCase +@end + +@implementation AllowlistTests + +#if !TARGET_OS_BRIDGE +static SecCertificateRef createCertFromStaticData(const UInt8 *certData, CFIndex certLength) +{ + SecCertificateRef cert = NULL; + CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, certData, certLength, kCFAllocatorNull); + if (data) { + cert = SecCertificateCreateWithData(NULL, data); + CFRelease(data); + } + return cert; +} + +- (void)testLeafOnAllowList +{ + SecCertificateRef certs[3]; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFDateRef date = NULL; + CFArrayRef certArray = NULL; + CFArrayRef anchorsArray = NULL; + + isnt(certs[0] = createCertFromStaticData(leafOnAllowList_Cert, sizeof(leafOnAllowList_Cert)), + NULL, "allowlist: create leaf cert"); + isnt(certs[1] = createCertFromStaticData(ca1_Cert, sizeof(ca1_Cert)), + NULL, "allowlist: create intermediate ca 1"); + isnt(certs[2] = createCertFromStaticData(root_Cert, sizeof(root_Cert)), + NULL, "allowlist: create root"); + + isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 3, &kCFTypeArrayCallBacks), + NULL, "allowlist: create cert array"); + + /* create a trust reference with ssl policy */ + isnt(policy = SecPolicyCreateBasicX509(), NULL, "allowlist: create policy"); + ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "allowlist: create trust"); + + /* set evaluate date: January 6, 2020 at 2:40:00 AM PST */ + isnt(date = CFDateCreate(NULL, 600000000.0), NULL, "allowlist: create date"); + ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "allowlist: set verify date"); + + /* use a known root CA at this point in time to anchor the chain */ + isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[2], 1, &kCFTypeArrayCallBacks), + NULL, "allowlist: create anchors array"); + ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "allowlist: set anchors"); + + SecTrustResultType trustResult = kSecTrustResultInvalid; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "allowlist: evaluate"); + + /* expected result is kSecTrustResultUnspecified since cert is on allow list and its issuer chains to a trusted root */ + ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", + (int)trustResult); + + /* clean up */ + for(CFIndex idx=0; idx < 3; idx++) { + if (certs[idx]) { CFRelease(certs[idx]); } + } + if (policy) { CFRelease(policy); } + if (trust) { CFRelease(trust); } + if (date) { CFRelease(date); } + if (certArray) { CFRelease(certArray); } + if (anchorsArray) { CFRelease(anchorsArray); } +} + +- (void)testLeafNotOnAllowList +{ + SecCertificateRef certs[3]; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFDateRef date = NULL; + CFArrayRef certArray = NULL; + CFArrayRef anchorsArray = NULL; + + isnt(certs[0] = createCertFromStaticData(leafNotOnAllowList_Cert, sizeof(leafNotOnAllowList_Cert)), + NULL, "!allowlist: create leaf cert"); + isnt(certs[1] = createCertFromStaticData(ca1_Cert, sizeof(ca1_Cert)), + NULL, "!allowlist: create intermediate ca 1"); + isnt(certs[2] = createCertFromStaticData(root_Cert, sizeof(root_Cert)), + NULL, "!allowlist: create root"); + + isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 3, &kCFTypeArrayCallBacks), + NULL, "!allowlist: create cert array"); + + /* create a trust reference with basic policy */ + isnt(policy = SecPolicyCreateBasicX509(), NULL, "!allowlist: create policy"); + ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "!allowlist: create trust"); + + /* set evaluate date: January 6, 2020 at 2:40:00 AM PST */ + isnt(date = CFDateCreate(NULL, 600000000.0), NULL, "allowlist: create date"); + ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "!allowlist: set verify date"); + + /* use a known root CA at this point in time to anchor the chain */ + isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[2], 1, &kCFTypeArrayCallBacks), + NULL, "allowlist: create anchors array"); + ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "!allowlist: set anchors"); + + SecTrustResultType trustResult = kSecTrustResultInvalid; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "!allowlist: evaluate"); + + /* expected result is kSecTrustResultFatalTrustFailure, since cert is not on allow list */ + ok(trustResult == kSecTrustResultFatalTrustFailure, + "trustResult 6 expected (got %d)", (int)trustResult); + + /* clean up */ + for(CFIndex idx=0; idx < 3; idx++) { + if (certs[idx]) { CFRelease(certs[idx]); } + } + if (policy) { CFRelease(policy); } + if (trust) { CFRelease(trust); } + if (date) { CFRelease(date); } + if (certArray) { CFRelease(certArray); } + if (anchorsArray) { CFRelease(anchorsArray); } +} + +- (void)testAllowListForRootCA +{ + SecCertificateRef certs[3]; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFDateRef date = NULL; + CFArrayRef certArray = NULL; + CFArrayRef anchorsArray = NULL; + + isnt(certs[0] = createCertFromStaticData(leaf_subCANotOnAllowlist_Cert, sizeof(leaf_subCANotOnAllowlist_Cert)), + NULL, "!allowlist: create leaf cert"); + isnt(certs[1] = createCertFromStaticData(subCANotOnAllowlist_Cert, sizeof(subCANotOnAllowlist_Cert)), + NULL, "!allowlist: create intermediate ca 1"); + isnt(certs[2] = createCertFromStaticData(root_Cert, sizeof(root_Cert)), + NULL, "!allowlist: create root"); + + isnt(certArray = CFArrayCreate(kCFAllocatorDefault, (const void **)&certs[0], 3, &kCFTypeArrayCallBacks), + NULL, "!allowlist: create cert array"); + + /* create a trust reference with basic policy */ + isnt(policy = SecPolicyCreateBasicX509(), NULL, "!allowlist: create policy"); + ok_status(SecTrustCreateWithCertificates(certArray, policy, &trust), "!allowlist: create trust"); + + /* set evaluate date: January 6, 2020 at 2:40:00 AM PST */ + isnt(date = CFDateCreate(NULL, 600000000.0), NULL, "allowlist: create date"); + ok_status((date) ? SecTrustSetVerifyDate(trust, date) : errSecParam, "!allowlist: set verify date"); + + /* use a known root CA at this point in time to anchor the chain */ + isnt(anchorsArray = CFArrayCreate(NULL, (const void **)&certs[2], 1, &kCFTypeArrayCallBacks), + NULL, "allowlist: create anchors array"); + ok_status((anchorsArray) ? SecTrustSetAnchorCertificates(trust, anchorsArray) : errSecParam, "!allowlist: set anchors"); + + SecTrustResultType trustResult = kSecTrustResultInvalid; + ok_status(SecTrustGetTrustResult(trust, &trustResult), "!allowlist: evaluate"); + + /* expected result is kSecTrustResultRecoverableTrustFailure (if issuer is distrusted) + or kSecTrustResultFatalTrustFailure (if issuer is revoked), since cert is not on allow list */ + ok(trustResult == kSecTrustResultFatalTrustFailure, + "trustResult 6 expected (got %d)", (int)trustResult); + + /* clean up */ + for(CFIndex idx=0; idx < 3; idx++) { + if (certs[idx]) { CFRelease(certs[idx]); } + } + if (policy) { CFRelease(policy); } + if (trust) { CFRelease(trust); } + if (date) { CFRelease(date); } + if (certArray) { CFRelease(certArray); } + if (anchorsArray) { CFRelease(anchorsArray); } +} + +- (void)testDateBasedAllowListForRootCA +{ + SecCertificateRef root = NULL, beforeInt = NULL, afterInt = NULL, + beforeLeaf = NULL, afterLeaf = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + NSArray *anchors = nil, *certs = nil; + NSDate *verifyDate = nil; + SecTrustResultType trustResult = kSecTrustResultInvalid; + + require(root = SecCertificateCreateWithBytes(NULL, _datetest_root, sizeof(_datetest_root)), out); + require(beforeInt = SecCertificateCreateWithBytes(NULL, _datetest_before_int, sizeof(_datetest_before_int)), out); + require(afterInt = SecCertificateCreateWithBytes(NULL, _datetest_after_int, sizeof(_datetest_after_int)), out); + require(beforeLeaf = SecCertificateCreateWithBytes(NULL, _datetest_before_leaf, sizeof(_datetest_before_leaf)), out); + require(afterLeaf = SecCertificateCreateWithBytes(NULL, _datetest_after_leaf, sizeof(_datetest_after_leaf)), out); + + anchors = @[(__bridge id)root]; + require(policy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com")), out); + verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:504000000.0]; /* 21 Dec 2016 */ + + /* Leaf issued before cutoff should pass */ + certs = @[(__bridge id)beforeLeaf, (__bridge id)beforeInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultUnspecified, "leaf issued before cutoff failed evaluation"); + CFReleaseNull(trust); + trustResult = kSecTrustResultInvalid; + + /* Leaf issued after cutoff should fail */ + certs = @[(__bridge id)afterLeaf, (__bridge id)beforeInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultFatalTrustFailure, "leaf issued after cutoff succeeded evaluation"); + CFReleaseNull(trust); + trustResult = kSecTrustResultInvalid; + + /* Intermediate issued after cutoff should fail (even for leaf issued before) */ + certs = @[(__bridge id)beforeLeaf, (__bridge id)afterInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultFatalTrustFailure, "intermediate issued after cutoff succeeded evaluation"); + CFReleaseNull(trust); + trustResult = kSecTrustResultInvalid; + + /* Intermediate issued after cutoff should fail */ + certs = @[(__bridge id)afterLeaf, (__bridge id)afterInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultFatalTrustFailure, "intermediate issued before cutoff succeeded evaluation"); + CFReleaseNull(trust); + trustResult = kSecTrustResultInvalid; + + /* Leaf issued before cutoff should choose acceptable path */ + certs = @[(__bridge id)beforeLeaf, (__bridge id) afterInt, (__bridge id)beforeInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultUnspecified, "leaf issued before cutoff failed evaluation (multi-path)"); + CFReleaseNull(trust); + trustResult = kSecTrustResultInvalid; + + /* No good path for leaf issued after cutoff */ + certs = @[(__bridge id)afterLeaf, (__bridge id)beforeInt, (__bridge id)afterInt]; + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + is(trustResult, kSecTrustResultFatalTrustFailure, "leaf issued after cutoff succeeded evaluation (multi-path)"); + +out: + CFReleaseNull(root); + CFReleaseNull(beforeInt); + CFReleaseNull(afterInt); + CFReleaseNull(beforeLeaf); + CFReleaseNull(afterLeaf); + CFReleaseNull(policy); + CFReleaseNull(trust); +} + +- (void)testLeafOnAllowListOtherFailures +{ + SecCertificateRef certs[3]; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + NSArray *anchors = nil, *certArray = nil; + NSDate *verifyDate = nil; + SecTrustResultType trustResult = kSecTrustResultInvalid; + + memset(certs, 0, 3 * sizeof(SecCertificateRef)); + + require(certs[0] = SecCertificateCreateWithBytes(NULL, leafOnAllowList_Cert, sizeof(leafOnAllowList_Cert)), out); + require(certs[1] = SecCertificateCreateWithBytes(NULL, ca1_Cert, sizeof(ca1_Cert)), out); + require(certs[2] = SecCertificateCreateWithBytes(NULL, root_Cert, sizeof(root_Cert)), out); + + anchors = @[(__bridge id)certs[2]]; + certArray = @[(__bridge id)certs[0], (__bridge id)certs[1], (__bridge id)certs[2]]; + verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]; // January 6, 2020 at 2:40:00 AM PST + + /* Mismatched policy, should fail */ + require(policy = SecPolicyCreateSSL(true, (__bridge CFStringRef)@"example.com"), out); + require_noerr(SecTrustCreateWithCertificates((__bridge CFArrayRef)certArray, policy, &trust), out); + require_noerr(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), out); + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, + "hostname failure with cert on allow list succeeded evaluation"); + CFReleaseNull(policy); + trustResult = kSecTrustResultInvalid; + + /* Expired, should fail */ + verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:500000000.0]; // November 4, 2016 at 5:53:20 PM PDT + require_noerr(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verifyDate), out); + require_noerr(SecTrustSetPolicies(trust, policy), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, + "EKU failure with cert on allow list succeeded evaluation"); + CFReleaseNull(policy); + trustResult = kSecTrustResultInvalid; + + /* Apple pinning policy, should fail */ + require(policy = SecPolicyCreateAppleSSLPinned((__bridge CFStringRef)@"aPolicy", + (__bridge CFStringRef)@"example.com", NULL, + (__bridge CFStringRef)@"1.2.840.113635.100.6.27.12"), out); + require_noerr(SecTrustSetPolicies(trust, policy), out); + require_noerr(SecTrustGetTrustResult(trust, &trustResult), out); + ok(trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure, + "Apple pinning policy with cert on allow list succeeded evaluation"); + +out: + CFReleaseNull(certs[0]); + CFReleaseNull(certs[1]); + CFReleaseNull(certs[2]); + CFReleaseNull(policy); + CFReleaseNull(trust); +} +#else /* TARGET_OS_BRIDGE */ +/* Allowlists are provided by Valid, which is not supported on bridgeOS */ +- (void)testSkipTests +{ + XCTAssert(true); +} +#endif + +@end diff --git a/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests_data.h b/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests_data.h new file mode 100644 index 00000000..d52467c7 --- /dev/null +++ b/tests/TrustTests/EvaluationTests/AllowlistBlocklistTests_data.h @@ -0,0 +1,1691 @@ +// +// AllowlistBlocklistTests_data.h +// Security +// + +#ifndef _TRUSTTESTS_ALLOWLIST_BLOCKLIST_TESTS_ +#define _TRUSTTESTS_ALLOWLIST_BLOCKLIST_TESTS_ + +/* subject:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware */ +/* issuer :/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware */ +const uint8_t UTNHardware_cer[] = { + 0x30,0x82,0x04,0x74,0x30,0x82,0x03,0x5C,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x44, + 0xBE,0x0C,0x8B,0x50,0x00,0x24,0xB4,0x11,0xD3,0x36,0x2A,0xFE,0x65,0x0A,0xFD,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81, + 0x97,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x07,0x13,0x0E,0x53,0x61,0x6C,0x74,0x20,0x4C,0x61,0x6B,0x65,0x20, + 0x43,0x69,0x74,0x79,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x0A,0x13,0x15,0x54, + 0x68,0x65,0x20,0x55,0x53,0x45,0x52,0x54,0x52,0x55,0x53,0x54,0x20,0x4E,0x65,0x74, + 0x77,0x6F,0x72,0x6B,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x0B,0x13,0x18,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x75,0x73,0x65,0x72,0x74,0x72, + 0x75,0x73,0x74,0x2E,0x63,0x6F,0x6D,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x03, + 0x13,0x16,0x55,0x54,0x4E,0x2D,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2D, + 0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x30,0x1E,0x17,0x0D,0x39,0x39,0x30,0x37, + 0x30,0x39,0x31,0x38,0x31,0x30,0x34,0x32,0x5A,0x17,0x0D,0x31,0x39,0x30,0x37,0x30, + 0x39,0x31,0x38,0x31,0x39,0x32,0x32,0x5A,0x30,0x81,0x97,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x07,0x13,0x0E, + 0x53,0x61,0x6C,0x74,0x20,0x4C,0x61,0x6B,0x65,0x20,0x43,0x69,0x74,0x79,0x31,0x1E, + 0x30,0x1C,0x06,0x03,0x55,0x04,0x0A,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45, + 0x52,0x54,0x52,0x55,0x53,0x54,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x21, + 0x30,0x1F,0x06,0x03,0x55,0x04,0x0B,0x13,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x77,0x77,0x77,0x2E,0x75,0x73,0x65,0x72,0x74,0x72,0x75,0x73,0x74,0x2E,0x63,0x6F, + 0x6D,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55,0x54,0x4E,0x2D, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2D,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,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,0xB1,0xF7,0xC3,0x38,0x3F,0xB4,0xA8,0x7F,0xCF,0x39,0x82,0x51,0x67, + 0xD0,0x6D,0x9F,0xD2,0xFF,0x58,0xF3,0xE7,0x9F,0x2B,0xEC,0x0D,0x89,0x54,0x99,0xB9, + 0x38,0x99,0x16,0xF7,0xE0,0x21,0x79,0x48,0xC2,0xBB,0x61,0x74,0x12,0x96,0x1D,0x3C, + 0x6A,0x72,0xD5,0x3C,0x10,0x67,0x3A,0x39,0xED,0x2B,0x13,0xCD,0x66,0xEB,0x95,0x09, + 0x33,0xA4,0x6C,0x97,0xB1,0xE8,0xC6,0xEC,0xC1,0x75,0x79,0x9C,0x46,0x5E,0x8D,0xAB, + 0xD0,0x6A,0xFD,0xB9,0x2A,0x55,0x17,0x10,0x54,0xB3,0x19,0xF0,0x9A,0xF6,0xF1,0xB1, + 0x5D,0xB6,0xA7,0x6D,0xFB,0xE0,0x71,0x17,0x6B,0xA2,0x88,0xFB,0x00,0xDF,0xFE,0x1A, + 0x31,0x77,0x0C,0x9A,0x01,0x7A,0xB1,0x32,0xE3,0x2B,0x01,0x07,0x38,0x6E,0xC3,0xA5, + 0x5E,0x23,0xBC,0x45,0x9B,0x7B,0x50,0xC1,0xC9,0x30,0x8F,0xDB,0xE5,0x2B,0x7A,0xD3, + 0x5B,0xFB,0x33,0x40,0x1E,0xA0,0xD5,0x98,0x17,0xBC,0x8B,0x87,0xC3,0x89,0xD3,0x5D, + 0xA0,0x8E,0xB2,0xAA,0xAA,0xF6,0x8E,0x69,0x88,0x06,0xC5,0xFA,0x89,0x21,0xF3,0x08, + 0x9D,0x69,0x2E,0x09,0x33,0x9B,0x29,0x0D,0x46,0x0F,0x8C,0xCC,0x49,0x34,0xB0,0x69, + 0x51,0xBD,0xF9,0x06,0xCD,0x68,0xAD,0x66,0x4C,0xBC,0x3E,0xAC,0x61,0xBD,0x0A,0x88, + 0x0E,0xC8,0xDF,0x3D,0xEE,0x7C,0x04,0x4C,0x9D,0x0A,0x5E,0x6B,0x91,0xD6,0xEE,0xC7, + 0xED,0x28,0x8D,0xAB,0x4D,0x87,0x89,0x73,0xD0,0x6E,0xA4,0xD0,0x1E,0x16,0x8B,0x14, + 0xE1,0x76,0x44,0x03,0x7F,0x63,0xAC,0xE4,0xCD,0x49,0x9C,0xC5,0x92,0xF4,0xAB,0x32, + 0xA1,0x48,0x5B,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xB9,0x30,0x81,0xB6,0x30,0x0B, + 0x06,0x03,0x55,0x1D,0x0F,0x04,0x04,0x03,0x02,0x01,0xC6,0x30,0x0F,0x06,0x03,0x55, + 0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xA1,0x72,0x5F,0x26,0x1B,0x28,0x98,0x43,0x95, + 0x5D,0x07,0x37,0xD5,0x85,0x96,0x9D,0x4B,0xD2,0xC3,0x45,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,0x2E,0x75,0x73,0x65,0x72,0x74,0x72,0x75, + 0x73,0x74,0x2E,0x63,0x6F,0x6D,0x2F,0x55,0x54,0x4E,0x2D,0x55,0x53,0x45,0x52,0x46, + 0x69,0x72,0x73,0x74,0x2D,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2E,0x63,0x72, + 0x6C,0x30,0x31,0x06,0x03,0x55,0x1D,0x25,0x04,0x2A,0x30,0x28,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x05, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x06,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x07,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x47,0x19,0x0F,0xDE,0x74,0xC6,0x99,0x97, + 0xAF,0xFC,0xAD,0x28,0x5E,0x75,0x8E,0xEB,0x2D,0x67,0xEE,0x4E,0x7B,0x2B,0xD7,0x0C, + 0xFF,0xF6,0xDE,0xCB,0x55,0xA2,0x0A,0xE1,0x4C,0x54,0x65,0x93,0x60,0x6B,0x9F,0x12, + 0x9C,0xAD,0x5E,0x83,0x2C,0xEB,0x5A,0xAE,0xC0,0xE4,0x2D,0xF4,0x00,0x63,0x1D,0xB8, + 0xC0,0x6C,0xF2,0xCF,0x49,0xBB,0x4D,0x93,0x6F,0x06,0xA6,0x0A,0x22,0xB2,0x49,0x62, + 0x08,0x4E,0xFF,0xC8,0xC8,0x14,0xB2,0x88,0x16,0x5D,0xE7,0x01,0xE4,0x12,0x95,0xE5, + 0x45,0x34,0xB3,0x8B,0x69,0xBD,0xCF,0xB4,0x85,0x8F,0x75,0x51,0x9E,0x7D,0x3A,0x38, + 0x3A,0x14,0x48,0x12,0xC6,0xFB,0xA7,0x3B,0x1A,0x8D,0x0D,0x82,0x40,0x07,0xE8,0x04, + 0x08,0x90,0xA1,0x89,0xCB,0x19,0x50,0xDF,0xCA,0x1C,0x01,0xBC,0x1D,0x04,0x19,0x7B, + 0x10,0x76,0x97,0x3B,0xEE,0x90,0x90,0xCA,0xC4,0x0E,0x1F,0x16,0x6E,0x75,0xEF,0x33, + 0xF8,0xD3,0x6F,0x5B,0x1E,0x96,0xE3,0xE0,0x74,0x77,0x74,0x7B,0x8A,0xA2,0x6E,0x2D, + 0xDD,0x76,0xD6,0x39,0x30,0x82,0xF0,0xAB,0x9C,0x52,0xF2,0x2A,0xC7,0xAF,0x49,0x5E, + 0x7E,0xC7,0x68,0xE5,0x82,0x81,0xC8,0x6A,0x27,0xF9,0x27,0x88,0x2A,0xD5,0x58,0x50, + 0x95,0x1F,0xF0,0x3B,0x1C,0x57,0xBB,0x7D,0x14,0x39,0x62,0x2B,0x9A,0xC9,0x94,0x92, + 0x2A,0xA3,0x22,0x0C,0xFF,0x89,0x26,0x7D,0x5F,0x23,0x2B,0x47,0xD7,0x15,0x1D,0xA9, + 0x6A,0x9E,0x51,0x0D,0x2A,0x51,0x9E,0x81,0xF9,0xD4,0x3B,0x5E,0x70,0x12,0x7F,0x10, + 0x32,0x9C,0x1E,0xBB,0x9D,0xF8,0x66,0xA8, +}; + +unsigned char Global_Trustee_cer[] = { + 0x30,0x82,0x06,0xdd,0x30,0x82,0x05,0xc5,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0xd8,0xf3,0x5f,0x4e, + 0xb7,0x87,0x2b,0x2d,0xab,0x06,0x92,0xe3,0x15,0x38,0x2f,0xb0,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xe3,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x07,0x13,0x05,0x54,0x61,0x6d,0x70,0x61,0x31, + 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c,0x61,0x67, + 0x65,0x20,0x31,0x30,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x47,0x6c,0x6f,0x62,0x61, + 0x6c,0x20,0x54,0x72,0x75,0x73,0x74,0x65,0x65,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0b,0x13,0x0e, + 0x47,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x54,0x72,0x75,0x73,0x74,0x65,0x65,0x31,0x28,0x30,0x26,0x06,0x03, + 0x55,0x04,0x0b,0x13,0x1f,0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47, + 0x72,0x6f,0x75,0x70,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12, + 0x06,0x03,0x55,0x04,0x0b,0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x17, + 0x30,0x15,0x06,0x03,0x55,0x04,0x03,0x13,0x0e,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x74,0x72,0x75,0x73, + 0x74,0x65,0x65,0x30,0x82,0x02,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, + 0x05,0x00,0x03,0x82,0x02,0x0f,0x00,0x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,0x00,0xd9,0x74,0xf2,0xaa, + 0x41,0x1d,0xdf,0xf5,0xc2,0x16,0x43,0x49,0x5c,0x29,0xbf,0xb6,0x89,0x74,0x29,0xbc,0x9c,0x8d,0x0c,0x46, + 0x4f,0x59,0x7e,0xb2,0x41,0x17,0x66,0x34,0x0c,0x65,0x89,0xe1,0x6c,0x25,0xe3,0x86,0x0a,0x9e,0x22,0x45, + 0x22,0x8c,0xdd,0x9d,0xe6,0xa3,0x95,0xde,0xdc,0x88,0x02,0x55,0x5c,0xe3,0x5b,0x91,0x75,0xeb,0x26,0x69, + 0x63,0xb9,0x2e,0xc6,0xca,0x2e,0x27,0xdf,0x88,0xba,0x02,0x20,0x6e,0xfe,0xb9,0x0b,0x29,0xd7,0xa7,0xd6, + 0xd7,0x48,0x1a,0x1c,0xce,0xdd,0x1f,0xa9,0x27,0x0e,0x62,0x4f,0xa1,0x96,0x1e,0xdd,0x54,0x3a,0x34,0x63, + 0x4a,0x76,0xf5,0x77,0x7d,0x59,0x67,0xd8,0x10,0xd4,0xb5,0x0f,0x3a,0x43,0x22,0x98,0xdb,0xf4,0x09,0xc4, + 0x0a,0x70,0xce,0xdd,0x90,0xd4,0x2f,0xef,0x74,0x13,0xc3,0xcd,0xc2,0x89,0x39,0x62,0x15,0x9d,0xe6,0x74, + 0xa8,0xe8,0x9b,0xf0,0x63,0x6e,0x9c,0x89,0xb6,0x0e,0xad,0x9b,0xf7,0xcc,0x82,0xe8,0xe8,0x2d,0xb8,0x0b, + 0xda,0x22,0xec,0x49,0x85,0x07,0x88,0x99,0x98,0x3f,0xf4,0x74,0xa9,0x09,0xf7,0x81,0x7c,0x97,0x0b,0x59, + 0x99,0x18,0x72,0x8b,0xdb,0x94,0x82,0x2b,0xa7,0xe8,0xaa,0x6b,0x97,0xbf,0x88,0x7e,0x75,0xb0,0x8b,0x45, + 0x45,0x0c,0xc7,0xa8,0x09,0xea,0x1b,0x41,0x58,0x30,0x3b,0x5f,0x78,0x65,0x15,0x34,0xd2,0xe4,0x3c,0x34, + 0x0d,0x1d,0xd8,0x64,0x3c,0x8a,0xa5,0x56,0x49,0x99,0x28,0x2d,0x4b,0xf2,0xcf,0xcd,0xd9,0x6e,0x49,0x64, + 0x9b,0xa9,0x79,0x90,0x77,0x55,0xa9,0x08,0x1b,0xad,0x1a,0x74,0x9e,0xe0,0x03,0x93,0x0a,0x09,0xb7,0xad, + 0xa7,0xb4,0x5c,0xef,0x83,0x6c,0xb7,0x9a,0xb4,0xc6,0x68,0x40,0x80,0x1d,0x42,0xd1,0x6e,0x79,0x9b,0xa9, + 0x19,0x21,0x9a,0x9c,0xf9,0x86,0x2d,0x00,0xd1,0x34,0xfe,0xe0,0xb6,0xf9,0x55,0xb6,0xf5,0x26,0xc5,0x95, + 0x16,0xa5,0x7c,0x73,0x9f,0x0a,0x29,0x89,0xac,0x3a,0x98,0xf7,0x9b,0x74,0x67,0xb7,0x90,0xb7,0x5d,0x09, + 0x23,0x6a,0x6a,0xed,0x2c,0x10,0xee,0x53,0x0a,0x10,0xf0,0x16,0x1f,0x57,0xb3,0xb1,0x0d,0x79,0x91,0x19, + 0xb0,0xeb,0xcd,0x30,0x3f,0xa0,0x14,0x5f,0xb3,0xc6,0xfd,0x5c,0x33,0xa7,0xb0,0xff,0x98,0xb0,0x55,0x8c, + 0xb9,0xa5,0xf2,0x6f,0x47,0x24,0x49,0x21,0x69,0xcc,0x42,0xa2,0x51,0x00,0x40,0x85,0x8c,0x82,0x82,0xab, + 0x32,0xa5,0xcb,0x9a,0xdc,0xd0,0xd9,0x18,0x0d,0xdf,0x19,0xf4,0xaf,0x83,0x0d,0xc1,0x3e,0x31,0xdb,0x24, + 0x48,0xb6,0x75,0x80,0xa1,0xe1,0xc9,0x77,0x64,0x1e,0xa7,0xe5,0x8b,0x7f,0x15,0x4d,0x4b,0xa7,0xc2,0xd0, + 0xed,0x79,0x95,0x5e,0x91,0x31,0xec,0x18,0xff,0x4e,0x9f,0x48,0x14,0xea,0x75,0xba,0x21,0xce,0x29,0x76, + 0xe9,0x1f,0x4e,0x51,0x87,0x2e,0xb3,0xcc,0x04,0x60,0xba,0x23,0x1f,0x1f,0x65,0xb2,0x0a,0xb8,0xd5,0x6e, + 0x8f,0x4b,0x42,0x89,0x47,0xa9,0x81,0x90,0x5b,0x2b,0xb2,0xb6,0xae,0xe6,0xa0,0x70,0x7b,0x78,0x90,0x0a, + 0x7a,0xc5,0xe5,0xe7,0xc5,0xfb,0x0a,0xf6,0x2f,0x69,0x8c,0x8c,0x1f,0x57,0xe0,0x06,0x99,0xff,0x11,0xd5, + 0x52,0x32,0x20,0x97,0x27,0x98,0xee,0x65,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xd4,0x30,0x82,0x01, + 0xd0,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28, + 0x98,0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x0e,0x04,0x16,0x04,0x14,0xb7,0xc3,0xde,0x1a,0x43,0xed,0x41,0x97,0xa9,0x8f,0x29,0x78,0x9c,0x03,0xb9, + 0xac,0x40,0x42,0x00,0xac,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05, + 0xa0,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55, + 0x1d,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06, + 0x0c,0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b, + 0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63, + 0x75,0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b, + 0x06,0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74, + 0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d, + 0x2f,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77, + 0x61,0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a, + 0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e, + 0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e, + 0x63,0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30, + 0x3b,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x63,0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e, + 0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74, + 0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x19, + 0x06,0x03,0x55,0x1d,0x11,0x04,0x12,0x30,0x10,0x82,0x0e,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x74,0x72, + 0x75,0x73,0x74,0x65,0x65,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x8f,0xba,0x75,0xba,0x39,0xd4,0x26,0xd3,0x70,0x0f,0xc4,0xb3,0x02,0xa7,0xc5, + 0x12,0x23,0x71,0xc9,0xfe,0x63,0xe9,0xa3,0x62,0x78,0x24,0x44,0x4f,0xd4,0xb9,0x11,0x3e,0x1f,0xc7,0x28, + 0xe7,0x55,0x6b,0xee,0xf4,0xe1,0x00,0x91,0x86,0x8a,0xc9,0x09,0x6b,0x9f,0x2e,0xa4,0x45,0x39,0xd1,0x61, + 0x62,0x5e,0x93,0xa5,0x05,0x45,0x78,0x9f,0x60,0x12,0x2c,0xf4,0x6c,0x65,0x65,0x0d,0xcc,0x46,0x34,0x8b, + 0x28,0xba,0xa0,0xc6,0xf4,0x99,0x71,0x64,0xf3,0x22,0x76,0xac,0x4f,0xf3,0x62,0xc9,0xa7,0x33,0x5a,0x07, + 0x1f,0x3d,0xc9,0x86,0x80,0xdc,0xdb,0x04,0x2f,0x87,0x27,0xe8,0xbf,0x48,0x44,0x81,0xc0,0xf0,0x49,0x23, + 0x6e,0x1f,0xe5,0xe4,0x03,0x86,0x24,0x13,0xa2,0x85,0x62,0x7c,0x58,0x04,0xca,0xe6,0x8d,0x13,0x72,0x0a, + 0xba,0x56,0x44,0xa2,0x0f,0xbc,0xfb,0xa0,0x3d,0x0d,0x2a,0x7f,0xfb,0x9e,0xa9,0x09,0x3d,0xb7,0x5a,0xd4, + 0x8a,0x8d,0xe1,0x25,0xe8,0xa4,0x09,0x84,0x70,0xad,0x12,0x44,0xb9,0xcf,0xb9,0x33,0x7a,0xba,0x5c,0xe6, + 0x4b,0xa6,0xbb,0x05,0x06,0x98,0xff,0xf2,0x98,0x52,0x7b,0x77,0x80,0x27,0x4a,0xd9,0xe2,0xfa,0xb9,0x52, + 0xd4,0xfb,0xfb,0xe6,0xd6,0x2d,0x9e,0x8f,0xc1,0x15,0x44,0x8d,0x9b,0x74,0x2f,0xee,0x94,0x5a,0x4e,0xd3, + 0xc4,0x8b,0x8a,0xac,0x43,0x9d,0x73,0xf6,0xae,0x0c,0x87,0x89,0xad,0x87,0xc9,0xc9,0xc7,0xdd,0xba,0x14, + 0x60,0x7a,0xf8,0xb5,0x35,0x9d,0xc2,0x8d,0xc6,0x96,0x81,0x0d,0xa9,0x52,0x8a,0x29,0x40,0x04,0xe9,0x19, + 0xb4 +}; +unsigned int Global_Trustee_cer_len = 1761; + +unsigned char UTN_USERFirst_Hardware_cer[] = { + 0x30,0x82,0x04,0x74,0x30,0x82,0x03,0x5c,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x44,0xbe,0x0c,0x8b,0x50, + 0x00,0x24,0xb4,0x11,0xd3,0x36,0x2a,0xfe,0x65,0x0a,0xfd,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, + 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74,0x79, + 0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52,0x54, + 0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55,0x04, + 0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74,0x72, + 0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55,0x54, + 0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65, + 0x30,0x1e,0x17,0x0d,0x39,0x39,0x30,0x37,0x30,0x39,0x31,0x38,0x31,0x30,0x34,0x32,0x5a,0x17,0x0d,0x31, + 0x39,0x30,0x37,0x30,0x39,0x31,0x38,0x31,0x39,0x32,0x32,0x5a,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55, + 0x54,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b, + 0x65,0x20,0x43,0x69,0x74,0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65, + 0x20,0x55,0x53,0x45,0x52,0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21, + 0x30,0x1f,0x06,0x03,0x55,0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e, + 0x75,0x73,0x65,0x72,0x74,0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55, + 0x04,0x03,0x13,0x16,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61, + 0x72,0x64,0x77,0x61,0x72,0x65,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,0xb1, + 0xf7,0xc3,0x38,0x3f,0xb4,0xa8,0x7f,0xcf,0x39,0x82,0x51,0x67,0xd0,0x6d,0x9f,0xd2,0xff,0x58,0xf3,0xe7, + 0x9f,0x2b,0xec,0x0d,0x89,0x54,0x99,0xb9,0x38,0x99,0x16,0xf7,0xe0,0x21,0x79,0x48,0xc2,0xbb,0x61,0x74, + 0x12,0x96,0x1d,0x3c,0x6a,0x72,0xd5,0x3c,0x10,0x67,0x3a,0x39,0xed,0x2b,0x13,0xcd,0x66,0xeb,0x95,0x09, + 0x33,0xa4,0x6c,0x97,0xb1,0xe8,0xc6,0xec,0xc1,0x75,0x79,0x9c,0x46,0x5e,0x8d,0xab,0xd0,0x6a,0xfd,0xb9, + 0x2a,0x55,0x17,0x10,0x54,0xb3,0x19,0xf0,0x9a,0xf6,0xf1,0xb1,0x5d,0xb6,0xa7,0x6d,0xfb,0xe0,0x71,0x17, + 0x6b,0xa2,0x88,0xfb,0x00,0xdf,0xfe,0x1a,0x31,0x77,0x0c,0x9a,0x01,0x7a,0xb1,0x32,0xe3,0x2b,0x01,0x07, + 0x38,0x6e,0xc3,0xa5,0x5e,0x23,0xbc,0x45,0x9b,0x7b,0x50,0xc1,0xc9,0x30,0x8f,0xdb,0xe5,0x2b,0x7a,0xd3, + 0x5b,0xfb,0x33,0x40,0x1e,0xa0,0xd5,0x98,0x17,0xbc,0x8b,0x87,0xc3,0x89,0xd3,0x5d,0xa0,0x8e,0xb2,0xaa, + 0xaa,0xf6,0x8e,0x69,0x88,0x06,0xc5,0xfa,0x89,0x21,0xf3,0x08,0x9d,0x69,0x2e,0x09,0x33,0x9b,0x29,0x0d, + 0x46,0x0f,0x8c,0xcc,0x49,0x34,0xb0,0x69,0x51,0xbd,0xf9,0x06,0xcd,0x68,0xad,0x66,0x4c,0xbc,0x3e,0xac, + 0x61,0xbd,0x0a,0x88,0x0e,0xc8,0xdf,0x3d,0xee,0x7c,0x04,0x4c,0x9d,0x0a,0x5e,0x6b,0x91,0xd6,0xee,0xc7, + 0xed,0x28,0x8d,0xab,0x4d,0x87,0x89,0x73,0xd0,0x6e,0xa4,0xd0,0x1e,0x16,0x8b,0x14,0xe1,0x76,0x44,0x03, + 0x7f,0x63,0xac,0xe4,0xcd,0x49,0x9c,0xc5,0x92,0xf4,0xab,0x32,0xa1,0x48,0x5b,0x02,0x03,0x01,0x00,0x01, + 0xa3,0x81,0xb9,0x30,0x81,0xb6,0x30,0x0b,0x06,0x03,0x55,0x1d,0x0f,0x04,0x04,0x03,0x02,0x01,0xc6,0x30, + 0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1d,0x06,0x03, + 0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98,0x43,0x95,0x5d,0x07,0x37,0xd5, + 0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,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,0x2e,0x75,0x73,0x65, + 0x72,0x74,0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46, + 0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x31,0x06, + 0x03,0x55,0x1d,0x25,0x04,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08, + 0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x05,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x06,0x06,0x08, + 0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x07,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01, + 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x47,0x19,0x0f,0xde,0x74,0xc6,0x99,0x97,0xaf,0xfc,0xad,0x28, + 0x5e,0x75,0x8e,0xeb,0x2d,0x67,0xee,0x4e,0x7b,0x2b,0xd7,0x0c,0xff,0xf6,0xde,0xcb,0x55,0xa2,0x0a,0xe1, + 0x4c,0x54,0x65,0x93,0x60,0x6b,0x9f,0x12,0x9c,0xad,0x5e,0x83,0x2c,0xeb,0x5a,0xae,0xc0,0xe4,0x2d,0xf4, + 0x00,0x63,0x1d,0xb8,0xc0,0x6c,0xf2,0xcf,0x49,0xbb,0x4d,0x93,0x6f,0x06,0xa6,0x0a,0x22,0xb2,0x49,0x62, + 0x08,0x4e,0xff,0xc8,0xc8,0x14,0xb2,0x88,0x16,0x5d,0xe7,0x01,0xe4,0x12,0x95,0xe5,0x45,0x34,0xb3,0x8b, + 0x69,0xbd,0xcf,0xb4,0x85,0x8f,0x75,0x51,0x9e,0x7d,0x3a,0x38,0x3a,0x14,0x48,0x12,0xc6,0xfb,0xa7,0x3b, + 0x1a,0x8d,0x0d,0x82,0x40,0x07,0xe8,0x04,0x08,0x90,0xa1,0x89,0xcb,0x19,0x50,0xdf,0xca,0x1c,0x01,0xbc, + 0x1d,0x04,0x19,0x7b,0x10,0x76,0x97,0x3b,0xee,0x90,0x90,0xca,0xc4,0x0e,0x1f,0x16,0x6e,0x75,0xef,0x33, + 0xf8,0xd3,0x6f,0x5b,0x1e,0x96,0xe3,0xe0,0x74,0x77,0x74,0x7b,0x8a,0xa2,0x6e,0x2d,0xdd,0x76,0xd6,0x39, + 0x30,0x82,0xf0,0xab,0x9c,0x52,0xf2,0x2a,0xc7,0xaf,0x49,0x5e,0x7e,0xc7,0x68,0xe5,0x82,0x81,0xc8,0x6a, + 0x27,0xf9,0x27,0x88,0x2a,0xd5,0x58,0x50,0x95,0x1f,0xf0,0x3b,0x1c,0x57,0xbb,0x7d,0x14,0x39,0x62,0x2b, + 0x9a,0xc9,0x94,0x92,0x2a,0xa3,0x22,0x0c,0xff,0x89,0x26,0x7d,0x5f,0x23,0x2b,0x47,0xd7,0x15,0x1d,0xa9, + 0x6a,0x9e,0x51,0x0d,0x2a,0x51,0x9e,0x81,0xf9,0xd4,0x3b,0x5e,0x70,0x12,0x7f,0x10,0x32,0x9c,0x1e,0xbb, + 0x9d,0xf8,0x66,0xa8 +}; +unsigned int UTN_USERFirst_Hardware_cer_len = 1144; + +unsigned char addons_mozilla_org_cer[] = { + 0x30,0x82,0x05,0xf8,0x30,0x82,0x04,0xe0,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0x92,0x39,0xd5,0x34, + 0x8f,0x40,0xd1,0x69,0x5a,0x74,0x54,0x70,0xe1,0xf2,0x3f,0x43,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xe2,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73, + 0x68,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c, + 0x61,0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f, + 0x67,0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54, + 0x65,0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, + 0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20, + 0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b, + 0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x1b,0x30,0x19,0x06,0x03,0x55, + 0x04,0x03,0x13,0x12,0x61,0x64,0x64,0x6f,0x6e,0x73,0x2e,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f, + 0x72,0x67,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,0xab,0xc6,0x6d,0x36,0xf3, + 0x15,0x73,0x78,0x83,0x73,0xce,0x74,0x85,0xd5,0xae,0xec,0xb2,0xf0,0xe0,0x24,0x1f,0x13,0x83,0xb8,0x20, + 0xac,0xbb,0x9a,0xfe,0x88,0xbb,0xab,0xa1,0x1d,0x0b,0x1f,0x45,0x00,0xaa,0x49,0xb7,0x35,0x37,0x0c,0x6a, + 0xef,0x47,0x4c,0xb9,0xd1,0xbe,0xe3,0x57,0x12,0x04,0x8d,0x92,0xc7,0xb6,0xec,0x01,0xbc,0xb6,0xda,0xc7, + 0x81,0x38,0x20,0xad,0x72,0x85,0xe6,0x0e,0xfc,0x81,0x6c,0x07,0xad,0x68,0x76,0x38,0xc5,0x44,0xd7,0xcc, + 0xc6,0x4a,0xc5,0x97,0x3e,0x64,0xf4,0x51,0xe6,0xf0,0x7e,0xb2,0xec,0x56,0xf7,0x25,0x82,0x4d,0x49,0x98, + 0xcb,0x16,0x98,0xdd,0x23,0xf1,0x89,0x91,0xd1,0x17,0x97,0x40,0x99,0x26,0xd6,0xe2,0xa2,0x2b,0x5e,0xdf, + 0xbd,0x89,0xf2,0x1b,0x1a,0x53,0x2d,0xcc,0x50,0x41,0x7a,0xd0,0x3d,0x2a,0x0c,0x55,0x70,0x14,0x01,0xe9, + 0x58,0x49,0x10,0x7a,0x0b,0x93,0x82,0x8b,0xe1,0x1e,0xed,0x3a,0x80,0x10,0x82,0xce,0x96,0x8a,0x34,0xf0, + 0xcc,0xd7,0xd3,0xb9,0xb4,0x50,0x87,0x55,0x54,0x09,0xb8,0x9d,0x42,0x28,0x55,0x00,0xe5,0x8c,0x35,0x54, + 0xbf,0xdd,0x25,0x91,0x46,0xb7,0x0d,0xe5,0x5d,0x83,0xa8,0xe5,0x8b,0xfb,0x84,0xe4,0x3c,0xae,0x76,0xda, + 0xc4,0x43,0x2b,0x5b,0x74,0x0b,0xf8,0xbe,0x5d,0x68,0xf1,0x78,0x5b,0xb5,0xce,0x7d,0xf1,0x5d,0x99,0x40, + 0xda,0xca,0xee,0x38,0x81,0x50,0xbe,0x98,0xa1,0x6c,0xb8,0x24,0xad,0xf3,0xaf,0x8c,0x0f,0xd7,0x11,0x28, + 0x2c,0x84,0x18,0x4c,0x7d,0xb5,0xd9,0x8f,0x30,0xb5,0x1b,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xf0, + 0x30,0x82,0x01,0xec,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f, + 0x26,0x1b,0x28,0x98,0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06, + 0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xdd,0x80,0xd2,0x54,0x3d,0xf7,0x4c,0x70,0xca,0xa3,0xb0,0xdd, + 0x34,0x7a,0x32,0xe4,0xe8,0x3b,0x5a,0x3b,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04, + 0x03,0x02,0x05,0xa0,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d, + 0x06,0x03,0x55,0x1d,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06, + 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d, + 0x30,0x3b,0x06,0x0c,0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f, + 0x73,0x65,0x63,0x75,0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50, + 0x53,0x30,0x7b,0x06,0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32, + 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e, + 0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61, + 0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74, + 0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65, + 0x30,0x63,0x30,0x3b,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e, + 0x63,0x72,0x74,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74, + 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f, + 0x6d,0x30,0x35,0x06,0x03,0x55,0x1d,0x11,0x04,0x2e,0x30,0x2c,0x82,0x12,0x61,0x64,0x64,0x6f,0x6e,0x73, + 0x2e,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x82,0x16,0x77,0x77,0x77,0x2e,0x61,0x64, + 0x64,0x6f,0x6e,0x73,0x2e,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x30,0x0d,0x06,0x09, + 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x33,0x3b,0x63,0x15, + 0xfc,0xb1,0xec,0x14,0x2c,0x93,0xdd,0x75,0x94,0xde,0x81,0x5a,0xd9,0x4e,0x99,0xbe,0xfb,0x4a,0xa4,0x39, + 0x55,0x4d,0xa1,0x40,0x7a,0xde,0x13,0x2a,0x87,0xa9,0x37,0xcf,0xe8,0xd5,0xfb,0xad,0xd1,0x7b,0x6d,0x6f, + 0x8c,0x20,0x87,0x82,0x54,0xe6,0x57,0x49,0xbc,0x20,0x28,0x84,0xcd,0xd6,0x01,0xd9,0x93,0x8b,0x17,0x6e, + 0x23,0x66,0xe5,0x84,0xc8,0x80,0x3f,0xc6,0xa1,0x70,0x80,0xe4,0xec,0x4d,0x1d,0xf9,0xfc,0x91,0x5a,0x73, + 0x62,0x29,0x9a,0xf7,0x20,0x1c,0x61,0xe0,0x8b,0x39,0x9f,0xca,0xbc,0x7e,0x8d,0xdd,0xbc,0xd9,0xb1,0xe3, + 0x9f,0x9e,0xdf,0x15,0x53,0x91,0x21,0x52,0x0b,0xd9,0x1a,0x23,0x0f,0x66,0x36,0xdb,0xac,0x93,0x96,0x4a, + 0xa3,0xa5,0x22,0xcf,0x29,0xf7,0xa2,0x99,0xa8,0xf6,0xb6,0xd9,0x40,0xae,0xd9,0x7e,0xb6,0xf6,0x58,0x2e, + 0x9b,0xac,0x36,0xca,0x64,0x8f,0x65,0x52,0xdc,0x86,0x9c,0x82,0xab,0x6e,0x50,0x4b,0xda,0x5f,0xfa,0x05, + 0x00,0x88,0x30,0x0e,0xde,0x8d,0x56,0xbf,0x81,0x47,0x8d,0x3d,0x06,0xe2,0xb2,0x62,0x92,0x67,0x8f,0x9e, + 0xc8,0x9a,0xb2,0xe5,0x06,0xb8,0x70,0x24,0xb8,0x77,0x7c,0x23,0x0a,0x38,0xc3,0x79,0x08,0xd8,0xb1,0x51, + 0x9d,0xac,0x95,0x11,0xc7,0x40,0x17,0x9e,0xa3,0x1c,0x8f,0xf2,0x11,0xa7,0x68,0x27,0xda,0x49,0x05,0x84, + 0x18,0x7c,0x58,0x2d,0x01,0x67,0x5c,0xe5,0x9f,0xa1,0x29,0xbb,0x4a,0x39,0x45,0x2f,0xbf,0x11,0xaa,0x79, + 0xa2,0xed,0xb4,0xd4,0xb5,0x65,0x43,0xb7,0x93,0x46,0x8a,0xd3 +}; +unsigned int addons_mozilla_org_cer_len = 1532; + +unsigned char login_live_com_cer[] = { + 0x30,0x82,0x05,0xec,0x30,0x82,0x04,0xd4,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0xb0,0xb7,0x13,0x3e, + 0xd0,0x96,0xf9,0xb5,0x6f,0xae,0x91,0xc8,0x74,0xbd,0x3a,0xc0,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xde,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73, + 0x68,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c, + 0x61,0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f, + 0x67,0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54, + 0x65,0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, + 0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20, + 0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b, + 0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x17,0x30,0x15,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0e,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x6c,0x69,0x76,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,0xf3,0xfc,0x2b,0x2f,0xef,0xe1,0xad,0x59,0xf0, + 0x42,0x3c,0xc2,0xf1,0x82,0xbf,0x2c,0x41,0x93,0xd1,0xf6,0x98,0x33,0x95,0x4c,0xbc,0x62,0xf1,0x95,0x58, + 0x08,0xb6,0xe9,0x7b,0x77,0x48,0xb0,0xd3,0xdc,0x17,0x3f,0xbc,0x6e,0xe6,0xec,0x1e,0xec,0x8d,0x17,0xfe, + 0x1c,0x24,0xc6,0x3e,0x67,0x3d,0x92,0x95,0xa2,0x30,0xc0,0xa7,0x57,0x20,0xcf,0x70,0x88,0x97,0x4a,0x05, + 0x93,0x79,0x93,0x42,0x97,0x2f,0x3e,0xff,0xc4,0x14,0x14,0x28,0xa2,0x13,0x36,0xb4,0xf8,0xee,0xbe,0x1d, + 0xbc,0x78,0x5d,0x61,0x93,0x5f,0xeb,0x88,0xd7,0xd1,0xe4,0x2b,0x9a,0xcd,0x58,0xe2,0x07,0x45,0x9f,0x4f, + 0xb8,0xb9,0x40,0x6a,0x33,0x2c,0x5b,0x21,0x03,0x5a,0x4a,0x94,0xf2,0x7a,0x97,0x59,0x1b,0xa8,0xb5,0x42, + 0xd8,0x83,0x00,0xaa,0x34,0xcc,0xa7,0x76,0xd0,0x47,0x03,0x5f,0x05,0xaf,0x3b,0xe1,0xb9,0xa1,0x34,0x25, + 0xb7,0x6c,0x5f,0x9a,0x30,0x84,0x98,0xc2,0xc2,0xd7,0xf2,0xb8,0x42,0x4a,0x10,0x55,0xbd,0xfa,0x53,0x81, + 0x5d,0x8d,0x68,0x66,0x45,0x2c,0x52,0x7e,0xe5,0xc4,0x04,0xc3,0x54,0xe7,0xc3,0x39,0xda,0x7a,0x4a,0xc5, + 0xb9,0x98,0x82,0x20,0xe1,0x2c,0x60,0x57,0xbf,0xba,0xf2,0x46,0x00,0xbc,0x5f,0x3a,0xdc,0xe3,0x33,0x97, + 0xf8,0x4a,0x98,0xb9,0xec,0x33,0x4f,0x2d,0x60,0x6c,0x15,0x92,0xa6,0x81,0x4a,0x0b,0xe9,0xec,0x76,0x70, + 0x34,0x31,0x17,0x70,0xe6,0x70,0x4b,0x8e,0x8b,0xd3,0x75,0xcb,0x78,0x49,0xab,0x66,0x9b,0x86,0x9f,0x8f, + 0xa9,0xc4,0x01,0xe8,0xca,0x1b,0xe7,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xe8,0x30,0x82,0x01,0xe4, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98, + 0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e, + 0x04,0x16,0x04,0x14,0xd4,0x64,0xf6,0xa9,0xe8,0xa5,0x7e,0xd7,0xbf,0x63,0x52,0x03,0x83,0x53,0xdb,0xc5, + 0x41,0x8d,0xea,0x80,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0, + 0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06,0x0c, + 0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63,0x75, + 0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b,0x06, + 0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e,0x2d, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63, + 0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3b, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x2d,0x06, + 0x03,0x55,0x1d,0x11,0x04,0x26,0x30,0x24,0x82,0x0e,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x6c,0x69,0x76,0x65, + 0x2e,0x63,0x6f,0x6d,0x82,0x12,0x77,0x77,0x77,0x2e,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x6c,0x69,0x76,0x65, + 0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x54,0xe3,0xa4,0x9a,0x24,0xd2,0xf3,0x1d,0x42,0xad,0x1b,0xf0,0x1e,0xab,0xfb,0xda, + 0xd5,0xaa,0xe9,0xcf,0x5a,0xb3,0x1e,0x57,0x7b,0x31,0xf2,0x6e,0x57,0x4b,0x31,0xaf,0x33,0xbb,0xb6,0x0d, + 0x15,0xc7,0x5e,0x59,0x01,0xce,0x44,0xb5,0xb7,0xbf,0x09,0xc9,0xd5,0xdc,0x69,0x84,0xe9,0xc5,0x1a,0xb7, + 0xf0,0x3e,0xd4,0xc0,0x24,0xbd,0x29,0x5f,0xb4,0xe9,0xd6,0x58,0xeb,0x45,0x11,0x89,0x34,0x34,0xd3,0x11, + 0xeb,0x34,0xce,0x2a,0x4f,0x00,0x3d,0xf6,0x72,0xef,0x69,0x66,0xc0,0x9f,0x9a,0xac,0x7e,0x70,0x50,0xac, + 0x55,0x47,0xda,0xbe,0x43,0x5b,0xec,0x8b,0xc8,0xc5,0x23,0x84,0xc9,0x9f,0xb6,0x52,0x08,0xcf,0x91,0x1b, + 0x2f,0x80,0x69,0xe6,0x34,0x33,0xe6,0xb3,0x9f,0xa4,0xe5,0x0d,0x9a,0x15,0xf9,0x57,0xfc,0x0b,0xa9,0x41, + 0x0b,0xf5,0xff,0x58,0x41,0x92,0x22,0x27,0x66,0x12,0x06,0xc7,0x2a,0xd8,0x59,0xa7,0xc6,0xdf,0x44,0x12, + 0x4f,0xc0,0xa8,0x7f,0xa7,0x41,0xc8,0xc8,0x69,0xff,0xba,0x05,0x2e,0x97,0xad,0x3b,0xd0,0xeb,0xf3,0x15, + 0x6d,0x7e,0x1b,0xe5,0xba,0xdd,0x34,0xbe,0x22,0x11,0xec,0x68,0x98,0x33,0x81,0x02,0x6a,0x0b,0x13,0x55, + 0x79,0x31,0x75,0x4e,0x3a,0xc8,0xb6,0x13,0xbd,0x97,0x6f,0x37,0x0a,0x0b,0x2d,0x88,0x0e,0xde,0x67,0x90, + 0xc2,0xb3,0xca,0x20,0xca,0x9a,0x51,0xf4,0x64,0x3e,0xdb,0xf4,0x2e,0x45,0xf2,0xc7,0x47,0x17,0xa8,0xf4, + 0xfa,0x90,0x5a,0x7f,0x80,0xa6,0x82,0xac,0xe4,0x6c,0x81,0x46,0xbb,0x52,0x85,0x20,0x24,0xf8,0x80,0xea +}; +unsigned int login_live_com_cer_len = 1520; + +unsigned char login_skype_com_cer[] = { + 0x30,0x82,0x05,0xef,0x30,0x82,0x04,0xd7,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0xe9,0x02,0x8b,0x95, + 0x78,0xe4,0x15,0xdc,0x1a,0x71,0x0a,0x2b,0x88,0x15,0x44,0x47,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xdf,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73, + 0x68,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c, + 0x61,0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f, + 0x67,0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54, + 0x65,0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, + 0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20, + 0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b, + 0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x18,0x30,0x16,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x73,0x6b,0x79,0x70,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,0xb0,0x78,0x99,0x86,0x0e,0xa2,0x73,0x23, + 0xd4,0x5a,0xc3,0x49,0xeb,0xb1,0x36,0x8c,0x7c,0xca,0x84,0xae,0x3c,0xaf,0x38,0x88,0x28,0x99,0x8d,0x2d, + 0x58,0x13,0xb1,0x97,0x78,0x3e,0x52,0x20,0x67,0xac,0x5b,0x73,0x98,0x6c,0x32,0x55,0xc9,0x70,0xd1,0xd9, + 0xaa,0x15,0xe8,0x2e,0x26,0x85,0x81,0xbc,0x56,0xe4,0xbc,0x80,0x63,0xdb,0x4e,0xd7,0xf5,0x02,0xbe,0x51, + 0x63,0x1e,0x3c,0xdb,0xdf,0xd7,0x00,0x5d,0x5a,0xb9,0xe5,0x7b,0x6a,0xea,0x38,0x20,0xb2,0x3b,0xb6,0xee, + 0x75,0x54,0x84,0xf9,0xa6,0xca,0x38,0x70,0xdd,0xbf,0xb0,0xff,0xa5,0x85,0x5d,0xb4,0x41,0xfe,0xdd,0x3d, + 0xd9,0x2a,0xe1,0x30,0x43,0x1a,0x98,0x79,0x93,0xa0,0x5f,0xe0,0x67,0x6c,0x95,0xfa,0x3e,0x7a,0xae,0x71, + 0x7b,0xe3,0x6d,0x88,0x42,0x3f,0x25,0xd4,0xee,0xbe,0x68,0x68,0xac,0xad,0xac,0x60,0xe0,0x20,0xa3,0x39, + 0x83,0xb9,0x5b,0x28,0xa3,0x93,0x6d,0xa1,0xbd,0x76,0x0a,0xe3,0xeb,0xae,0x87,0x27,0x0e,0x54,0x8f,0xb4, + 0x48,0x0c,0x9a,0x54,0xf4,0x5d,0x8e,0x37,0x50,0xdc,0x5e,0xa4,0x8b,0x6b,0x4b,0xdc,0xa6,0xf3,0x34,0xbe, + 0x77,0x59,0x22,0x88,0xff,0x19,0x2b,0x6d,0x76,0x64,0x73,0xda,0x0c,0x87,0x07,0x2b,0x9a,0x37,0x3a,0xd0, + 0xe2,0x8c,0xf6,0x36,0x32,0x6b,0x9a,0x79,0xcc,0xd2,0x3b,0x93,0x6f,0x1a,0x4d,0x6c,0xe6,0xc1,0x9d,0x40, + 0xac,0x2d,0x74,0xc3,0xbe,0xea,0x5c,0x73,0x65,0x01,0x29,0xb1,0x2a,0xbf,0x70,0x59,0xc1,0xce,0xc6,0xc3, + 0xa2,0xc8,0x45,0x5f,0xba,0x67,0x3d,0x0f,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xea,0x30,0x82,0x01, + 0xe6,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28, + 0x98,0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x0e,0x04,0x16,0x04,0x14,0xd5,0x8e,0x5a,0x51,0x13,0xb4,0x29,0x0d,0x31,0xb6,0x1c,0x8d,0x3e,0x51,0x51, + 0x31,0x0a,0x33,0xaa,0x81,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05, + 0xa0,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55, + 0x1d,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06, + 0x0c,0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b, + 0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63, + 0x75,0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b, + 0x06,0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74, + 0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d, + 0x2f,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77, + 0x61,0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a, + 0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e, + 0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e, + 0x63,0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30, + 0x3b,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x63,0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e, + 0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74, + 0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x2f, + 0x06,0x03,0x55,0x1d,0x11,0x04,0x28,0x30,0x26,0x82,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x73,0x6b,0x79, + 0x70,0x65,0x2e,0x63,0x6f,0x6d,0x82,0x13,0x77,0x77,0x77,0x2e,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x73,0x6b, + 0x79,0x70,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05, + 0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x08,0xf2,0x81,0x75,0x91,0xbb,0xce,0x12,0x04,0x18,0xc2,0x4d,0x5a, + 0xfb,0x46,0x90,0x0a,0x54,0x44,0xf4,0xf2,0xdd,0x07,0x81,0xf0,0x1f,0xa6,0x7a,0x6f,0x9f,0xcf,0xb8,0x0e, + 0x2c,0x4f,0x9c,0xc4,0x9a,0xf5,0xa8,0xf6,0xba,0xa4,0xc9,0x7a,0x5d,0xb1,0xe2,0x5a,0xca,0x3c,0xfa,0x60, + 0xa8,0x68,0x3e,0xcb,0xba,0x2d,0xe2,0xcd,0xd6,0xb6,0xe4,0x92,0x3c,0x69,0xad,0x57,0xea,0xa8,0x2f,0x38, + 0x10,0x84,0x72,0xe5,0x68,0x71,0xed,0xbe,0xeb,0x6e,0x18,0xef,0x63,0x7a,0xbe,0xe7,0x24,0xff,0xc0,0x63, + 0xfd,0x58,0x3b,0x4c,0x81,0x92,0xd8,0x29,0xab,0x8e,0x35,0x5d,0xd7,0xd3,0x09,0x6b,0x85,0xd3,0xd5,0x73, + 0x05,0x44,0xe2,0xe5,0xbb,0x83,0x53,0x10,0xcb,0xf2,0xcf,0xb7,0x6e,0xe1,0x69,0xb7,0xa1,0x92,0x64,0xc5, + 0xcf,0xcd,0x82,0xbb,0x36,0xa0,0x38,0xad,0xd7,0x24,0xdf,0x53,0xfc,0x3f,0x62,0xb7,0xb7,0xd5,0xc7,0x57, + 0xe3,0x93,0x31,0x70,0x8e,0x24,0x89,0x86,0xca,0x63,0x2b,0x39,0xba,0x5d,0xd9,0x6a,0x60,0xec,0xa1,0x4e, + 0x8a,0xfe,0x53,0xf8,0x5e,0x92,0xdf,0x2f,0x5c,0x26,0x17,0x6d,0x03,0x7d,0x02,0x0f,0x0f,0xaa,0x43,0x67, + 0x6d,0xb0,0x62,0xbf,0x7e,0x53,0xdd,0xcc,0xec,0x78,0x73,0x95,0xe5,0xa5,0xf6,0x00,0xa3,0x04,0xfd,0x3f, + 0x04,0x2a,0xb3,0x98,0xc5,0xb7,0x03,0x1c,0xdb,0xc9,0x50,0xab,0xb0,0x05,0x1d,0x1e,0xbe,0x56,0xb4,0xcf, + 0x3e,0x42,0x13,0x94,0x9e,0xf9,0xe7,0x01,0x81,0xa5,0x78,0x6f,0x0c,0x7a,0x76,0xac,0x05,0x86,0xec,0xac, + 0xc2,0x11,0xac +}; +unsigned int login_skype_com_cer_len = 1523; + +unsigned char login_yahoo_com_1_cer[] = { + 0x30,0x82,0x05,0xd9,0x30,0x82,0x04,0xc1,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x39,0x2a,0x43,0x4f,0x0e, + 0x07,0xdf,0x1f,0x8a,0xa3,0x05,0xde,0x34,0xe0,0xc2,0x29,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, + 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74,0x79, + 0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52,0x54, + 0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55,0x04, + 0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74,0x72, + 0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55,0x54, + 0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65, + 0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31, + 0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xdf,0x31,0x0b,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05,0x33, + 0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72,0x69, + 0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73,0x68, + 0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c,0x61, + 0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f,0x67, + 0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54,0x65, + 0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f,0x48, + 0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20,0x43, + 0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b,0x13, + 0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04, + 0x03,0x13,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68,0x6f,0x6f,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,0xa1,0xa4,0x05,0x3d,0xed,0x85,0x45,0x93,0x8a, + 0x18,0x4d,0xc6,0x03,0x00,0x57,0xe2,0x40,0x77,0xf0,0x1c,0xeb,0xd0,0x19,0xdf,0x22,0x5d,0x08,0x7f,0xd1, + 0x07,0x3c,0x41,0x89,0x46,0x17,0xa3,0x09,0xfa,0xfc,0xf8,0xa9,0x04,0xd1,0x96,0x8f,0xab,0xd7,0x4f,0x3c, + 0xf9,0xad,0x18,0xa9,0x74,0x81,0xc4,0x57,0x0a,0x3a,0x26,0x16,0xce,0x62,0x3e,0xbc,0x3f,0x6c,0x21,0xee, + 0x93,0x8d,0xcb,0x0d,0xa0,0x1f,0x9a,0x96,0xd0,0x8f,0xad,0xf5,0x93,0x93,0x82,0xee,0x72,0x0c,0xa1,0x75, + 0x15,0xa3,0x7b,0x84,0x56,0xb8,0xad,0xff,0x52,0x11,0x71,0x84,0xbc,0x3a,0x30,0x0b,0x7e,0x98,0xa8,0xe1, + 0xa8,0x3f,0x37,0x52,0xd0,0xf1,0x7c,0x6f,0x90,0xd8,0x45,0x0a,0xac,0x39,0x72,0x6a,0x61,0xd5,0xbb,0xc3, + 0x8c,0xf9,0xc2,0xcc,0xdf,0xfd,0x3a,0x71,0xb9,0xaf,0xbc,0xdc,0x3a,0xdc,0x0c,0xb6,0xb1,0xd2,0xd1,0x89, + 0xbb,0x41,0xb6,0xf2,0xde,0x57,0xd5,0x15,0xdf,0xfc,0xfd,0xe2,0x31,0xc5,0xdf,0xca,0xc1,0xd8,0x8f,0x2c, + 0xbf,0xf0,0x0e,0x5b,0x71,0xe0,0x34,0x71,0xc3,0xc5,0x4d,0x7d,0x7a,0xd4,0xfa,0xed,0x30,0x4b,0x2f,0xea, + 0xb6,0x2e,0x9e,0x93,0x3c,0xe2,0x3a,0xf8,0x42,0xa2,0x1a,0xee,0xdc,0xdf,0xcd,0x0f,0xa9,0xf6,0x79,0x84, + 0x1a,0x8e,0x6c,0x02,0xb6,0x86,0xe5,0xbf,0x51,0x6a,0x66,0xf8,0xf3,0x9c,0xd3,0x59,0x0c,0x7b,0xa5,0x99, + 0x78,0xcd,0x7c,0x99,0xfa,0xc6,0x96,0x47,0xd8,0x32,0xd4,0x74,0x76,0x0e,0x77,0x4b,0x20,0x74,0xa4,0xb7, + 0x89,0x75,0x92,0x4a,0xb4,0x5b,0x55,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xd5,0x30,0x82,0x01,0xd1, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98, + 0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e, + 0x04,0x16,0x04,0x14,0x86,0x49,0x45,0xfc,0x33,0x19,0x33,0xd4,0x04,0xed,0x27,0x61,0xee,0xe8,0x01,0xc9, + 0x0c,0x7f,0x2f,0x7e,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0, + 0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06,0x0c, + 0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63,0x75, + 0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b,0x06, + 0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e,0x2d, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63, + 0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3b, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x1a,0x06, + 0x03,0x55,0x1d,0x11,0x04,0x13,0x30,0x11,0x82,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68,0x6f, + 0x6f,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x57,0x62,0xe1,0x77,0xeb,0xfc,0x1f,0xbf,0x88,0x53,0xaf,0x58,0xd3,0xd4,0xd6, + 0x6d,0x67,0x30,0x17,0x40,0xbe,0xe0,0x1f,0x64,0xde,0x87,0x15,0xcc,0xe0,0xa4,0x56,0xa9,0xd1,0x9f,0xf9, + 0x01,0xfe,0x02,0xb1,0xb1,0xea,0xe2,0x5f,0xee,0x71,0x16,0x31,0xf9,0x08,0xd5,0xc2,0xd7,0x9a,0x9b,0xb2, + 0x5a,0x38,0xd7,0xa9,0x7f,0xe9,0x87,0x6b,0x31,0xf9,0x0b,0xac,0xd9,0xfd,0x50,0x71,0xe0,0xdb,0x82,0x92, + 0x0f,0x81,0x9c,0x8d,0x77,0xe9,0xeb,0x2e,0xea,0xd4,0x23,0x41,0x87,0xec,0x2d,0xb2,0x78,0xb3,0x8e,0xb1, + 0x67,0xd2,0xee,0x71,0x03,0x08,0x12,0x99,0xb3,0x02,0x29,0x6f,0xde,0x8b,0xde,0xc1,0xa9,0x03,0x0a,0x5a, + 0x33,0x1c,0x3d,0x11,0x03,0xc6,0x48,0x0c,0x98,0x9c,0x15,0x2e,0xd9,0xa6,0x85,0x52,0xe7,0x05,0x8a,0xae, + 0x30,0x23,0xeb,0xed,0x28,0x6c,0x60,0xe9,0x2d,0x7f,0x8f,0x47,0x8b,0x2f,0xd0,0xdc,0xe6,0xbb,0x0f,0x7e, + 0x5f,0xf2,0x48,0x81,0x8e,0x50,0x04,0x63,0xb1,0x51,0x80,0x75,0x9a,0xa9,0xb6,0x10,0x1c,0x10,0x5f,0x6f, + 0x18,0x6f,0xe0,0x0e,0x96,0x45,0xce,0xee,0xf1,0xb5,0x20,0xdb,0xef,0xda,0x6e,0xc8,0x95,0xe3,0xf6,0x45, + 0xfd,0xca,0xfc,0xa5,0x5f,0x49,0x6d,0x06,0x1e,0xd2,0xde,0x61,0x3d,0x15,0x7d,0x37,0xe5,0x1c,0x35,0x8e, + 0x06,0xc2,0x6b,0xf7,0xb4,0xa8,0x28,0x2c,0x31,0xcb,0xaa,0xb4,0xa7,0x97,0x4f,0x9d,0x8a,0xf6,0xaf,0x7e, + 0x37,0xb9,0x7b,0x3d,0xdf,0x92,0x66,0x8b,0x8f,0x4e,0x9d,0xc6,0x36,0xe7,0x5c,0xa6,0xab,0x12,0x0f,0xd6, + 0xcf +}; +unsigned int login_yahoo_com_1_cer_len = 1501; + +unsigned char login_yahoo_com_2_cer[] = { + 0x30,0x82,0x05,0xd9,0x30,0x82,0x04,0xc1,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x3e,0x75,0xce,0xd4,0x6b, + 0x69,0x30,0x21,0x21,0x88,0x30,0xae,0x86,0xa8,0x2a,0x71,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, + 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74,0x79, + 0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52,0x54, + 0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55,0x04, + 0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74,0x72, + 0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55,0x54, + 0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65, + 0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31, + 0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xdf,0x31,0x0b,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05,0x33, + 0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72,0x69, + 0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73,0x68, + 0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c,0x61, + 0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f,0x67, + 0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54,0x65, + 0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f,0x48, + 0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20,0x43, + 0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b,0x13, + 0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04, + 0x03,0x13,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68,0x6f,0x6f,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,0xa1,0xa4,0x05,0x3d,0xed,0x85,0x45,0x93,0x8a, + 0x18,0x4d,0xc6,0x03,0x00,0x57,0xe2,0x40,0x77,0xf0,0x1c,0xeb,0xd0,0x19,0xdf,0x22,0x5d,0x08,0x7f,0xd1, + 0x07,0x3c,0x41,0x89,0x46,0x17,0xa3,0x09,0xfa,0xfc,0xf8,0xa9,0x04,0xd1,0x96,0x8f,0xab,0xd7,0x4f,0x3c, + 0xf9,0xad,0x18,0xa9,0x74,0x81,0xc4,0x57,0x0a,0x3a,0x26,0x16,0xce,0x62,0x3e,0xbc,0x3f,0x6c,0x21,0xee, + 0x93,0x8d,0xcb,0x0d,0xa0,0x1f,0x9a,0x96,0xd0,0x8f,0xad,0xf5,0x93,0x93,0x82,0xee,0x72,0x0c,0xa1,0x75, + 0x15,0xa3,0x7b,0x84,0x56,0xb8,0xad,0xff,0x52,0x11,0x71,0x84,0xbc,0x3a,0x30,0x0b,0x7e,0x98,0xa8,0xe1, + 0xa8,0x3f,0x37,0x52,0xd0,0xf1,0x7c,0x6f,0x90,0xd8,0x45,0x0a,0xac,0x39,0x72,0x6a,0x61,0xd5,0xbb,0xc3, + 0x8c,0xf9,0xc2,0xcc,0xdf,0xfd,0x3a,0x71,0xb9,0xaf,0xbc,0xdc,0x3a,0xdc,0x0c,0xb6,0xb1,0xd2,0xd1,0x89, + 0xbb,0x41,0xb6,0xf2,0xde,0x57,0xd5,0x15,0xdf,0xfc,0xfd,0xe2,0x31,0xc5,0xdf,0xca,0xc1,0xd8,0x8f,0x2c, + 0xbf,0xf0,0x0e,0x5b,0x71,0xe0,0x34,0x71,0xc3,0xc5,0x4d,0x7d,0x7a,0xd4,0xfa,0xed,0x30,0x4b,0x2f,0xea, + 0xb6,0x2e,0x9e,0x93,0x3c,0xe2,0x3a,0xf8,0x42,0xa2,0x1a,0xee,0xdc,0xdf,0xcd,0x0f,0xa9,0xf6,0x79,0x84, + 0x1a,0x8e,0x6c,0x02,0xb6,0x86,0xe5,0xbf,0x51,0x6a,0x66,0xf8,0xf3,0x9c,0xd3,0x59,0x0c,0x7b,0xa5,0x99, + 0x78,0xcd,0x7c,0x99,0xfa,0xc6,0x96,0x47,0xd8,0x32,0xd4,0x74,0x76,0x0e,0x77,0x4b,0x20,0x74,0xa4,0xb7, + 0x89,0x75,0x92,0x4a,0xb4,0x5b,0x55,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xd5,0x30,0x82,0x01,0xd1, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98, + 0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e, + 0x04,0x16,0x04,0x14,0x86,0x49,0x45,0xfc,0x33,0x19,0x33,0xd4,0x04,0xed,0x27,0x61,0xee,0xe8,0x01,0xc9, + 0x0c,0x7f,0x2f,0x7e,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0, + 0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06,0x0c, + 0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63,0x75, + 0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b,0x06, + 0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e,0x2d, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63, + 0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3b, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x1a,0x06, + 0x03,0x55,0x1d,0x11,0x04,0x13,0x30,0x11,0x82,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68,0x6f, + 0x6f,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x53,0x69,0x98,0x8e,0x28,0x4e,0x9c,0x2b,0x5b,0x1d,0xcc,0x6b,0x77,0x28,0x3d, + 0xbb,0xfa,0xa5,0x4e,0x7e,0x56,0x29,0xa4,0xea,0x10,0xe2,0xf4,0xe6,0x2d,0x06,0xd1,0x84,0xdb,0x23,0xce, + 0x97,0xf3,0x68,0xb6,0x0f,0x3a,0xde,0x15,0x0b,0x24,0x1d,0x91,0xe3,0x6c,0x2e,0x30,0xb7,0xe9,0x70,0xb0, + 0xc3,0x46,0x80,0xf0,0xd3,0xb1,0x51,0xbf,0x4f,0xd6,0x78,0xa0,0xfc,0xac,0xc6,0xcf,0x31,0x04,0x63,0xe2, + 0x34,0x55,0x05,0x4a,0x3d,0xf6,0x30,0xba,0xf3,0x33,0xe5,0xba,0xd2,0x96,0xf3,0xd5,0xb1,0xb6,0x93,0x89, + 0x1a,0xa4,0x68,0xbe,0x7e,0xed,0x63,0xb4,0x1a,0x48,0xc0,0x53,0xe4,0xa3,0xf0,0x39,0x0c,0x32,0x92,0xc7, + 0x43,0x0d,0x1a,0x71,0xed,0xd0,0x46,0x93,0xbf,0x93,0x62,0x6c,0x33,0x4b,0xcd,0x36,0x0d,0x69,0x5e,0xbb, + 0x6c,0x96,0x99,0x21,0x69,0xc4,0x4b,0x67,0x72,0xdb,0x6c,0x6a,0xb8,0xf7,0x68,0xed,0xc5,0x8f,0xad,0x63, + 0x65,0x95,0x0a,0x4c,0xe0,0xf9,0x0f,0x7e,0x37,0x3d,0xaa,0xd4,0x93,0xba,0x67,0x09,0xc3,0xa5,0xa4,0x0d, + 0x03,0x5a,0x6d,0xd5,0x0b,0xfe,0xf0,0x40,0x14,0xb4,0xf6,0xb8,0x69,0x7c,0x6d,0xc2,0x32,0x4b,0x9f,0xb5, + 0x1a,0xe7,0x46,0xae,0x4c,0x5a,0x2b,0xaa,0x7a,0x5e,0x90,0x57,0x95,0xfa,0xdb,0x66,0x02,0x20,0x1e,0x6a, + 0x69,0x66,0x15,0x9c,0xc2,0xb6,0xf5,0xbc,0x50,0xb5,0xfd,0x45,0xc7,0x1f,0x68,0xb4,0x47,0x59,0xac,0xc4, + 0x1b,0x28,0x93,0x4e,0x52,0x53,0x12,0x03,0x58,0x4b,0x71,0x83,0x9f,0x66,0xe6,0xac,0x79,0x48,0xfe,0xfe, + 0x47 +}; +unsigned int login_yahoo_com_2_cer_len = 1501; + +unsigned char login_yahoo_com_cer[] = { + 0x30,0x82,0x05,0xef,0x30,0x82,0x04,0xd7,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0xd7,0x55,0x8f,0xda, + 0xf5,0xf1,0x10,0x5b,0xb2,0x13,0x28,0x2b,0x70,0x77,0x29,0xa3,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xdf,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73, + 0x68,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c, + 0x61,0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f, + 0x67,0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54, + 0x65,0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, + 0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20, + 0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b, + 0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x18,0x30,0x16,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68,0x6f,0x6f,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,0xa1,0xa4,0x05,0x3d,0xed,0x85,0x45,0x93, + 0x8a,0x18,0x4d,0xc6,0x03,0x00,0x57,0xe2,0x40,0x77,0xf0,0x1c,0xeb,0xd0,0x19,0xdf,0x22,0x5d,0x08,0x7f, + 0xd1,0x07,0x3c,0x41,0x89,0x46,0x17,0xa3,0x09,0xfa,0xfc,0xf8,0xa9,0x04,0xd1,0x96,0x8f,0xab,0xd7,0x4f, + 0x3c,0xf9,0xad,0x18,0xa9,0x74,0x81,0xc4,0x57,0x0a,0x3a,0x26,0x16,0xce,0x62,0x3e,0xbc,0x3f,0x6c,0x21, + 0xee,0x93,0x8d,0xcb,0x0d,0xa0,0x1f,0x9a,0x96,0xd0,0x8f,0xad,0xf5,0x93,0x93,0x82,0xee,0x72,0x0c,0xa1, + 0x75,0x15,0xa3,0x7b,0x84,0x56,0xb8,0xad,0xff,0x52,0x11,0x71,0x84,0xbc,0x3a,0x30,0x0b,0x7e,0x98,0xa8, + 0xe1,0xa8,0x3f,0x37,0x52,0xd0,0xf1,0x7c,0x6f,0x90,0xd8,0x45,0x0a,0xac,0x39,0x72,0x6a,0x61,0xd5,0xbb, + 0xc3,0x8c,0xf9,0xc2,0xcc,0xdf,0xfd,0x3a,0x71,0xb9,0xaf,0xbc,0xdc,0x3a,0xdc,0x0c,0xb6,0xb1,0xd2,0xd1, + 0x89,0xbb,0x41,0xb6,0xf2,0xde,0x57,0xd5,0x15,0xdf,0xfc,0xfd,0xe2,0x31,0xc5,0xdf,0xca,0xc1,0xd8,0x8f, + 0x2c,0xbf,0xf0,0x0e,0x5b,0x71,0xe0,0x34,0x71,0xc3,0xc5,0x4d,0x7d,0x7a,0xd4,0xfa,0xed,0x30,0x4b,0x2f, + 0xea,0xb6,0x2e,0x9e,0x93,0x3c,0xe2,0x3a,0xf8,0x42,0xa2,0x1a,0xee,0xdc,0xdf,0xcd,0x0f,0xa9,0xf6,0x79, + 0x84,0x1a,0x8e,0x6c,0x02,0xb6,0x86,0xe5,0xbf,0x51,0x6a,0x66,0xf8,0xf3,0x9c,0xd3,0x59,0x0c,0x7b,0xa5, + 0x99,0x78,0xcd,0x7c,0x99,0xfa,0xc6,0x96,0x47,0xd8,0x32,0xd4,0x74,0x76,0x0e,0x77,0x4b,0x20,0x74,0xa4, + 0xb7,0x89,0x75,0x92,0x4a,0xb4,0x5b,0x55,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xea,0x30,0x82,0x01, + 0xe6,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28, + 0x98,0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x0e,0x04,0x16,0x04,0x14,0x86,0x49,0x45,0xfc,0x33,0x19,0x33,0xd4,0x04,0xed,0x27,0x61,0xee,0xe8,0x01, + 0xc9,0x0c,0x7f,0x2f,0x7e,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05, + 0xa0,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55, + 0x1d,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06, + 0x0c,0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b, + 0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63, + 0x75,0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b, + 0x06,0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74, + 0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d, + 0x2f,0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77, + 0x61,0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a, + 0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e, + 0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e, + 0x63,0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30, + 0x3b,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x63,0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e, + 0x41,0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74, + 0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x2f, + 0x06,0x03,0x55,0x1d,0x11,0x04,0x28,0x30,0x26,0x82,0x0f,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61,0x68, + 0x6f,0x6f,0x2e,0x63,0x6f,0x6d,0x82,0x13,0x77,0x77,0x77,0x2e,0x6c,0x6f,0x67,0x69,0x6e,0x2e,0x79,0x61, + 0x68,0x6f,0x6f,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05, + 0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x3d,0x57,0xc9,0x48,0x24,0x5c,0xee,0x64,0x81,0xf5,0xae,0xbe,0x55, + 0x29,0x16,0xff,0x2a,0x2f,0x84,0xed,0xd9,0xf8,0xa3,0x03,0xc8,0x30,0x66,0xbb,0xc8,0xd4,0x81,0x2d,0x21, + 0xf7,0x08,0xf7,0xac,0x96,0x42,0x9a,0x41,0x75,0x7a,0xba,0x5d,0x10,0x23,0xcb,0x92,0x42,0x61,0xfa,0x8a, + 0xda,0x6d,0x65,0x34,0x19,0xe5,0xa9,0xd6,0x2d,0x13,0x78,0xd7,0x81,0x44,0x92,0xa9,0x6e,0x80,0x63,0x15, + 0xcb,0xfe,0x35,0x1f,0x02,0xd1,0x8a,0x14,0xb0,0xa8,0xcc,0x94,0x20,0x3b,0xa8,0x1a,0xf0,0x5d,0x36,0x50, + 0xdb,0x0d,0xae,0xe9,0x64,0xe4,0xf6,0x8d,0x69,0x7d,0x30,0xc8,0x14,0x17,0x00,0x4a,0xe5,0xa6,0x35,0xfb, + 0x7d,0x0d,0x22,0x9d,0x79,0x76,0x52,0x2c,0xbc,0x97,0x06,0x88,0x9a,0x15,0xf4,0x73,0xe6,0xf1,0xf5,0x98, + 0xa5,0xcd,0x07,0x44,0x91,0xb8,0xa7,0x68,0x67,0x45,0xd2,0x72,0x11,0x60,0xe2,0x71,0xb7,0x50,0x55,0xe2, + 0x8a,0xa9,0x0d,0xd6,0x92,0xee,0x04,0x2a,0x8b,0x30,0xa0,0xa2,0x05,0x46,0x34,0x6d,0x92,0xc6,0x3b,0xaa, + 0x4d,0xa0,0xd0,0xab,0x01,0x19,0x0a,0x32,0xb7,0xe8,0xe3,0xcf,0xf1,0xd2,0x97,0x49,0x7b,0xac,0xa4,0x97, + 0xf7,0xf0,0x57,0xae,0x63,0x77,0x9a,0x7f,0x96,0xda,0x4d,0xfd,0xbe,0xdc,0x07,0x36,0xe3,0x25,0xbd,0x89, + 0x79,0x8e,0x29,0x12,0x13,0x8b,0x88,0x07,0xfb,0x6b,0xdb,0xa4,0xcd,0xb3,0x2d,0x27,0xe9,0xd4,0xca,0x60, + 0xd7,0x85,0x53,0xfb,0x74,0xc6,0x5c,0x35,0x8c,0x70,0x1f,0xf9,0xb2,0xb7,0x92,0x27,0x20,0xc7,0x94,0xd5, + 0x67,0x14,0x30 +}; +unsigned int login_yahoo_com_cer_len = 1523; + +unsigned char mail_google_com_cer[] = { + 0x30,0x82,0x05,0xee,0x30,0x82,0x04,0xd6,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x04,0x7e,0xcb,0xe9,0xfc, + 0xa5,0x5f,0x7b,0xd0,0x9e,0xae,0x36,0xe1,0x0c,0xae,0x1e,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, + 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74,0x79, + 0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52,0x54, + 0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55,0x04, + 0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74,0x72, + 0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55,0x54, + 0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65, + 0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31, + 0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xdf,0x31,0x0b,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05,0x33, + 0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72,0x69, + 0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73,0x68, + 0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c,0x61, + 0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f,0x67, + 0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54,0x65, + 0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f,0x48, + 0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20,0x43, + 0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b,0x13, + 0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04, + 0x03,0x13,0x0f,0x6d,0x61,0x69,0x6c,0x2e,0x67,0x6f,0x6f,0x67,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,0xb0,0x73,0xf0,0xf2,0x04,0xee,0xc2,0xa2,0x46, + 0xca,0x34,0x2a,0xaa,0xbb,0x60,0x23,0xd1,0x11,0x76,0x1f,0x1f,0x3a,0xd0,0x65,0x83,0x4e,0x9a,0x45,0xa8, + 0x43,0x70,0x85,0x76,0xf0,0x1f,0x87,0x00,0x02,0x1f,0x6e,0x3b,0x17,0x17,0xc4,0xb5,0xe9,0x19,0x46,0xa2, + 0x92,0x25,0x8d,0x62,0x2a,0xb4,0x63,0x30,0x1f,0xb9,0x85,0xf8,0x35,0xe1,0x16,0x5a,0x76,0x49,0xcc,0x50, + 0x48,0x53,0x39,0x59,0x89,0xd6,0x84,0x02,0xfb,0x9a,0xec,0x1b,0xc7,0x51,0xd5,0x76,0x95,0x90,0xd4,0x3a, + 0x2a,0xb8,0xa6,0xde,0x02,0x4d,0x06,0xfb,0xcd,0xed,0xa5,0x46,0x41,0x5f,0x55,0x74,0xe5,0xec,0x7e,0x40, + 0xdc,0x50,0x9c,0xb5,0xe4,0x35,0x5d,0x1e,0x68,0x20,0xf8,0xe9,0xde,0xa3,0x6a,0x28,0xbf,0x41,0xd2,0xa1, + 0xb3,0xe2,0x25,0x8d,0x0c,0x1b,0xca,0x3d,0x93,0x0c,0x18,0xae,0xdf,0xc5,0xbc,0xfd,0xbc,0x82,0xba,0x68, + 0x00,0xd7,0x16,0x32,0x71,0x9f,0x65,0xb5,0x11,0xda,0x68,0x59,0xd0,0xa6,0x57,0x64,0x1b,0xc9,0xfe,0x98, + 0xe5,0xf5,0xa5,0x65,0xea,0xe1,0xdb,0xee,0xf4,0xb3,0x9d,0xb3,0x8e,0xea,0x87,0xae,0x16,0xd2,0x1e,0xa0, + 0x7c,0x7c,0x69,0x3f,0x29,0x16,0x85,0x01,0x53,0xa7,0x6c,0xf1,0x60,0xab,0xdd,0xa2,0xfc,0x25,0x47,0xd4, + 0x32,0xd1,0x12,0xdd,0xf7,0x48,0x12,0xe0,0xfc,0x9c,0xa2,0x77,0x98,0xe9,0x89,0x99,0xb8,0xf8,0x38,0xf1, + 0x8c,0x06,0xc2,0x7a,0x23,0x36,0x6d,0x9b,0x9d,0xcd,0x30,0xc8,0xc7,0x34,0x17,0x1e,0xbb,0x7d,0x42,0xc8, + 0xab,0xe7,0x15,0x16,0xf6,0x73,0xb5,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xea,0x30,0x82,0x01,0xe6, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98, + 0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e, + 0x04,0x16,0x04,0x14,0x18,0x2a,0xa2,0xc8,0xd4,0x7a,0x3f,0x7b,0xad,0x04,0x8b,0xbd,0x6f,0x9e,0x10,0x46, + 0x13,0x78,0x71,0x9d,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0, + 0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06,0x0c, + 0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63,0x75, + 0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b,0x06, + 0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e,0x2d, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63, + 0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3b, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x2f,0x06, + 0x03,0x55,0x1d,0x11,0x04,0x28,0x30,0x26,0x82,0x0f,0x6d,0x61,0x69,0x6c,0x2e,0x67,0x6f,0x6f,0x67,0x6c, + 0x65,0x2e,0x63,0x6f,0x6d,0x82,0x13,0x77,0x77,0x77,0x2e,0x6d,0x61,0x69,0x6c,0x2e,0x67,0x6f,0x6f,0x67, + 0x6c,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05, + 0x00,0x03,0x82,0x01,0x01,0x00,0x67,0x06,0x08,0x0a,0x27,0xc5,0x93,0x6e,0x02,0xf2,0xde,0x17,0x3f,0xd0, + 0xd3,0x1b,0x7c,0xff,0xb5,0xcd,0x7a,0xc7,0x77,0xc7,0xbe,0xdf,0x12,0xca,0x19,0xde,0xb0,0x13,0x57,0x0c, + 0x03,0x91,0xc4,0x79,0x52,0xcf,0x7f,0xb7,0x5e,0x55,0x20,0x84,0x49,0xdd,0xf5,0xd0,0x29,0x2f,0x0e,0x04, + 0xda,0x59,0x9e,0x0e,0x13,0x9f,0xf4,0xc0,0x32,0x9b,0xff,0xa1,0x11,0x24,0x2a,0x97,0xa3,0xf2,0x3f,0x3d, + 0x2a,0x6b,0xa8,0xad,0x8c,0x19,0x75,0x95,0x0e,0x1d,0x25,0xfd,0x4f,0xc4,0x7a,0x15,0xc3,0x1d,0xc7,0x13, + 0x40,0xc8,0x0d,0xbe,0x97,0x60,0x72,0xa6,0xfe,0x25,0xbe,0x8f,0xec,0xd5,0xa6,0x86,0xc3,0x21,0x5c,0x59, + 0x52,0xd9,0x6a,0x0b,0x5c,0x9f,0x4b,0xde,0xb5,0xf9,0xec,0xe2,0xf4,0xc5,0xcc,0x62,0x53,0x76,0x89,0x65, + 0xe4,0x29,0xda,0xb7,0xbf,0x96,0xe0,0x60,0x8d,0x0d,0xb7,0x09,0x55,0xd6,0x40,0x55,0x1d,0xc1,0xf2,0x96, + 0x21,0x75,0xaf,0x89,0x86,0x1f,0x5d,0x81,0x97,0x29,0x28,0x1e,0x29,0xd7,0x96,0xc1,0x20,0x03,0x32,0x7b, + 0x00,0x3b,0x6a,0x37,0x17,0x5a,0xa3,0xb3,0x1a,0x6f,0x32,0x3b,0x6e,0xf1,0xa3,0x5d,0xab,0xab,0xcc,0x2a, + 0xcb,0x30,0x0c,0x1f,0x35,0x23,0x8b,0x69,0x44,0x5c,0xea,0xac,0x28,0x60,0xed,0xab,0x6b,0x63,0x9e,0xf6, + 0x92,0xbc,0xbd,0x9a,0x5a,0x26,0x4c,0xc5,0x98,0xb8,0x0e,0x19,0x3e,0xfc,0x05,0x31,0xe3,0x16,0xd9,0xfd, + 0x90,0x05,0x03,0x86,0xc6,0x57,0x01,0x1f,0x7f,0x78,0xa0,0xcf,0x33,0x6a,0xaa,0x66,0x6b,0x22,0xd0,0xa7, + 0x49,0x23 +}; +unsigned int mail_google_com_cer_len = 1522; + +unsigned char www_google_com_cer[] = { + 0x30,0x82,0x05,0xe4,0x30,0x82,0x04,0xcc,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,0xf5,0xc8,0x6a,0xf3, + 0x61,0x62,0xf1,0x3a,0x64,0xf5,0x4f,0x6d,0xc9,0x58,0x7c,0x06,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, + 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x97,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x55,0x54,0x31,0x17,0x30,0x15, + 0x06,0x03,0x55,0x04,0x07,0x13,0x0e,0x53,0x61,0x6c,0x74,0x20,0x4c,0x61,0x6b,0x65,0x20,0x43,0x69,0x74, + 0x79,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x54,0x68,0x65,0x20,0x55,0x53,0x45,0x52, + 0x54,0x52,0x55,0x53,0x54,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x21,0x30,0x1f,0x06,0x03,0x55, + 0x04,0x0b,0x13,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x75,0x73,0x65,0x72,0x74, + 0x72,0x75,0x73,0x74,0x2e,0x63,0x6f,0x6d,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,0x16,0x55, + 0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72, + 0x65,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x33,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d, + 0x31,0x34,0x30,0x33,0x31,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xde,0x31,0x0b,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x11,0x13,0x05, + 0x33,0x38,0x34,0x37,0x37,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x08,0x13,0x07,0x46,0x6c,0x6f,0x72, + 0x69,0x64,0x61,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x45,0x6e,0x67,0x6c,0x69,0x73, + 0x68,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x09,0x13,0x0e,0x53,0x65,0x61,0x20,0x56,0x69,0x6c,0x6c, + 0x61,0x67,0x65,0x20,0x31,0x30,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,0x13,0x0b,0x47,0x6f,0x6f, + 0x67,0x6c,0x65,0x20,0x4c,0x74,0x64,0x2e,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0b,0x13,0x0a,0x54, + 0x65,0x63,0x68,0x20,0x44,0x65,0x70,0x74,0x2e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x0b,0x13,0x1f, + 0x48,0x6f,0x73,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x47,0x54,0x49,0x20,0x47,0x72,0x6f,0x75,0x70,0x20, + 0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0b, + 0x13,0x0b,0x50,0x6c,0x61,0x74,0x69,0x6e,0x75,0x6d,0x53,0x53,0x4c,0x31,0x17,0x30,0x15,0x06,0x03,0x55, + 0x04,0x03,0x13,0x0e,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,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,0xb0,0x73,0xf0,0xf2,0x04,0xee,0xc2,0xa2,0x46, + 0xca,0x34,0x2a,0xaa,0xbb,0x60,0x23,0xd1,0x11,0x76,0x1f,0x1f,0x3a,0xd0,0x65,0x83,0x4e,0x9a,0x45,0xa8, + 0x43,0x70,0x85,0x76,0xf0,0x1f,0x87,0x00,0x02,0x1f,0x6e,0x3b,0x17,0x17,0xc4,0xb5,0xe9,0x19,0x46,0xa2, + 0x92,0x25,0x8d,0x62,0x2a,0xb4,0x63,0x30,0x1f,0xb9,0x85,0xf8,0x35,0xe1,0x16,0x5a,0x76,0x49,0xcc,0x50, + 0x48,0x53,0x39,0x59,0x89,0xd6,0x84,0x02,0xfb,0x9a,0xec,0x1b,0xc7,0x51,0xd5,0x76,0x95,0x90,0xd4,0x3a, + 0x2a,0xb8,0xa6,0xde,0x02,0x4d,0x06,0xfb,0xcd,0xed,0xa5,0x46,0x41,0x5f,0x55,0x74,0xe5,0xec,0x7e,0x40, + 0xdc,0x50,0x9c,0xb5,0xe4,0x35,0x5d,0x1e,0x68,0x20,0xf8,0xe9,0xde,0xa3,0x6a,0x28,0xbf,0x41,0xd2,0xa1, + 0xb3,0xe2,0x25,0x8d,0x0c,0x1b,0xca,0x3d,0x93,0x0c,0x18,0xae,0xdf,0xc5,0xbc,0xfd,0xbc,0x82,0xba,0x68, + 0x00,0xd7,0x16,0x32,0x71,0x9f,0x65,0xb5,0x11,0xda,0x68,0x59,0xd0,0xa6,0x57,0x64,0x1b,0xc9,0xfe,0x98, + 0xe5,0xf5,0xa5,0x65,0xea,0xe1,0xdb,0xee,0xf4,0xb3,0x9d,0xb3,0x8e,0xea,0x87,0xae,0x16,0xd2,0x1e,0xa0, + 0x7c,0x7c,0x69,0x3f,0x29,0x16,0x85,0x01,0x53,0xa7,0x6c,0xf1,0x60,0xab,0xdd,0xa2,0xfc,0x25,0x47,0xd4, + 0x32,0xd1,0x12,0xdd,0xf7,0x48,0x12,0xe0,0xfc,0x9c,0xa2,0x77,0x98,0xe9,0x89,0x99,0xb8,0xf8,0x38,0xf1, + 0x8c,0x06,0xc2,0x7a,0x23,0x36,0x6d,0x9b,0x9d,0xcd,0x30,0xc8,0xc7,0x34,0x17,0x1e,0xbb,0x7d,0x42,0xc8, + 0xab,0xe7,0x15,0x16,0xf6,0x73,0xb5,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xe0,0x30,0x82,0x01,0xdc, + 0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xa1,0x72,0x5f,0x26,0x1b,0x28,0x98, + 0x43,0x95,0x5d,0x07,0x37,0xd5,0x85,0x96,0x9d,0x4b,0xd2,0xc3,0x45,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e, + 0x04,0x16,0x04,0x14,0x18,0x2a,0xa2,0xc8,0xd4,0x7a,0x3f,0x7b,0xad,0x04,0x8b,0xbd,0x6f,0x9e,0x10,0x46, + 0x13,0x78,0x71,0x9d,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0, + 0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d, + 0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2b,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55,0x1d,0x20,0x04,0x3f,0x30,0x3d,0x30,0x3b,0x06,0x0c, + 0x2b,0x06,0x01,0x04,0x01,0xb2,0x31,0x01,0x02,0x01,0x03,0x04,0x30,0x2b,0x30,0x29,0x06,0x08,0x2b,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1d,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x73,0x65,0x63,0x75, + 0x72,0x65,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x63,0x6f,0x6d,0x2f,0x43,0x50,0x53,0x30,0x7b,0x06, + 0x03,0x55,0x1d,0x1f,0x04,0x74,0x30,0x72,0x30,0x38,0xa0,0x36,0xa0,0x34,0x86,0x32,0x68,0x74,0x74,0x70, + 0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f, + 0x55,0x54,0x4e,0x2d,0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61, + 0x72,0x65,0x2e,0x63,0x72,0x6c,0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x63,0x72,0x6c,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x2e,0x6e,0x65,0x74,0x2f,0x55,0x54,0x4e,0x2d, + 0x55,0x53,0x45,0x52,0x46,0x69,0x72,0x73,0x74,0x2d,0x48,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x2e,0x63, + 0x72,0x6c,0x30,0x71,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3b, + 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2f,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63, + 0x72,0x74,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x55,0x54,0x4e,0x41, + 0x64,0x64,0x54,0x72,0x75,0x73,0x74,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2e,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, + 0x6f,0x63,0x73,0x70,0x2e,0x63,0x6f,0x6d,0x6f,0x64,0x6f,0x63,0x61,0x2e,0x63,0x6f,0x6d,0x30,0x25,0x06, + 0x03,0x55,0x1d,0x11,0x04,0x1e,0x30,0x1c,0x82,0x0e,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65, + 0x2e,0x63,0x6f,0x6d,0x82,0x0a,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x63,0x6f,0x6d,0x30,0x0d,0x06,0x09, + 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x71,0xc0,0x99,0x3f, + 0x5e,0xf6,0xbd,0x33,0xff,0x9e,0x16,0xcb,0xa8,0xbf,0xdd,0x70,0xf9,0xd2,0x53,0x3b,0x36,0xae,0xc9,0x17, + 0xc8,0xae,0x5e,0x4d,0xdd,0x62,0xf7,0xb7,0xd3,0x3e,0x77,0xa3,0xfe,0xc0,0x7b,0x32,0xb5,0xc9,0x94,0x05, + 0x52,0x50,0xf2,0x5f,0x3d,0x79,0x84,0x49,0x4f,0x5d,0x6c,0xb0,0xd7,0x59,0xbd,0xd4,0x6c,0x88,0xfa,0xfc, + 0xc5,0x65,0x86,0xeb,0x28,0x52,0xa2,0x42,0xf6,0x7c,0xbc,0x6a,0xc7,0x07,0x2e,0x25,0xd1,0x90,0x62,0x20, + 0xc6,0x8d,0x51,0xc2,0x2c,0x45,0x39,0x4e,0x03,0xda,0xf7,0x18,0xe8,0xcc,0x0a,0x3a,0xd9,0x45,0xd8,0x6c, + 0x6e,0x34,0x8b,0x62,0x9c,0x4e,0x15,0xf9,0x43,0xee,0xe5,0x97,0xc0,0x3f,0xad,0x35,0x13,0xc5,0x2b,0x06, + 0xc7,0x41,0xfd,0xe2,0xf7,0x7e,0x45,0xad,0x9b,0xd1,0xe1,0x66,0xed,0xf8,0x7a,0x4b,0x94,0x39,0x7a,0x2f, + 0xeb,0xe8,0x3f,0x43,0xd8,0x35,0xd6,0x56,0xfa,0x74,0xe7,0x6d,0xe6,0xed,0xac,0x65,0x84,0xfe,0xd0,0x4d, + 0x06,0x12,0xde,0xda,0x59,0x00,0x3c,0x09,0x5c,0xcf,0x88,0x4b,0xe8,0x3d,0xb4,0x15,0x21,0x92,0xcc,0x6d, + 0xa6,0x51,0xe2,0x8e,0x97,0xf1,0xf4,0x82,0x46,0xcb,0xc4,0x53,0x5e,0xda,0x5c,0x9d,0x65,0x92,0x01,0x65, + 0x89,0x00,0xe5,0xb6,0x99,0xff,0x26,0x40,0xf1,0x2f,0x19,0x31,0x08,0x1a,0xb1,0x67,0x55,0x86,0x0d,0xae, + 0x35,0x33,0x86,0xbc,0x97,0x48,0x92,0xd7,0x96,0x60,0xf8,0xce,0xfc,0x96,0xeb,0x87,0xc4,0x73,0xcc,0x94, + 0x9b,0x58,0x5b,0xf3,0x7a,0xa4,0x27,0x13,0xd6,0x4f,0xf4,0x69 +}; +unsigned int www_google_com_cer_len = 1512; + +/* subject:/CN=Leaf revoked ok1/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=CA revoked/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char leaf_subCANotOnAllowlist_Cert[] = { + 0x30,0x82,0x04,0x41,0x30,0x82,0x03,0x29,0xA0,0x03,0x02,0x01,0x02,0x02,0x05,0x00, + 0xFA,0x6B,0x46,0x67,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x30,0x7C,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x0C,0x0A, + 0x43,0x41,0x20,0x72,0x65,0x76,0x6F,0x6B,0x65,0x64,0x31,0x22,0x30,0x20,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65, + 0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x20,0x17,0x0D,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30, + 0x37,0x5A,0x18,0x0F,0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30, + 0x30,0x37,0x5A,0x30,0x81,0x82,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x10,0x4C,0x65,0x61,0x66,0x20,0x72,0x65,0x76,0x6F,0x6B,0x65,0x64,0x20,0x6F,0x6B, + 0x31,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69, + 0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43, + 0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12,0x30,0x10,0x06,0x03, + 0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,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,0xC0,0x08,0xBA,0xCA,0x52,0x4C,0x3F, + 0xD7,0x80,0x14,0x2A,0x58,0xD7,0x3B,0xC2,0xB3,0x30,0xF5,0xA9,0x91,0xCA,0x28,0xE0, + 0xA3,0xF3,0x4B,0xB3,0x5F,0x10,0xBF,0x15,0x48,0xB0,0xE2,0xD7,0x60,0x57,0xC6,0xEA, + 0x9D,0x08,0x57,0xF7,0x1F,0x54,0x63,0xEB,0x8F,0x33,0x9D,0xD1,0xB0,0xFE,0x5D,0x28, + 0x99,0xA4,0xCC,0xBB,0xF3,0x07,0x3D,0xED,0xC3,0x07,0x4A,0x0B,0x92,0x66,0xA1,0x06, + 0xAC,0xA6,0x89,0xCC,0xCD,0x48,0xC5,0x34,0x54,0xB0,0x68,0x9D,0x50,0xAC,0xC6,0x3A, + 0x6C,0x5E,0xC7,0x4C,0x11,0xC5,0x43,0x4A,0x59,0xB4,0x74,0xE5,0xC3,0x5D,0xA7,0xB8, + 0x4C,0x55,0x6D,0x84,0x66,0x63,0xEE,0xAA,0xDC,0xF0,0x4B,0x7B,0x90,0xCE,0xA2,0x8D, + 0x5A,0x58,0x7B,0xC0,0x12,0xF6,0xA5,0x4F,0x79,0xAD,0x06,0x22,0xDA,0xA0,0xE7,0xD5, + 0xBE,0x2E,0x46,0xF2,0x4C,0x6B,0x1E,0x0A,0xED,0xF9,0x5E,0xBB,0x73,0x6F,0x8B,0xE6, + 0xAC,0xDB,0x18,0x2B,0x01,0xFB,0x58,0x7A,0xB2,0x9B,0x52,0x0D,0x41,0xCA,0xD4,0x18, + 0x0C,0x84,0x42,0xE8,0x70,0x12,0x99,0xC8,0x95,0xF3,0x19,0x0C,0xF0,0x75,0xB3,0x49, + 0xFC,0x9A,0x7A,0x58,0xE9,0xD1,0xFB,0xCD,0x39,0x3B,0x27,0x58,0xED,0x14,0xF9,0x47, + 0x1F,0xCE,0x31,0x2D,0x5B,0xA1,0x1E,0x2A,0x78,0x83,0x5F,0x18,0x55,0x66,0xAE,0xAA, + 0x47,0x50,0xB2,0x42,0x7C,0x6D,0xA6,0x63,0x75,0x32,0x32,0x3E,0xBD,0xA3,0x2F,0x7D, + 0xE8,0x69,0xD1,0x61,0xD9,0x02,0x86,0x60,0xBF,0xC7,0x5E,0x0B,0xDE,0x87,0x9D,0x18, + 0xAF,0x42,0x37,0x98,0x2F,0x56,0x19,0xB7,0xF1,0x02,0x03,0x01,0x00,0x01,0xA3,0x81, + 0xC0,0x30,0x81,0xBD,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, + 0x03,0x02,0x07,0x80,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,0xF8, + 0xA6,0xB9,0x3E,0xE8,0xBA,0x5A,0xED,0x7C,0x5C,0x96,0x07,0xFE,0x75,0x0C,0x79,0xE8, + 0xBF,0xB6,0x12,0x30,0x41,0x06,0x03,0x55,0x1D,0x1F,0x04,0x3A,0x30,0x38,0x30,0x36, + 0xA0,0x34,0xA0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x76,0x61,0x6C, + 0x69,0x64,0x74,0x65,0x73,0x74,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x67,0x65,0x6F, + 0x66,0x66,0x6B,0x2E,0x6E,0x65,0x74,0x2F,0x76,0x32,0x2D,0x72,0x65,0x76,0x6F,0x6B, + 0x65,0x64,0x2E,0x63,0x72,0x6C,0x30,0x39,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x01,0x01,0x04,0x2D,0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x30,0x01,0x86,0x1D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6B,0x6E,0x6F,0x77,0x6E, + 0x2D,0x61,0x6E,0x73,0x77,0x65,0x72,0x2D,0x6F,0x63,0x73,0x70,0x2F,0x6F,0x63,0x73, + 0x70,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x90,0x28,0xA2,0xBF,0x5B,0x3F,0x46,0xFB,0xF1,0x6D,0xDF, + 0x7B,0xED,0x92,0x2C,0xCA,0xB3,0x38,0xF9,0xE3,0x7F,0xA6,0xD6,0xBA,0x22,0x5A,0x06, + 0x27,0x21,0xBA,0xC6,0x1C,0xDA,0x64,0x3B,0xB8,0x70,0x89,0x06,0xF8,0x04,0x8F,0x69, + 0xC2,0x69,0x46,0xF5,0x22,0x8A,0x91,0xE3,0x77,0x21,0x46,0xF7,0x8E,0xDF,0xDE,0x46, + 0xD4,0x19,0x62,0xDC,0xC7,0x02,0x9E,0xE6,0x31,0x0A,0x13,0xA1,0x54,0x3B,0xE6,0x5C, + 0x17,0x3F,0xAB,0xDC,0x29,0x0F,0x93,0x74,0xC0,0xD9,0xA3,0xD4,0x76,0xA2,0x1D,0x7E, + 0x79,0xDF,0x8D,0xFC,0xAE,0x11,0xBD,0x83,0x95,0x12,0x70,0xA3,0xE9,0x39,0xCF,0x06, + 0x49,0x93,0xD8,0x05,0x53,0x07,0xB9,0xCF,0xD9,0x8E,0x1D,0xA2,0xBB,0x79,0x54,0x94, + 0xF8,0x9D,0xB4,0x38,0xE6,0x98,0x65,0x3C,0xD0,0x7E,0x16,0x8F,0x11,0x84,0x76,0xA4, + 0x4A,0x55,0xC3,0x09,0xED,0x68,0xA8,0x62,0xD1,0x97,0x51,0x8C,0x64,0x33,0xFD,0xFA, + 0x3F,0xD7,0xA5,0x3B,0xD1,0x0B,0xC0,0xCF,0x34,0x77,0x66,0x9F,0x15,0x0D,0xB0,0x0C, + 0x8C,0x5F,0x57,0x72,0xFC,0xB9,0xB6,0x5A,0x34,0xF3,0xC4,0x78,0x5D,0x9F,0xAC,0xD1, + 0x99,0x6D,0x98,0xBE,0x80,0x68,0x1F,0xAA,0xF6,0xEE,0x3C,0x1D,0x8B,0xBF,0x59,0x2A, + 0xC5,0x67,0xAA,0x52,0x9A,0xFD,0x8A,0x14,0x65,0x3C,0x71,0xB8,0xE9,0x0E,0xAF,0x20, + 0x6A,0x42,0x90,0x22,0xCB,0xE5,0x79,0x99,0xAC,0x91,0xAE,0x63,0x1A,0xDB,0x4E,0xD9, + 0xCC,0x2A,0x52,0xD4,0x02,0x51,0x42,0xAF,0x27,0x0C,0xA8,0x41,0xFE,0x33,0xBC,0xF5, + 0x91,0x7E,0x15,0x6A,0x5A, +}; + +/* subject:/CN=CA revoked/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=Valid Test CA Root V2/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char subCANotOnAllowlist_Cert[] = { + 0x30,0x82,0x04,0x2C,0x30,0x82,0x03,0x14,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x3E, + 0x1D,0x6A,0x98,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, + 0x05,0x00,0x30,0x81,0x87,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15, + 0x56,0x61,0x6C,0x69,0x64,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x20,0x52,0x6F, + 0x6F,0x74,0x20,0x56,0x32,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19, + 0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65, + 0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12, + 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, + 0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x20,0x17,0x0D, + 0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30,0x36,0x5A,0x18,0x0F,0x32, + 0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30,0x30,0x36,0x5A,0x30,0x7C, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x0C,0x0A,0x43,0x41,0x20,0x72,0x65, + 0x76,0x6F,0x6B,0x65,0x64,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19, + 0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65, + 0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12, + 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, + 0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,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,0xCA,0x23,0x02, + 0x7B,0x12,0x84,0x9C,0x8D,0x0E,0x43,0x70,0xD8,0xAB,0x93,0x8D,0x20,0xB0,0xF0,0xC0, + 0xDA,0xE6,0xFB,0xBD,0x96,0x26,0x1A,0x5B,0x74,0x24,0x21,0x97,0x90,0xFF,0x7F,0x75, + 0xF6,0x47,0x3C,0x7C,0x79,0xD9,0x0A,0x9A,0xA3,0x84,0x1C,0x3A,0x3E,0x63,0xC0,0xA7, + 0x3C,0x0A,0xB6,0xD1,0x16,0x8D,0x3E,0x5F,0xEF,0x97,0x11,0x91,0x18,0x19,0x42,0xA7, + 0xC5,0xCA,0x81,0xB2,0xD7,0xE4,0x8F,0x18,0x65,0xAC,0x42,0xB1,0xE1,0x43,0x1D,0x46, + 0xF0,0x80,0x45,0xFC,0x10,0xE5,0x7B,0xE1,0x7C,0xF7,0x49,0xC1,0x8D,0x8F,0xF2,0x2D, + 0xE6,0x28,0x51,0x45,0xA8,0xBB,0x83,0x5B,0xAD,0xB8,0x95,0xBF,0x92,0xD2,0xF8,0x9A, + 0xB3,0x31,0x50,0x58,0x4A,0xBA,0xA5,0xC7,0x3F,0x54,0xCC,0x3A,0xE0,0x58,0xCA,0xA2, + 0x3D,0x76,0x41,0xE5,0x5A,0x6F,0x7D,0xD6,0xD0,0x74,0xBC,0xE5,0x99,0xCD,0xBD,0x11, + 0x1C,0x28,0x24,0x96,0xDE,0x63,0x3B,0xDC,0xF8,0xE9,0x22,0x9E,0xCD,0x3D,0x82,0xE7, + 0x3C,0x5A,0x03,0xFA,0xE6,0x01,0x7B,0xA4,0xB6,0x4D,0x37,0xCE,0x18,0x2C,0xF1,0xFA, + 0xE1,0xB8,0x86,0x45,0x1E,0xAA,0x61,0xD2,0x89,0xF2,0x43,0x8E,0x8D,0x70,0x64,0x3F, + 0x1A,0x45,0x7C,0x9C,0xA6,0x1B,0x75,0xB6,0x44,0x81,0x0A,0xBA,0x90,0x00,0x54,0xDB, + 0x62,0xE1,0xC5,0x4B,0x2E,0x0D,0x49,0x9F,0xDC,0x4E,0xCF,0xE1,0xB1,0xC1,0xDD,0x88, + 0xA1,0xBA,0x8F,0x96,0x13,0xAB,0x14,0x6C,0xF7,0x2E,0xE4,0x46,0x49,0xE1,0x07,0xFF, + 0xA1,0xBC,0x85,0x3C,0x56,0x83,0x40,0x32,0xE4,0x4B,0xC6,0x80,0x43,0x02,0x03,0x01, + 0x00,0x01,0xA3,0x81,0xA7,0x30,0x81,0xA4,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, + 0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01, + 0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xF8,0xA6,0xB9,0x3E,0xE8,0xBA,0x5A,0xED,0x7C, + 0x5C,0x96,0x07,0xFE,0x75,0x0C,0x79,0xE8,0xBF,0xB6,0x12,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xBA,0x56,0xD8,0x57,0x66,0xBD,0xFC,0x5B, + 0xE2,0x10,0xF2,0x39,0xB3,0xAF,0xB2,0x72,0xED,0x55,0x0F,0x1C,0x30,0x3E,0x06,0x03, + 0x55,0x1D,0x1F,0x04,0x37,0x30,0x35,0x30,0x33,0xA0,0x31,0xA0,0x2F,0x86,0x2D,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x76,0x61,0x6C,0x69,0x64,0x74,0x65,0x73,0x74,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x67,0x65,0x6F,0x66,0x66,0x6B,0x2E,0x6E,0x65,0x74, + 0x2F,0x76,0x32,0x2D,0x72,0x6F,0x6F,0x74,0x2E,0x63,0x72,0x6C,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00, + 0xBF,0xC5,0x46,0x37,0x47,0x5A,0x47,0xE9,0x14,0xB8,0xDC,0x68,0x1C,0xF1,0xAA,0x2E, + 0x5B,0x2B,0xF0,0xEE,0x7A,0x7D,0xF2,0x6B,0x44,0x77,0x57,0x56,0x58,0xEB,0xFC,0x9A, + 0x19,0x9B,0xDF,0xE7,0x58,0x98,0xF0,0x5C,0xC7,0x3A,0x22,0x85,0x84,0x46,0xFB,0x71, + 0x09,0x2F,0xFC,0x22,0x51,0x49,0xF6,0x28,0xEF,0xC5,0xB6,0x5C,0x71,0xFC,0x61,0x12, + 0xC1,0xA3,0xE1,0xD4,0x77,0x71,0xCC,0xDF,0x12,0x85,0xB4,0x7D,0x43,0xCF,0x7D,0x2A, + 0x4F,0xF1,0x3A,0x09,0x6E,0xE4,0xC4,0xD5,0xB6,0x8D,0xC7,0x03,0xEB,0x07,0xBC,0x1C, + 0x0A,0xB4,0x17,0x3E,0xBF,0xC7,0x3E,0xE7,0x9F,0x98,0x51,0xC1,0xA4,0x69,0x09,0x58, + 0x88,0xD9,0xA4,0xAE,0xB2,0xE7,0x53,0x5F,0xCA,0x8E,0xE9,0x1B,0x84,0x04,0xEA,0x4F, + 0xFD,0xE2,0x86,0x6F,0xF4,0x1E,0xD3,0x3F,0xF7,0x2D,0x40,0xDF,0x22,0x0E,0x9F,0x76, + 0x91,0xC8,0x99,0x6F,0x79,0x54,0x23,0xFE,0xBC,0xE7,0xD8,0xDF,0xD9,0x86,0x55,0x1D, + 0x9B,0xF8,0x67,0xF4,0xD0,0xC3,0x8D,0xF3,0x47,0xAC,0xD2,0x04,0x7B,0xCC,0x4D,0x0A, + 0xF9,0x1E,0xEF,0x5C,0x1D,0x0F,0x55,0x28,0x73,0x59,0x5F,0x91,0x84,0x2E,0xE3,0xBA, + 0x59,0xA1,0x66,0x5F,0x62,0x3E,0x5C,0x26,0xBF,0x1C,0x5E,0xBA,0x51,0x9B,0xCB,0x08, + 0x59,0x3D,0xDD,0xF7,0xFF,0x8D,0x02,0xAB,0xC2,0x15,0x8D,0x61,0x54,0x9A,0xFB,0xBB, + 0x89,0x92,0x58,0x3A,0x27,0xBE,0xB1,0xE5,0xDF,0x91,0x16,0x94,0x8F,0x16,0x88,0x8D, + 0xDD,0x64,0xC4,0xF9,0x9B,0x7C,0x19,0x4B,0x9E,0x4F,0x6C,0xFC,0xBF,0x2A,0x7A,0x1D, +}; + +/* subject:/CN=Leaf sha256 valid complete ok1/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=CA sha256 valid complete/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char leafOnAllowList_Cert[] = { + 0x30,0x82,0x04,0x6C,0x30,0x82,0x03,0x54,0xA0,0x03,0x02,0x01,0x02,0x02,0x05,0x00, + 0xC9,0x44,0x22,0x78,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x30,0x81,0x8A,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x18,0x43,0x41,0x20,0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6C,0x69,0x64, + 0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x31,0x22,0x30,0x20,0x06,0x03,0x55, + 0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63, + 0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70, + 0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C, + 0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53, + 0x30,0x20,0x17,0x0D,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30,0x37, + 0x5A,0x18,0x0F,0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30,0x30, + 0x37,0x5A,0x30,0x81,0x90,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04,0x03,0x0C,0x1E, + 0x4C,0x65,0x61,0x66,0x20,0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6C,0x69, + 0x64,0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x20,0x6F,0x6B,0x31,0x31,0x22, + 0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50, + 0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20, + 0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07, + 0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,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,0xB4,0x45,0x14,0x8C,0x97,0x75,0x09,0xD1,0x43,0x55, + 0x8F,0x80,0x19,0x11,0x13,0x83,0xB2,0x6C,0x38,0x23,0xCE,0x1C,0x61,0xFE,0x41,0xD7, + 0xB4,0x78,0x98,0xF9,0xE9,0x72,0xCA,0x45,0xB4,0x0F,0xEB,0x32,0x57,0x45,0x93,0x6F, + 0x7F,0xC8,0xDC,0xEC,0xE1,0x2D,0x77,0x8A,0x8C,0x8D,0x9E,0x65,0xE0,0xE9,0x09,0x02, + 0xA1,0x1E,0x5F,0xDA,0x00,0xED,0xDD,0x49,0x34,0xCA,0xD8,0xA2,0x8E,0x3F,0xF3,0x5F, + 0x3E,0x6C,0x86,0x31,0x83,0x01,0xB4,0xCA,0x95,0xD3,0x5F,0x5A,0xBF,0x09,0x7E,0x3D, + 0x2A,0xBC,0x03,0x96,0xB7,0xC5,0x66,0x04,0x77,0xB7,0x37,0x43,0xA3,0x08,0x3B,0x0C, + 0x39,0x7D,0x98,0xAD,0x97,0xF3,0x69,0x65,0x07,0x4A,0x0E,0xF3,0xB9,0xD1,0xD5,0xE2, + 0xB8,0x91,0x39,0xBB,0xBE,0x3C,0xE7,0x37,0xCD,0xB4,0x22,0x3A,0x22,0xE8,0xFB,0x65, + 0xC8,0x52,0x88,0x30,0xFC,0x84,0x00,0xE0,0x17,0xB7,0x46,0xF0,0xF1,0x14,0xC3,0x7B, + 0x10,0x6A,0x26,0x5A,0xD8,0x09,0x86,0x91,0xC7,0x2A,0xEE,0xC7,0xA6,0x12,0x30,0x32, + 0x38,0x6D,0x78,0x38,0x59,0x72,0xC8,0x5A,0xC9,0x9E,0x3C,0xB5,0xAD,0x82,0xD7,0x83, + 0xC4,0xC3,0x30,0x15,0x46,0x2F,0x24,0xE0,0x9B,0xDD,0x12,0x97,0x6E,0x54,0x6C,0x8C, + 0x31,0x30,0xD4,0x24,0x40,0x48,0x46,0x58,0x51,0xF9,0x86,0x2B,0xA4,0x8E,0x16,0x63, + 0xAE,0x35,0x8E,0xCD,0x64,0x4B,0xA8,0x9D,0x68,0xD5,0x8C,0xBE,0xCF,0x06,0x4C,0x91, + 0xAC,0x77,0x81,0xCE,0x16,0x6C,0x92,0xCE,0x30,0x03,0x51,0x79,0xDF,0xA4,0x11,0xC0, + 0x4F,0xAC,0xF7,0x28,0x8F,0x09,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xCE,0x30,0x81, + 0xCB,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,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,0x49,0x96,0xB4,0x72, + 0xB2,0x4C,0x90,0x9B,0xA3,0x22,0x66,0x52,0x66,0x72,0x25,0x3A,0x51,0x93,0xE6,0xC7, + 0x30,0x4F,0x06,0x03,0x55,0x1D,0x1F,0x04,0x48,0x30,0x46,0x30,0x44,0xA0,0x42,0xA0, + 0x40,0x86,0x3E,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x76,0x61,0x6C,0x69,0x64,0x74, + 0x65,0x73,0x74,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x67,0x65,0x6F,0x66,0x66,0x6B, + 0x2E,0x6E,0x65,0x74,0x2F,0x76,0x32,0x2D,0x73,0x68,0x61,0x32,0x35,0x36,0x2D,0x76, + 0x61,0x6C,0x69,0x64,0x2D,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x2E,0x63,0x72, + 0x6C,0x30,0x39,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x2D,0x30, + 0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x1D,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6B,0x6E,0x6F,0x77,0x6E,0x2D,0x61,0x6E,0x73,0x77, + 0x65,0x72,0x2D,0x6F,0x63,0x73,0x70,0x2F,0x6F,0x63,0x73,0x70,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00, + 0x2F,0x35,0xE8,0xE8,0xF5,0x5C,0x7E,0x48,0x81,0xC9,0xCF,0xF5,0x45,0x08,0xB9,0x47, + 0x08,0xCD,0x5C,0x4A,0xD5,0xD3,0xB2,0x4C,0x9E,0x9F,0xDD,0x7F,0xC6,0xF1,0x76,0xFC, + 0xCB,0xC0,0x7C,0x50,0xCC,0x63,0xA8,0xE3,0xB3,0x79,0xA7,0x80,0xE4,0x77,0xC3,0x8A, + 0x9E,0x25,0x93,0xB2,0x51,0x00,0x5C,0x4D,0xE1,0x9F,0x16,0xFD,0xC7,0x30,0x28,0xA7, + 0x91,0x5E,0xE5,0x33,0x2A,0xE7,0xB3,0x19,0x12,0x0D,0x6B,0xC6,0x09,0xA9,0xF9,0x2C, + 0x32,0x4A,0xB6,0x3F,0x8E,0xBB,0x5F,0x14,0x39,0x32,0x87,0xBB,0x23,0xDF,0x81,0x72, + 0x40,0xEB,0x54,0xF6,0xA8,0x33,0x1E,0xE2,0xB7,0x54,0xD8,0x80,0xB4,0xFA,0x74,0xA2, + 0xC2,0xEB,0x26,0x11,0x60,0xFD,0x0B,0x37,0x83,0x7F,0x1C,0x14,0xE6,0xCA,0x45,0x8A, + 0xA7,0xF9,0x47,0x94,0xA8,0xCD,0xCE,0x0D,0x5E,0x14,0x63,0x0A,0xCB,0x6D,0xE6,0x7C, + 0xED,0xF0,0x57,0xFD,0x0F,0x29,0xB7,0x47,0x3A,0x7A,0xE6,0x62,0x58,0xD9,0x55,0x80, + 0x5B,0xF6,0xD7,0x98,0x5B,0xE4,0x47,0xAE,0x60,0xC5,0x79,0x1D,0x53,0x94,0x81,0x87, + 0x20,0xC8,0x27,0x95,0xF2,0x41,0xE7,0xA3,0xA4,0xB8,0xE5,0x7E,0x59,0xDD,0xFF,0xA3, + 0x79,0x64,0x4A,0x65,0x0A,0x42,0x29,0xD0,0x0A,0x35,0x41,0xF6,0xCA,0x05,0x5A,0x72, + 0xBE,0xAA,0x4A,0x77,0x9A,0xC5,0x1B,0x59,0x46,0x40,0xF7,0x9D,0x75,0xAE,0xAF,0x92, + 0x12,0xF6,0x82,0xEA,0xCF,0xF9,0x6E,0x4F,0x94,0xB7,0x17,0x90,0xA9,0xAF,0x45,0xEA, + 0xAE,0x76,0xB4,0x52,0x2E,0x10,0x4C,0x74,0x7C,0x92,0x70,0xD4,0xEA,0x4D,0x65,0x6B, +}; + +/* subject:/CN=Leaf sha256 valid complete revoked1/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=CA sha256 valid complete/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char leafNotOnAllowList_Cert[] = { + 0x30,0x82,0x04,0x70,0x30,0x82,0x03,0x58,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x20, + 0x11,0x11,0xF5,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, + 0x05,0x00,0x30,0x81,0x8A,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18, + 0x43,0x41,0x20,0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6C,0x69,0x64,0x20, + 0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04, + 0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74, + 0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65, + 0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02, + 0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30, + 0x20,0x17,0x0D,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30,0x37,0x5A, + 0x18,0x0F,0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30,0x30,0x37, + 0x5A,0x30,0x81,0x95,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04,0x03,0x0C,0x23,0x4C, + 0x65,0x61,0x66,0x20,0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6C,0x69,0x64, + 0x20,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74,0x65,0x20,0x72,0x65,0x76,0x6F,0x6B,0x65, + 0x64,0x31,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C, + 0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20, + 0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12,0x30,0x10,0x06, + 0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,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,0xB1,0x1D,0xC6,0x90,0xDB,0xE4, + 0x97,0x45,0x2E,0xBB,0x6C,0x70,0x6D,0x89,0xE6,0x98,0x0D,0xA7,0x3C,0x7D,0x9C,0x36, + 0xE6,0xEC,0x96,0xA7,0xBE,0xC3,0xE0,0x3F,0x73,0xA7,0xCB,0xDA,0xE9,0xEA,0x56,0xE1, + 0xE8,0x55,0x9E,0xFF,0x72,0x43,0x37,0x88,0x1C,0x79,0x8B,0xA6,0xCD,0x3B,0xFB,0xDC, + 0x00,0xA2,0xB1,0xF6,0xF9,0x01,0x6B,0x2F,0xD7,0xA3,0x9A,0x31,0xC6,0xD2,0x94,0x48, + 0x34,0x01,0x4C,0x20,0x5A,0x4B,0xBE,0xDB,0x4D,0xDD,0xB2,0xB3,0x0F,0xEC,0x5A,0x94, + 0x08,0x19,0x77,0x6C,0xE0,0x46,0x87,0xD8,0x07,0x63,0x72,0x06,0x7B,0x42,0x82,0xEA, + 0x18,0xCE,0x43,0x10,0xC6,0xD2,0xB6,0x6A,0x51,0xF0,0x19,0xBD,0xF3,0x1B,0xB0,0x78, + 0x92,0x97,0x25,0xDF,0x16,0xA4,0x99,0xE0,0x36,0x50,0x37,0x67,0x47,0xCE,0x7D,0x62, + 0x07,0xFB,0x94,0x37,0xA6,0x29,0xF7,0x1F,0x3F,0x63,0x70,0x26,0x81,0x06,0x57,0x23, + 0x74,0x2B,0x16,0xA3,0x3A,0x1C,0xE7,0xF6,0x2E,0x51,0x3B,0x38,0x7B,0x3F,0x43,0xE4, + 0xEC,0xC1,0x35,0x43,0x66,0xC1,0x32,0x7D,0xB2,0x91,0xB7,0x40,0x1E,0x80,0xFD,0x39, + 0x25,0xF8,0xDB,0x4A,0x57,0xBE,0x41,0x97,0xF5,0xF8,0xA3,0xFA,0xC5,0xC1,0xF0,0xDF, + 0x6F,0x9F,0x07,0x41,0xA0,0xFB,0x21,0x7C,0x35,0x64,0xA3,0xB5,0xD6,0xE1,0xFF,0x0E, + 0x34,0x22,0xD8,0xD8,0x84,0x75,0x5A,0xDD,0xC3,0xCB,0x33,0x6F,0x98,0x82,0xF6,0x69, + 0x1A,0x4C,0x3E,0x50,0x3D,0x35,0xE6,0xA9,0xE2,0x64,0x7C,0x0F,0x3E,0xD8,0xC0,0x93, + 0x52,0xDB,0x87,0xA1,0x0B,0x4C,0x36,0x57,0x91,0x67,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x81,0xCE,0x30,0x81,0xCB,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, + 0x04,0x03,0x02,0x07,0x80,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, + 0x49,0x96,0xB4,0x72,0xB2,0x4C,0x90,0x9B,0xA3,0x22,0x66,0x52,0x66,0x72,0x25,0x3A, + 0x51,0x93,0xE6,0xC7,0x30,0x4F,0x06,0x03,0x55,0x1D,0x1F,0x04,0x48,0x30,0x46,0x30, + 0x44,0xA0,0x42,0xA0,0x40,0x86,0x3E,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x76,0x61, + 0x6C,0x69,0x64,0x74,0x65,0x73,0x74,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x67,0x65, + 0x6F,0x66,0x66,0x6B,0x2E,0x6E,0x65,0x74,0x2F,0x76,0x32,0x2D,0x73,0x68,0x61,0x32, + 0x35,0x36,0x2D,0x76,0x61,0x6C,0x69,0x64,0x2D,0x63,0x6F,0x6D,0x70,0x6C,0x65,0x74, + 0x65,0x2E,0x63,0x72,0x6C,0x30,0x39,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01, + 0x01,0x04,0x2D,0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30, + 0x01,0x86,0x1D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6B,0x6E,0x6F,0x77,0x6E,0x2D, + 0x61,0x6E,0x73,0x77,0x65,0x72,0x2D,0x6F,0x63,0x73,0x70,0x2F,0x6F,0x63,0x73,0x70, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x65,0xFD,0x30,0xA6,0x32,0x7D,0x2A,0xB7,0xB7,0xC3,0xD8,0x66, + 0x49,0x91,0x9C,0x39,0x17,0xB2,0x3F,0x9F,0x62,0xB4,0x8A,0x07,0x9A,0xA8,0xE5,0x1C, + 0x6A,0x62,0xEA,0x77,0x4B,0x7A,0xC0,0xE6,0x24,0x2C,0xAE,0xAE,0x0F,0xE6,0xE6,0x82, + 0x7F,0x02,0xA2,0x3B,0xC8,0x4C,0xB3,0x7C,0x0E,0x7B,0x3C,0x2E,0x52,0x95,0xDB,0x29, + 0xBF,0xFE,0x11,0x5D,0xE2,0xEE,0xE2,0xFC,0xE2,0x48,0x10,0xDE,0xF2,0xD6,0x24,0x66, + 0xD8,0x81,0x76,0xDF,0x0F,0xA5,0x26,0x82,0x8D,0xEB,0xA0,0xDE,0xD8,0x59,0x53,0x69, + 0x0D,0x47,0x9A,0xB2,0xFE,0xB4,0x1D,0xFB,0x32,0x56,0x49,0x09,0xA4,0x52,0xB4,0xB9, + 0x19,0x54,0x4E,0xEC,0x29,0x8A,0x59,0x5D,0x63,0x1B,0xB9,0x09,0x4D,0xF1,0xB0,0x85, + 0xF2,0x91,0xE8,0x7A,0x76,0x38,0x28,0x5C,0x08,0x36,0x9E,0xAC,0x74,0x31,0xD5,0xFF, + 0xDA,0x15,0xCE,0x80,0x15,0x6F,0x23,0xDC,0xB6,0x93,0x01,0xC7,0x12,0x8A,0x06,0xD4, + 0x42,0xE9,0x81,0x29,0xB9,0x2A,0xC7,0xD0,0xA9,0xFA,0xD6,0x6C,0xA4,0x26,0x4D,0x54, + 0x16,0xA7,0x65,0x52,0xB9,0xEF,0x4A,0x68,0xDF,0x14,0xFF,0x73,0x4B,0xED,0x18,0x9B, + 0xDB,0x27,0x66,0x38,0xBF,0x03,0x13,0xCC,0xBC,0xE5,0xBA,0x1C,0x7F,0x62,0x36,0x04, + 0x39,0xA2,0x6E,0x32,0x65,0xA1,0x03,0x7A,0x63,0xC8,0x3C,0x01,0x85,0xE3,0x60,0xAF, + 0x3D,0x1B,0xA9,0x86,0xB6,0xBA,0xD0,0x23,0xDC,0x82,0x05,0x0B,0x6A,0x4F,0x7B,0x82, + 0xC1,0xF6,0xC7,0x23,0xB3,0x6C,0xBC,0x10,0x88,0x89,0xFF,0xBE,0x45,0xF6,0x5A,0xA1, + 0x00,0x0F,0xD9,0x83, +}; + +/* subject:/CN=CA sha256 valid complete/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=Valid Test CA Root V2/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char ca1_Cert[] = { + 0x30,0x82,0x04,0x3C,0x30,0x82,0x03,0x24,0xA0,0x03,0x02,0x01,0x02,0x02,0x05,0x00, + 0xE4,0xF5,0x4B,0x6E,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x30,0x81,0x87,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x15,0x56,0x61,0x6C,0x69,0x64,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x20,0x52, + 0x6F,0x6F,0x74,0x20,0x56,0x32,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54, + 0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74, + 0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x20,0x17, + 0x0D,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x34,0x30,0x30,0x35,0x5A,0x18,0x0F, + 0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x34,0x30,0x30,0x35,0x5A,0x30, + 0x81,0x8A,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x43,0x41,0x20, + 0x73,0x68,0x61,0x32,0x35,0x36,0x20,0x76,0x61,0x6C,0x69,0x64,0x20,0x63,0x6F,0x6D, + 0x70,0x6C,0x65,0x74,0x65,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C,0x19, + 0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54,0x65, + 0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x12, + 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, + 0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,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,0xDE,0x13,0x51, + 0x00,0x15,0x31,0xFE,0x34,0x3D,0x25,0x3F,0x63,0x7B,0x77,0x40,0x41,0x67,0xFE,0xD4, + 0xEF,0xE2,0xE1,0x83,0x3C,0x27,0x29,0x76,0x41,0x55,0xBE,0x00,0x71,0xEA,0x78,0x5B, + 0x60,0xA5,0x6B,0xD7,0xE8,0xD3,0x20,0x49,0xDA,0xED,0xD8,0x55,0xA5,0x5A,0xDF,0x01, + 0x0C,0x7E,0x41,0x0B,0xAA,0x61,0xCF,0xBD,0xBF,0x87,0x2F,0xCC,0x02,0x79,0x92,0x51, + 0x00,0x29,0x1E,0x6F,0x09,0x9F,0x1D,0xA9,0x85,0xA8,0xB6,0x0B,0xF6,0x8F,0x07,0x46, + 0x08,0xD2,0x0F,0x92,0x70,0x25,0x82,0xA4,0x73,0xA8,0xF4,0xE6,0x8F,0x5D,0x6D,0x49, + 0x0F,0xE4,0x05,0xD2,0xEF,0xA5,0xE8,0x49,0xAD,0xA5,0x08,0xC0,0x89,0x4F,0xEF,0xA7, + 0x36,0xA1,0xF2,0x0D,0xBD,0x41,0xAD,0x63,0x6B,0xC4,0x65,0xD1,0x79,0x94,0xAF,0x3A, + 0x35,0xA3,0x7A,0x5B,0xE7,0xA0,0x78,0x16,0x4E,0xB7,0x0A,0x1A,0x3A,0xF5,0xC6,0xA5, + 0x6B,0x9C,0x14,0x0F,0x15,0xEB,0xBE,0xA1,0x29,0xA6,0xA7,0xB2,0x92,0x3A,0xD6,0xFA, + 0x91,0xEF,0xCB,0xC4,0x7C,0xDB,0x49,0x11,0x73,0x0D,0x94,0xCA,0x0C,0xEA,0x53,0xAE, + 0x9C,0xCA,0x07,0xC7,0x48,0xC2,0xC0,0xE3,0x0C,0x58,0x1C,0xA5,0xE0,0x27,0x45,0xE3, + 0xCD,0xEC,0x17,0x50,0xE7,0xC5,0xD1,0x58,0x5A,0x19,0x3E,0xA5,0xDA,0xE3,0x19,0xB0, + 0x63,0x53,0x0B,0x53,0xDB,0xF0,0x40,0xF2,0xAF,0xBA,0x20,0xA5,0x96,0xB2,0x5E,0xD0, + 0x0F,0x28,0xED,0x5F,0xCC,0xEB,0x69,0x16,0xF0,0xCD,0x22,0xDF,0x7B,0xBF,0x8F,0x32, + 0x11,0x9F,0xF8,0x29,0x48,0x5D,0x6A,0x0A,0xDB,0x46,0x70,0x80,0x19,0x02,0x03,0x01, + 0x00,0x01,0xA3,0x81,0xA7,0x30,0x81,0xA4,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01, + 0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01, + 0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x49,0x96,0xB4,0x72,0xB2,0x4C,0x90,0x9B,0xA3, + 0x22,0x66,0x52,0x66,0x72,0x25,0x3A,0x51,0x93,0xE6,0xC7,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xBA,0x56,0xD8,0x57,0x66,0xBD,0xFC,0x5B, + 0xE2,0x10,0xF2,0x39,0xB3,0xAF,0xB2,0x72,0xED,0x55,0x0F,0x1C,0x30,0x3E,0x06,0x03, + 0x55,0x1D,0x1F,0x04,0x37,0x30,0x35,0x30,0x33,0xA0,0x31,0xA0,0x2F,0x86,0x2D,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x76,0x61,0x6C,0x69,0x64,0x74,0x65,0x73,0x74,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x67,0x65,0x6F,0x66,0x66,0x6B,0x2E,0x6E,0x65,0x74, + 0x2F,0x76,0x32,0x2D,0x72,0x6F,0x6F,0x74,0x2E,0x63,0x72,0x6C,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00, + 0x75,0xDE,0xCF,0x34,0xBD,0xF4,0xAF,0x9C,0x50,0xDA,0x36,0x78,0xE1,0xE1,0xCD,0x54, + 0x35,0x61,0xB0,0x4C,0x46,0x17,0x55,0x7D,0x9F,0x1E,0x69,0xCD,0x66,0x62,0x2B,0xF5, + 0x30,0xD9,0xAE,0x36,0xD2,0xF6,0x21,0x03,0x59,0x3B,0xAB,0xFF,0x79,0xA7,0xF8,0x16, + 0xF3,0x79,0x49,0x19,0xF5,0x05,0x4F,0x70,0xB5,0x26,0xA8,0x41,0xB0,0x66,0x33,0xA1, + 0x3C,0xF9,0xF9,0x61,0x77,0x5F,0x52,0xA7,0x5A,0xC1,0xA1,0x1D,0xA9,0x2B,0x7A,0x44, + 0x8C,0x01,0x4C,0x8A,0x5B,0x2C,0xF0,0x10,0xB8,0x17,0xEF,0x45,0xAA,0x1E,0xC9,0x46, + 0xF8,0x19,0x0A,0xE0,0x25,0x9D,0xC1,0xBF,0x6D,0x34,0x1F,0xFA,0xC9,0xFF,0x62,0x5C, + 0x44,0x96,0x01,0x2B,0x4B,0xBF,0xD0,0xD5,0x56,0x07,0xA9,0x43,0x0D,0xF6,0x85,0x7C, + 0x49,0x0B,0x43,0xA9,0xD7,0xAA,0xC2,0xBF,0x0A,0x5B,0xC0,0xD1,0xA1,0x82,0x9F,0x5F, + 0xB8,0xF4,0x0B,0xC5,0x9A,0x40,0x0B,0xC2,0x2D,0xC9,0xF0,0x4A,0x76,0xA9,0x9B,0x58, + 0x25,0xCA,0x13,0x48,0x63,0xE7,0xD5,0x58,0x58,0x91,0x4D,0xEE,0x21,0x14,0x83,0x5E, + 0x2E,0x9B,0xBF,0x74,0x9E,0x03,0x8C,0x86,0xAF,0xB0,0xCC,0xD8,0xC1,0xC2,0x3D,0xFE, + 0xF8,0x2F,0x6E,0x9E,0x42,0xEF,0x8E,0x20,0xE7,0x94,0x56,0xB6,0xDA,0xC1,0x84,0xC6, + 0x77,0xF1,0x27,0x8B,0xA7,0x68,0x0F,0x8A,0x43,0xD5,0xC6,0x99,0x37,0x43,0x4D,0xAF, + 0xAD,0x9C,0xDC,0x3D,0x10,0x7E,0xDF,0xBF,0xDD,0x76,0xE5,0xE6,0xD7,0x90,0x94,0x9D, + 0xCE,0x46,0x27,0xD7,0x10,0xB7,0xC6,0x07,0xA7,0x6D,0xC9,0x9A,0x8E,0xE3,0x71,0xA6, +}; + +/* subject:/CN=Valid Test CA Root V2/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +/* issuer :/CN=Valid Test CA Root V2/OU=Valid Project Test CAs V2/O=Apple Inc./L=Cupertino/ST=CA/C=US */ +unsigned char root_Cert[] = { + 0x30,0x82,0x03,0xD7,0x30,0x82,0x02,0xBF,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0x8C,0x0C,0x8D,0x50,0x34,0x29,0x1D,0xB6,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x87,0x31,0x1E,0x30,0x1C,0x06,0x03, + 0x55,0x04,0x03,0x0C,0x15,0x56,0x61,0x6C,0x69,0x64,0x20,0x54,0x65,0x73,0x74,0x20, + 0x43,0x41,0x20,0x52,0x6F,0x6F,0x74,0x20,0x56,0x32,0x31,0x22,0x30,0x20,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65, + 0x63,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x30,0x20,0x17,0x0D,0x31,0x37,0x30,0x35,0x30,0x31,0x32,0x32,0x33,0x35,0x33, + 0x32,0x5A,0x18,0x0F,0x32,0x31,0x31,0x37,0x30,0x34,0x30,0x37,0x32,0x32,0x33,0x35, + 0x33,0x32,0x5A,0x30,0x81,0x87,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C, + 0x15,0x56,0x61,0x6C,0x69,0x64,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x20,0x52, + 0x6F,0x6F,0x74,0x20,0x56,0x32,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x19,0x56,0x61,0x6C,0x69,0x64,0x20,0x50,0x72,0x6F,0x6A,0x65,0x63,0x74,0x20,0x54, + 0x65,0x73,0x74,0x20,0x43,0x41,0x73,0x20,0x56,0x32,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74, + 0x69,0x6E,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,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,0xC3,0x6D, + 0x14,0x60,0xB3,0xD3,0x0A,0x8A,0xF6,0xBE,0xA7,0x42,0xBF,0xC7,0x11,0xC2,0x6C,0x8A, + 0x94,0xF1,0x0E,0x3D,0x67,0x1C,0x9D,0x4A,0xD6,0x2E,0xC1,0xEA,0x77,0xA2,0x6E,0xAA, + 0x99,0x67,0xBE,0x9F,0xA7,0xBE,0xBD,0x24,0xD1,0x43,0xC8,0x3A,0x88,0x77,0x70,0x24, + 0x9D,0xC6,0x5E,0x53,0x59,0x31,0xA9,0xB1,0x1B,0x1F,0xBA,0x67,0xA7,0x57,0x55,0x0D, + 0xB3,0xD4,0x01,0xAE,0xE4,0xA8,0xC4,0xE7,0x29,0x1C,0xA1,0x39,0x6F,0x1A,0x1C,0x2D, + 0xC1,0x56,0x0A,0x16,0x3F,0x26,0x2F,0x20,0x49,0x33,0x35,0xD2,0xF9,0x6D,0x3B,0x5E, + 0x98,0x59,0x4A,0x70,0xCE,0xFF,0xA4,0x23,0xE6,0x23,0x43,0x23,0xE5,0x8B,0x2F,0xEE, + 0x6A,0x28,0x28,0x4B,0x31,0xA0,0xC8,0x08,0x6C,0x0F,0x38,0x11,0xBC,0x27,0x7F,0x61, + 0xCF,0xB0,0x36,0xB9,0x8C,0xBA,0xBA,0x3E,0x00,0x1E,0xD0,0xFF,0x71,0x92,0xDB,0xA1, + 0x8C,0x1F,0x03,0x29,0x13,0x7C,0xAF,0x87,0xA2,0x41,0x2A,0x5E,0x07,0xFE,0xEF,0x37, + 0xC8,0xB4,0x72,0xC7,0x89,0x03,0x81,0x69,0x01,0xC8,0x7B,0xBE,0x82,0x0A,0x45,0xE2, + 0x88,0xD6,0x63,0x80,0x54,0x29,0x00,0xF6,0xAF,0x58,0xB7,0x65,0x4A,0xD0,0x1A,0x7F, + 0x75,0x01,0x06,0xF6,0xB2,0x94,0x2D,0x5E,0x1D,0x02,0xB8,0xEE,0xFA,0x55,0xC8,0xDD, + 0x84,0x29,0xE7,0x59,0xAA,0xD6,0xEB,0x6C,0x11,0x26,0x16,0xEF,0xF4,0xDA,0x73,0xD8, + 0x39,0xD8,0xEC,0xF1,0x8F,0x1C,0x13,0xD6,0x2C,0x7A,0xD9,0x8A,0x12,0xF1,0xE1,0x3D, + 0xAB,0x81,0x6F,0x7D,0x95,0x74,0x20,0x6A,0xC0,0x1D,0xF4,0x5B,0x7C,0xDD,0x02,0x03, + 0x01,0x00,0x01,0xA3,0x42,0x30,0x40,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, + 0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01, + 0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04, + 0x16,0x04,0x14,0xBA,0x56,0xD8,0x57,0x66,0xBD,0xFC,0x5B,0xE2,0x10,0xF2,0x39,0xB3, + 0xAF,0xB2,0x72,0xED,0x55,0x0F,0x1C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xB6,0x57,0xE2,0x6C,0x23, + 0x90,0x87,0xD5,0x40,0xF4,0xE2,0x39,0x35,0x2F,0x1B,0xFB,0x31,0x0E,0x14,0xF9,0xFF, + 0x97,0x5C,0xED,0x7A,0x6D,0x5F,0x80,0x1F,0x98,0x93,0x0A,0x13,0xA5,0x8F,0x9B,0x2B, + 0x20,0x0E,0xAF,0x62,0x1B,0xB0,0xF8,0xBB,0x00,0xBD,0xDC,0x56,0x3B,0xD9,0x4B,0x6C, + 0x7B,0x80,0xEA,0x18,0xC7,0x32,0x8A,0x38,0xAE,0x9F,0xEE,0x1F,0x17,0x0D,0x1C,0x82, + 0xEB,0x92,0xE5,0x87,0x1B,0x9E,0x3E,0xE2,0x32,0x7B,0xB5,0x9F,0xBC,0x52,0x1F,0x07, + 0xB1,0x77,0x16,0xA9,0xC2,0xB6,0x9F,0xC1,0xE4,0xCA,0x27,0x45,0x18,0xF7,0x07,0x7F, + 0x74,0x95,0x5E,0x8C,0x67,0x3D,0xEA,0x20,0x39,0x4A,0x4A,0x79,0xB6,0xEC,0xCE,0x98, + 0x3F,0x60,0x51,0x26,0xF3,0x37,0x0E,0x0C,0xFC,0x3E,0x14,0xBF,0xEA,0x75,0xA7,0x68, + 0x0F,0xA4,0x1C,0x57,0x04,0xF8,0xC1,0x11,0x6D,0xD0,0x1F,0x93,0x30,0x5C,0xB4,0x99, + 0x91,0x67,0x3C,0x72,0x95,0x63,0x7F,0x2D,0x66,0xE0,0x32,0x11,0xC4,0x76,0xF5,0xC0, + 0x36,0x23,0x20,0xBC,0xE4,0x4F,0xDA,0xE7,0xDC,0x10,0x62,0x49,0xC0,0xC7,0x91,0xFE, + 0x4C,0xCC,0x09,0x40,0xB9,0x33,0x0D,0xD5,0x90,0x4E,0xD9,0x83,0x54,0x2C,0x42,0x81, + 0x17,0xFA,0xDF,0x57,0x3A,0x15,0x76,0x05,0x1F,0x11,0x40,0xCE,0x85,0xEC,0xA2,0xA3, + 0xF6,0xAC,0xB6,0x67,0xA6,0x78,0xD0,0xA9,0xA7,0xF2,0x60,0xF4,0xFC,0xD1,0x78,0x9E, + 0x00,0x00,0xD9,0xE7,0xE7,0xE5,0xED,0xE4,0x10,0x8D,0x8E,0x5B,0xCC,0x8E,0xB6,0xD6, + 0x71,0xCF,0x54,0x16,0xD4,0x99,0xCD,0x6D,0x40,0x2A,0x8A, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Test CA */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Test CA */ +/* SHA256: 51a0f31fc01dec8732b6fd136a434d6c87cd62e038b4fbd640b0fd624d1fcf6d */ +unsigned char _datetest_root[994]={ + 0x30,0x82,0x03,0xDE,0x30,0x82,0x02,0xC6,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xAB,0x16,0xC1,0x56,0x85,0x86,0xE5,0xC8,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x44, + 0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x44,0x61,0x74,0x65,0x20,0x54,0x65,0x73, + 0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x36,0x31,0x30,0x31,0x32,0x31,0x38, + 0x31,0x35,0x34,0x39,0x5A,0x17,0x0D,0x32,0x36,0x31,0x30,0x31,0x30,0x31,0x38,0x31, + 0x35,0x34,0x39,0x5A,0x30,0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43, + 0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55, + 0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63, + 0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E, + 0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x44,0x65,0x6E,0x79, + 0x6C,0x69,0x73,0x74,0x20,0x44,0x61,0x74,0x65,0x20,0x54,0x65,0x73,0x74,0x20,0x43, + 0x41,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,0xF0,0x5A,0x62,0x0B,0xEA,0xD6,0xD6,0x78,0x94,0xEE,0x71,0xB5,0xF8,0x42, + 0xBB,0xF2,0x2F,0xC6,0xFB,0x53,0x7E,0xE4,0xF5,0xC9,0x8F,0x94,0xBC,0x02,0xB9,0x12, + 0x8E,0x5D,0xB4,0x12,0xE3,0x73,0xBD,0xD8,0x1A,0x3F,0x2D,0xBC,0x39,0x31,0x42,0x02, + 0x74,0xE7,0x93,0xB4,0x2B,0x6F,0xA9,0x42,0x8A,0xD4,0x0E,0xC9,0x96,0x90,0xE5,0xF6, + 0xAD,0xD7,0x7E,0x58,0xBA,0x6B,0xBD,0xBF,0xFC,0x8F,0x1E,0xD4,0xBE,0xD1,0x11,0x4B, + 0x7D,0x8A,0xD0,0x36,0xAD,0x2A,0x9A,0x37,0x5B,0xDF,0xCB,0x66,0x85,0x85,0x4F,0xD6, + 0x6F,0xEB,0xB3,0xC8,0xF7,0x6C,0x42,0x2E,0xE9,0xD6,0x84,0xD7,0x0F,0xD5,0x97,0xFD, + 0x4F,0x31,0x33,0x1B,0x5B,0x23,0x56,0x1B,0x7C,0x1E,0x11,0x51,0xE8,0x14,0x22,0x50, + 0x15,0x3D,0x01,0x1F,0x02,0x36,0x44,0x64,0x70,0xB3,0x7A,0xF7,0xF6,0xDA,0x14,0x9E, + 0x39,0xC3,0xD1,0x9E,0xED,0x70,0x2C,0x4E,0xA5,0xA5,0x1C,0xB7,0xEE,0xEF,0x4E,0x90, + 0x5D,0xF9,0x34,0xBB,0xA7,0xDF,0xD4,0xC5,0xEB,0x84,0xC4,0x3B,0x3D,0xCA,0x9A,0x9C, + 0xAD,0xB1,0x24,0xD4,0xD1,0x82,0xCC,0x1A,0xC4,0xEF,0xAE,0xB1,0xF0,0x12,0x28,0x37, + 0x40,0x45,0x83,0xBF,0x39,0xC7,0x90,0xB6,0x23,0x63,0xAD,0xC8,0xB9,0xF4,0x80,0x4B, + 0x91,0x91,0x64,0xDD,0x05,0x5E,0x0A,0x36,0xAB,0x7A,0x32,0xBA,0x05,0xBC,0x62,0x93, + 0xDE,0x5D,0xBA,0x2B,0x91,0xF2,0xD6,0x49,0x61,0x08,0x98,0xA2,0xD2,0x6E,0xF2,0x2D, + 0x4D,0x90,0x65,0x51,0x9C,0xC0,0x79,0x33,0x08,0xE1,0x7F,0xC0,0x09,0xCF,0x4D,0xB3, + 0x25,0x1F,0x02,0x03,0x01,0x00,0x01,0xA3,0x45,0x30,0x43,0x30,0x12,0x06,0x03,0x55, + 0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x02,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30, + 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x4D,0xA5,0xDB,0xEF,0x4F,0xCD, + 0x74,0xE6,0x2A,0xB1,0xDC,0x5C,0xBE,0x12,0x04,0x94,0xEC,0x4A,0x66,0xD3,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01, + 0x01,0x00,0x06,0x5E,0xFD,0x98,0x73,0xA7,0x69,0xE2,0xAE,0x1C,0x06,0x00,0xD1,0x7C, + 0x59,0x70,0xB9,0x85,0xAF,0xB8,0xC0,0xAB,0x3B,0x60,0x64,0x0B,0x1B,0x81,0xA7,0x7D, + 0x5A,0xC4,0xDA,0x94,0x2B,0xBC,0xA7,0xDA,0x24,0x4E,0x83,0x21,0x12,0xFA,0x93,0x3E, + 0x67,0x38,0x37,0xBD,0x2B,0xEB,0x19,0xA4,0x08,0x73,0xB1,0x27,0x84,0x67,0x10,0x48, + 0x50,0x94,0x4C,0x55,0x0D,0x23,0x9F,0x0A,0xB2,0x18,0x6F,0xC1,0xE0,0x13,0xC2,0x2D, + 0x29,0x52,0xBA,0x4F,0x01,0x2C,0xD6,0x9E,0x73,0x5B,0x74,0x8A,0x0D,0x8C,0x1E,0x15, + 0x70,0x7E,0x9B,0xE0,0xCC,0xB2,0x6E,0xFE,0x44,0xD4,0xD0,0x76,0x41,0x95,0xFE,0x11, + 0xAA,0x4E,0x07,0xC6,0xBA,0x4B,0x46,0x02,0x0E,0xFC,0x4A,0xB9,0x15,0x2D,0x80,0xB5, + 0x33,0xE3,0x4E,0x41,0x46,0x05,0xEB,0x0A,0x15,0x43,0xC6,0x6A,0xC5,0x2B,0x53,0x49, + 0x49,0x61,0x57,0x0D,0x8D,0x42,0x63,0xB2,0xA6,0xC5,0xA5,0x23,0x3B,0xAC,0x50,0xDC, + 0x05,0x41,0x53,0x74,0xC5,0x67,0xA1,0x69,0xA6,0x66,0x4D,0x0F,0xF8,0x94,0x54,0x4B, + 0xA5,0x31,0x81,0xE8,0x3A,0x5C,0x02,0x84,0x56,0xFF,0xBE,0x13,0x15,0x95,0xC9,0xAF, + 0x17,0x77,0xD0,0x38,0x38,0x12,0xF9,0xA8,0x93,0x77,0x2F,0xCD,0x40,0x60,0xBC,0xCF, + 0x35,0x1C,0xE4,0xBD,0x5E,0x8D,0x96,0x19,0xB7,0x50,0x7E,0xED,0x44,0x1C,0x8C,0x08, + 0x6B,0xEE,0xEE,0xC9,0x8C,0xD6,0xDC,0x61,0x2C,0xD2,0x35,0x5E,0xB7,0x4C,0x58,0xFC, + 0x5D,0x62,0xEA,0xED,0x68,0xE8,0x1F,0xB1,0x0A,0x39,0x5C,0x29,0xBC,0x42,0x09,0xBA, + 0x4F,0x35, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Testing Intermediate CA 1 */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Test CA */ +/* Not Before: Oct 15 00:00:00 2016 GMT */ +/* X509v3 Subject Key Identifier: E7:C3:06:5B:22:E0:EC:DA:8C:80:00:D9:0C:AC:0B:78:D4:68:C5:B7 */ +unsigned char _datetest_before_int[1050]={ + 0x30,0x82,0x04,0x16,0x30,0x82,0x02,0xFE,0xA0,0x03,0x02,0x01,0x02,0x02,0x11,0x00, + 0x9A,0x17,0xF8,0x6F,0x33,0x3D,0xAB,0x4C,0xD3,0xFB,0x3A,0x6D,0xCF,0x05,0x94,0xEC, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30, + 0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20, + 0x44,0x61,0x74,0x65,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, + 0x31,0x36,0x31,0x30,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31, + 0x37,0x31,0x30,0x31,0x32,0x31,0x38,0x32,0x38,0x31,0x38,0x5A,0x30,0x81,0x9C,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69, + 0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65, + 0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E, + 0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x30,0x30,0x2E,0x06,0x03,0x55, + 0x04,0x03,0x0C,0x27,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x44,0x61,0x74, + 0x65,0x20,0x54,0x65,0x73,0x74,0x69,0x6E,0x67,0x20,0x49,0x6E,0x74,0x65,0x72,0x6D, + 0x65,0x64,0x69,0x61,0x74,0x65,0x20,0x43,0x41,0x20,0x31,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,0xF0,0xCB,0x1D,0x6C, + 0x7D,0xC1,0x90,0xB7,0xD9,0xB5,0x66,0x61,0x5E,0x34,0x76,0x14,0xFA,0xF8,0xB4,0xE1, + 0x6D,0x67,0xB0,0x9E,0xB9,0x93,0xB0,0xBE,0x15,0xA4,0xAB,0x76,0x23,0x0D,0x5C,0xC0, + 0x4D,0xB6,0x9F,0xCC,0x9B,0x3A,0x7E,0x50,0x13,0xE6,0x46,0x39,0xB1,0xE9,0x5F,0xB3, + 0xD7,0x86,0xA4,0x23,0xA5,0x27,0xDC,0x20,0x6A,0x64,0xD8,0x0A,0xCD,0x5F,0xEE,0x40, + 0x16,0xCE,0x4D,0xB9,0xCF,0xA2,0x62,0xC8,0x01,0x70,0x7F,0x8D,0x42,0x46,0xB1,0xF2, + 0x80,0x57,0xD5,0x82,0x53,0xEF,0xF2,0x16,0xA4,0xD5,0x07,0xE2,0xA7,0x7A,0x5E,0xD5, + 0x5A,0x4F,0x58,0x88,0xF7,0xEB,0x1B,0x58,0x91,0x6D,0x4E,0xD8,0xCC,0x9F,0xA6,0x98, + 0x05,0xE6,0xFB,0xC2,0x55,0xCA,0xD9,0x7E,0xC8,0xAA,0xC2,0x92,0xC1,0x73,0xBB,0xEC, + 0x89,0x51,0x1C,0x6B,0x0C,0xE5,0x7D,0xF8,0x54,0xBE,0xF7,0x67,0x8C,0xEE,0xE4,0xBB, + 0xFF,0xB9,0x15,0x4F,0xD7,0x1B,0x76,0xF7,0x37,0xEF,0xB0,0xA0,0x2A,0x22,0x4D,0x4B, + 0x2A,0xDE,0x3D,0x37,0x28,0x4A,0x79,0xF6,0xC7,0xE3,0x51,0xEC,0xC4,0x2F,0xDA,0xC1, + 0xBA,0x1A,0xFF,0xDD,0x43,0x2A,0x44,0xD4,0x94,0xDC,0xEE,0xDB,0xC3,0xF2,0xB4,0x76, + 0x01,0xF7,0x69,0x48,0x11,0x67,0xAC,0x3C,0x1C,0xE0,0xEF,0x88,0x77,0x70,0x66,0x39, + 0x17,0xAA,0xD8,0x2C,0x67,0xE3,0xC3,0x2B,0xCD,0xC4,0xB9,0xC8,0xCD,0xA9,0xA4,0xC1, + 0x24,0xDF,0x8E,0x4D,0xE0,0x03,0x1E,0x40,0xAB,0xDD,0x10,0xE7,0xB5,0x93,0x1F,0xF2, + 0xC9,0xCC,0x91,0x3A,0x8D,0x52,0xC9,0x3D,0x7D,0x4D,0xA0,0xBB,0x02,0x03,0x01,0x00, + 0x01,0xA3,0x63,0x30,0x61,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,0x02,0x04,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0xE7,0xC3,0x06,0x5B,0x22,0xE0,0xEC,0xDA,0x8C,0x80,0x00,0xD9,0x0C,0xAC,0x0B, + 0x78,0xD4,0x68,0xC5,0xB7,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, + 0x80,0x14,0x4D,0xA5,0xDB,0xEF,0x4F,0xCD,0x74,0xE6,0x2A,0xB1,0xDC,0x5C,0xBE,0x12, + 0x04,0x94,0xEC,0x4A,0x66,0xD3,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, + 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x08,0xDC,0x9E,0xA4,0x60,0xDF, + 0x04,0x27,0xB5,0x01,0x63,0xDA,0xE3,0x6C,0x58,0x1D,0xB8,0xE8,0x17,0x06,0x4F,0x86, + 0xC8,0x97,0x65,0xF5,0x6D,0x39,0x51,0x0F,0xD4,0xF9,0xAD,0xCF,0x8C,0x08,0x7C,0xAC, + 0x26,0xD1,0x43,0xB2,0x79,0x7E,0x13,0xCD,0xF2,0x9D,0x30,0xC4,0x63,0xF2,0x5E,0x72, + 0x1A,0x0F,0x41,0x47,0x69,0x98,0x00,0xF0,0x4D,0x93,0x44,0x8A,0x26,0xDE,0x24,0xC0, + 0x66,0xA3,0xB0,0x20,0xAD,0x33,0xEB,0xF2,0x0A,0xDD,0x65,0xF4,0x9D,0x29,0x10,0x88, + 0x5B,0xFF,0x1C,0x76,0x71,0x42,0xE9,0x6F,0xBD,0xAE,0xA6,0xBB,0x4B,0xFF,0x30,0xA0, + 0x6E,0x47,0x85,0x12,0x6E,0x81,0xFC,0xB0,0x51,0x5F,0xB4,0xE9,0xCC,0x83,0x0E,0xC5, + 0xEC,0x41,0x6F,0x28,0x28,0xF0,0x51,0x4A,0x42,0x7C,0xCF,0xAE,0x8B,0xD8,0x09,0x44, + 0x32,0x27,0x07,0x57,0x86,0x1B,0xB6,0xF3,0xAF,0xCA,0x1C,0x2F,0xDD,0x1C,0x58,0x17, + 0xF4,0x13,0xA3,0x4F,0x72,0x60,0x71,0x39,0xEE,0x8E,0xF2,0x9D,0x40,0xCA,0x39,0x63, + 0xFD,0x1F,0x8C,0x2C,0xFD,0x62,0xA8,0x0E,0xC3,0x04,0x62,0x9D,0x79,0x11,0xD2,0x5C, + 0x09,0xE5,0x27,0x50,0x3A,0x62,0x93,0xC5,0xA5,0x60,0xFB,0xE5,0x7F,0xB6,0x46,0xD5, + 0xA8,0xF8,0x38,0x05,0x94,0xCD,0x47,0x5B,0xA0,0xA4,0x67,0xB8,0x81,0x99,0xA2,0x92, + 0xEB,0x13,0x37,0x56,0xD6,0xAC,0x80,0xA6,0x7F,0x1A,0xBB,0x14,0x68,0x72,0x04,0xBD, + 0xD7,0xEE,0x8F,0x48,0x56,0xC7,0xDF,0x86,0xBB,0x76,0xE4,0xE3,0xE3,0x46,0xF3,0x8B, + 0x51,0x22,0xD6,0xD2,0xB9,0xAA,0x15,0xA2,0xB4,0xAC, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Testing Intermediate CA 1 */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Test CA */ +/* Not Before: Dec 1 00:01:00 2016 GMT */ +/* X509v3 Subject Key Identifier: E7:C3:06:5B:22:E0:EC:DA:8C:80:00:D9:0C:AC:0B:78:D4:68:C5:B7 */ +unsigned char _datetest_after_int[1050]={ + 0x30,0x82,0x04,0x16,0x30,0x82,0x02,0xFE,0xA0,0x03,0x02,0x01,0x02,0x02,0x11,0x00, + 0x9A,0x17,0xF8,0x6F,0x33,0x3D,0xAB,0x4C,0xD3,0xFB,0x3A,0x6D,0xCF,0x05,0x94,0xEE, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30, + 0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20, + 0x44,0x61,0x74,0x65,0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D, + 0x31,0x36,0x31,0x32,0x30,0x31,0x30,0x30,0x30,0x31,0x30,0x30,0x5A,0x17,0x0D,0x31, + 0x37,0x31,0x30,0x31,0x32,0x32,0x30,0x33,0x34,0x34,0x38,0x5A,0x30,0x81,0x9C,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69, + 0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65, + 0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E, + 0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x30,0x30,0x2E,0x06,0x03,0x55, + 0x04,0x03,0x0C,0x27,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x44,0x61,0x74, + 0x65,0x20,0x54,0x65,0x73,0x74,0x69,0x6E,0x67,0x20,0x49,0x6E,0x74,0x65,0x72,0x6D, + 0x65,0x64,0x69,0x61,0x74,0x65,0x20,0x43,0x41,0x20,0x31,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,0xF0,0xCB,0x1D,0x6C, + 0x7D,0xC1,0x90,0xB7,0xD9,0xB5,0x66,0x61,0x5E,0x34,0x76,0x14,0xFA,0xF8,0xB4,0xE1, + 0x6D,0x67,0xB0,0x9E,0xB9,0x93,0xB0,0xBE,0x15,0xA4,0xAB,0x76,0x23,0x0D,0x5C,0xC0, + 0x4D,0xB6,0x9F,0xCC,0x9B,0x3A,0x7E,0x50,0x13,0xE6,0x46,0x39,0xB1,0xE9,0x5F,0xB3, + 0xD7,0x86,0xA4,0x23,0xA5,0x27,0xDC,0x20,0x6A,0x64,0xD8,0x0A,0xCD,0x5F,0xEE,0x40, + 0x16,0xCE,0x4D,0xB9,0xCF,0xA2,0x62,0xC8,0x01,0x70,0x7F,0x8D,0x42,0x46,0xB1,0xF2, + 0x80,0x57,0xD5,0x82,0x53,0xEF,0xF2,0x16,0xA4,0xD5,0x07,0xE2,0xA7,0x7A,0x5E,0xD5, + 0x5A,0x4F,0x58,0x88,0xF7,0xEB,0x1B,0x58,0x91,0x6D,0x4E,0xD8,0xCC,0x9F,0xA6,0x98, + 0x05,0xE6,0xFB,0xC2,0x55,0xCA,0xD9,0x7E,0xC8,0xAA,0xC2,0x92,0xC1,0x73,0xBB,0xEC, + 0x89,0x51,0x1C,0x6B,0x0C,0xE5,0x7D,0xF8,0x54,0xBE,0xF7,0x67,0x8C,0xEE,0xE4,0xBB, + 0xFF,0xB9,0x15,0x4F,0xD7,0x1B,0x76,0xF7,0x37,0xEF,0xB0,0xA0,0x2A,0x22,0x4D,0x4B, + 0x2A,0xDE,0x3D,0x37,0x28,0x4A,0x79,0xF6,0xC7,0xE3,0x51,0xEC,0xC4,0x2F,0xDA,0xC1, + 0xBA,0x1A,0xFF,0xDD,0x43,0x2A,0x44,0xD4,0x94,0xDC,0xEE,0xDB,0xC3,0xF2,0xB4,0x76, + 0x01,0xF7,0x69,0x48,0x11,0x67,0xAC,0x3C,0x1C,0xE0,0xEF,0x88,0x77,0x70,0x66,0x39, + 0x17,0xAA,0xD8,0x2C,0x67,0xE3,0xC3,0x2B,0xCD,0xC4,0xB9,0xC8,0xCD,0xA9,0xA4,0xC1, + 0x24,0xDF,0x8E,0x4D,0xE0,0x03,0x1E,0x40,0xAB,0xDD,0x10,0xE7,0xB5,0x93,0x1F,0xF2, + 0xC9,0xCC,0x91,0x3A,0x8D,0x52,0xC9,0x3D,0x7D,0x4D,0xA0,0xBB,0x02,0x03,0x01,0x00, + 0x01,0xA3,0x63,0x30,0x61,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,0x02,0x04,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0xE7,0xC3,0x06,0x5B,0x22,0xE0,0xEC,0xDA,0x8C,0x80,0x00,0xD9,0x0C,0xAC,0x0B, + 0x78,0xD4,0x68,0xC5,0xB7,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, + 0x80,0x14,0x4D,0xA5,0xDB,0xEF,0x4F,0xCD,0x74,0xE6,0x2A,0xB1,0xDC,0x5C,0xBE,0x12, + 0x04,0x94,0xEC,0x4A,0x66,0xD3,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, + 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x82,0xDE,0x0F,0x06,0xD4,0xC3, + 0x55,0xD1,0xC9,0x9A,0xDF,0x87,0x69,0xA8,0xA2,0x11,0x12,0x73,0xF4,0x8B,0x98,0x02, + 0xA6,0xE0,0xB1,0x11,0x0E,0xEB,0xC3,0x3B,0x1D,0x8B,0xBF,0x45,0x4B,0x24,0xEA,0x7A, + 0xEF,0x70,0x2A,0xAB,0xE4,0xB6,0xA1,0xB1,0x66,0x5E,0x12,0x09,0x49,0x93,0x6A,0x4B, + 0x3A,0x10,0xD1,0xEE,0xA0,0x6D,0xC7,0x19,0x5B,0xE0,0x75,0x2F,0x3F,0xFB,0x66,0x1F, + 0x91,0x86,0x30,0x5A,0xC6,0x77,0xED,0x06,0x85,0xF8,0x65,0x96,0x48,0x30,0x32,0x25, + 0x93,0x59,0x51,0x2D,0x7D,0x20,0x12,0x9A,0x87,0x07,0x40,0x8C,0x8F,0x81,0xD8,0xF8, + 0xF2,0xF2,0x3E,0xF3,0xF3,0xC8,0x7D,0x7A,0xAA,0xE3,0xF7,0xCD,0x9D,0x69,0x6F,0x85, + 0x15,0xCD,0x18,0xC0,0xBB,0x6E,0x27,0xAD,0xD3,0x9A,0xD2,0x6A,0x42,0x02,0x0C,0xDB, + 0xF5,0x0C,0x85,0xC3,0xB3,0xDB,0x4C,0x28,0x61,0x82,0xC8,0x88,0x44,0x95,0x08,0xBE, + 0x24,0x07,0xEA,0xD2,0x4C,0x0A,0xA9,0x2E,0x47,0x28,0xDE,0xF3,0x24,0xDC,0x22,0x57, + 0xA4,0x5D,0x04,0x22,0x28,0xC6,0x4F,0xBD,0x2E,0xB7,0xD4,0x2C,0x06,0x0E,0x22,0xF5, + 0x05,0xA6,0x76,0x8E,0x77,0xFD,0x1C,0xA1,0x4E,0x10,0x1D,0x82,0x74,0x73,0x06,0x47, + 0xC2,0xD2,0xF7,0x59,0xD5,0xBF,0x64,0x77,0xBB,0x47,0x15,0x23,0x4B,0x78,0x7C,0x51, + 0x34,0xF0,0xF7,0x04,0xE1,0x5C,0xED,0x28,0x55,0x7B,0xC1,0x07,0x52,0x2A,0x86,0x48, + 0xEB,0x8C,0xC2,0x55,0x56,0xDA,0x98,0xF3,0x5C,0x8F,0x21,0x70,0xDD,0xFB,0xA4,0x61, + 0x2F,0x57,0xE7,0x0B,0x70,0x2F,0x00,0x72,0x79,0x3C, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Testing Before Leaf */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Testing Intermediate CA 1 */ +/* Not Before: Oct 15 00:00:00 2016 GMT */ +unsigned char _datetest_before_leaf[1109]={ + 0x30,0x82,0x04,0x51,0x30,0x82,0x03,0x39,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x4C, + 0x3E,0x59,0xB4,0xB4,0x96,0x67,0xC6,0x13,0xB0,0xB4,0x67,0x03,0xB9,0x27,0xAE,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81, + 0x9C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x30,0x30,0x2E,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x27,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x44, + 0x61,0x74,0x65,0x20,0x54,0x65,0x73,0x74,0x69,0x6E,0x67,0x20,0x49,0x6E,0x74,0x65, + 0x72,0x6D,0x65,0x64,0x69,0x61,0x74,0x65,0x20,0x43,0x41,0x20,0x31,0x30,0x1E,0x17, + 0x0D,0x31,0x36,0x31,0x30,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D, + 0x31,0x37,0x31,0x30,0x31,0x32,0x31,0x38,0x33,0x38,0x30,0x38,0x5A,0x30,0x81,0x91, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E, + 0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70, + 0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45, + 0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x25,0x30,0x23,0x06,0x03, + 0x55,0x04,0x03,0x0C,0x1C,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x54,0x65, + 0x73,0x74,0x69,0x6E,0x67,0x20,0x42,0x65,0x66,0x6F,0x72,0x65,0x20,0x4C,0x65,0x61, + 0x66,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,0xB5,0x10,0x30,0xBE,0xE6,0x80,0x11,0x8B,0x5B,0xD8,0xDD,0xFE,0x66,0x19, + 0x8A,0xBC,0x01,0x29,0xA8,0x85,0x25,0xDB,0xF0,0x33,0xA9,0x5F,0x34,0xFC,0x7A,0xB7, + 0x19,0xD1,0x4A,0x7C,0xC9,0xBE,0x9C,0x8E,0xD3,0xB6,0xAA,0x48,0x97,0x53,0xBF,0x20, + 0x1D,0x81,0xAC,0x87,0xCA,0x60,0xC0,0xD5,0xC5,0x9E,0x86,0x48,0xA4,0xBD,0xB2,0x9E, + 0x88,0x92,0x2C,0x6C,0x8D,0xAC,0xC5,0x65,0x6C,0x5C,0x38,0x4E,0x1A,0xDC,0x00,0x70, + 0xCA,0x68,0x33,0x38,0x10,0xE0,0x5F,0xAC,0x8C,0x47,0x73,0xA5,0xC6,0xC7,0x2C,0x4C, + 0xB8,0xBB,0xE7,0x6C,0x42,0x6C,0x11,0x8C,0x2C,0x5E,0xBC,0x4C,0x87,0x1E,0xDE,0x2C, + 0xDE,0x40,0x7E,0xB9,0x32,0x7D,0x73,0x5B,0xF8,0x59,0x50,0x71,0x1E,0x43,0x06,0x89, + 0x09,0xC3,0x3B,0xC2,0xEB,0xD5,0x26,0x50,0x0D,0x98,0x09,0xE7,0x50,0x39,0x87,0x3C, + 0x06,0x5E,0xFF,0x4E,0xD4,0x9C,0x53,0xF9,0xBD,0x3E,0x5E,0x73,0x8B,0xBC,0xE5,0x3E, + 0xD2,0x96,0x4D,0xE5,0x1E,0x24,0x3D,0x34,0xA8,0x7C,0xB9,0x55,0xC0,0xA6,0x61,0x69, + 0xC2,0xCF,0x1F,0x67,0x45,0xC6,0x3A,0x56,0x1F,0xD2,0x93,0x32,0x3F,0x1A,0x60,0x6B, + 0x5B,0xCD,0x1A,0x6D,0x54,0x8C,0xF4,0x3F,0x4D,0x2B,0xA8,0xE7,0x2D,0xF8,0x12,0x39, + 0xCC,0xE6,0x41,0x35,0xD0,0x27,0xE5,0x20,0x15,0xFD,0xF0,0xC4,0xDF,0x7C,0x13,0x65, + 0x1B,0xD8,0x54,0x9D,0x68,0xDC,0xAA,0x51,0xD3,0x6C,0x4F,0x6C,0x16,0x83,0xC6,0x3F, + 0xF9,0x95,0xFF,0xE6,0x4B,0x23,0x4B,0xE1,0x5D,0x02,0xC5,0x14,0x03,0x3A,0x0A,0xFB, + 0xAB,0x1B,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x97,0x30,0x81,0x94,0x30,0x0C,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55, + 0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x13,0x06,0x03,0x55, + 0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x11,0x04,0x18,0x30,0x16,0x82,0x14,0x74,0x65,0x73, + 0x74,0x73,0x65,0x72,0x76,0x65,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F, + 0x6D,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x52,0xBB,0x5E,0x78, + 0x5F,0x54,0xE6,0xD9,0x56,0x8B,0xE9,0x31,0xE7,0x9A,0x68,0xF2,0x96,0xB5,0x34,0xA4, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xE7,0xC3,0x06, + 0x5B,0x22,0xE0,0xEC,0xDA,0x8C,0x80,0x00,0xD9,0x0C,0xAC,0x0B,0x78,0xD4,0x68,0xC5, + 0xB7,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x2B,0x8A,0xFF,0xC4,0x3F,0x5C,0x0C,0x98,0x78,0x65,0xC2, + 0x5C,0x41,0x26,0xA1,0x1F,0x08,0xAB,0x6C,0xB2,0xF9,0xF3,0x6C,0x71,0xDA,0xD6,0xCB, + 0x40,0x2C,0xE8,0xA2,0x06,0x66,0xF0,0xD0,0x93,0x7B,0x0A,0x29,0xBB,0x9C,0x12,0xF5, + 0xE0,0xFF,0xC5,0x58,0xB2,0x95,0x25,0x29,0x1E,0x8B,0xFE,0xCC,0x8F,0xC7,0x5E,0x76, + 0x58,0x5E,0x27,0x29,0x47,0xC4,0x1B,0xC1,0xEB,0x22,0x2E,0xDB,0xE2,0x7F,0x38,0x09, + 0x14,0xAC,0x94,0xF6,0xFB,0x16,0x21,0x08,0x11,0x20,0x2B,0x2A,0xB5,0x22,0xD3,0x31, + 0x43,0xB0,0x4E,0xE8,0x33,0x3B,0xDC,0x10,0x56,0xDE,0x55,0xC8,0x9A,0x31,0x6C,0x52, + 0x6D,0xE9,0x79,0x70,0xEB,0xCD,0xD8,0x27,0x32,0xF6,0x30,0x7D,0x48,0xAF,0xB5,0xD8, + 0xBD,0xF3,0x68,0xEC,0xB0,0x7F,0x5A,0x52,0x9A,0x5A,0xF1,0x8E,0xCD,0x94,0x37,0x16, + 0xA2,0x75,0x3C,0x0E,0xDA,0xDE,0x12,0x33,0xAE,0x04,0xAB,0x27,0xDE,0xD1,0x60,0x13, + 0x0C,0x67,0x07,0x2A,0x7C,0xF2,0x46,0x74,0x3C,0x79,0x9B,0x6D,0xF3,0x2D,0x2E,0x69, + 0xDD,0xF4,0xEA,0xEC,0xD2,0xDD,0x85,0x79,0x77,0xCD,0x20,0xA9,0x19,0x3F,0x99,0xBB, + 0xA4,0x8A,0x78,0xBE,0x0E,0xEC,0xB9,0x91,0xAD,0xB6,0xFC,0xFB,0xCF,0xCF,0x71,0xBF, + 0x3C,0x13,0x2F,0xEB,0xD8,0xC8,0x22,0xC3,0x07,0xBB,0xCB,0x95,0x39,0xD4,0x61,0xDF, + 0x4F,0x87,0x41,0xCA,0xDD,0xD8,0x54,0xD7,0xDE,0x9C,0x13,0xF6,0x69,0x90,0xEE,0xE8, + 0xF8,0x0B,0x83,0x38,0x31,0x4C,0x67,0x96,0xF6,0x4A,0x77,0x00,0x41,0x11,0x91,0x77, + 0xC2,0x05,0x60,0x30,0x8C, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Testing After Leaf */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Denylist Date Testing Intermediate CA 1 */ +/* Not Before: Dec 1 00:01:00 2016 GMT */ +unsigned char _datetest_after_leaf[1108]={ + 0x30,0x82,0x04,0x50,0x30,0x82,0x03,0x38,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x4C, + 0x3E,0x59,0xB4,0xB4,0x96,0x67,0xC6,0x13,0xB0,0xB4,0x67,0x03,0xB9,0x27,0xAF,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81, + 0x9C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x30,0x30,0x2E,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x27,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x44, + 0x61,0x74,0x65,0x20,0x54,0x65,0x73,0x74,0x69,0x6E,0x67,0x20,0x49,0x6E,0x74,0x65, + 0x72,0x6D,0x65,0x64,0x69,0x61,0x74,0x65,0x20,0x43,0x41,0x20,0x31,0x30,0x1E,0x17, + 0x0D,0x31,0x36,0x31,0x32,0x30,0x31,0x30,0x30,0x30,0x31,0x30,0x30,0x5A,0x17,0x0D, + 0x31,0x37,0x31,0x30,0x31,0x32,0x31,0x38,0x33,0x38,0x34,0x37,0x5A,0x30,0x81,0x90, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30, + 0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E, + 0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70, + 0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45, + 0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x24,0x30,0x22,0x06,0x03, + 0x55,0x04,0x03,0x0C,0x1B,0x44,0x65,0x6E,0x79,0x6C,0x69,0x73,0x74,0x20,0x54,0x65, + 0x73,0x74,0x69,0x6E,0x67,0x20,0x41,0x66,0x74,0x65,0x72,0x20,0x4C,0x65,0x61,0x66, + 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,0xE9,0xD1,0x18,0x04,0x41,0x52,0x27,0x4F,0x91,0x31,0xBD,0xF2,0x9F,0x11,0x8F, + 0x50,0xF6,0x5C,0xD2,0x6F,0x8B,0x7F,0xDA,0x20,0x50,0x92,0x7F,0x7D,0x61,0x6E,0x52, + 0x74,0xE1,0x66,0x14,0x70,0xAD,0x9E,0x84,0xF2,0x71,0x23,0xC7,0xC6,0xFD,0x58,0xE3, + 0x5B,0x37,0xFF,0x8F,0x72,0xC9,0x4D,0x71,0x20,0xA0,0x7F,0x23,0xD5,0xF5,0xC1,0x37, + 0x01,0x57,0x1C,0x8F,0x8E,0xD1,0x59,0xED,0x26,0x41,0xED,0xE7,0x47,0x86,0xCE,0xBB, + 0x27,0x45,0xAC,0x08,0x51,0xAB,0x3E,0xD8,0x92,0x98,0x6D,0x88,0x24,0xD1,0x56,0x8D, + 0xED,0x81,0xCE,0xBA,0x8F,0x9E,0x8E,0x9E,0x81,0x29,0xC5,0x9C,0x32,0x75,0xC6,0x5D, + 0xDE,0x1E,0x61,0x38,0xD7,0x89,0x41,0x17,0xAC,0xDC,0xB9,0x98,0xC4,0x7E,0xA7,0xC0, + 0x3B,0xB9,0xF2,0xA0,0xB0,0x88,0x3E,0x84,0xBC,0x28,0x1D,0x5B,0x35,0x92,0xCC,0xCB, + 0x9B,0x4E,0xD3,0xF2,0x2F,0x9B,0x77,0xC5,0xB1,0x08,0x18,0x86,0xF1,0x1E,0x47,0xDD, + 0x9A,0x94,0x5E,0xEF,0xE7,0x32,0xAD,0xD0,0x3C,0x65,0x81,0x5D,0xD7,0x94,0x56,0xCA, + 0x95,0xEA,0x4C,0x87,0xE1,0x48,0xC0,0xB9,0xA7,0x23,0xED,0x0F,0xFC,0x56,0x38,0x10, + 0x4E,0x7F,0xB3,0x73,0x0B,0x3A,0xCB,0xB9,0x89,0x15,0xA9,0xBD,0x81,0xB9,0x9F,0xD9, + 0x53,0x2E,0x73,0x95,0x2D,0xA9,0x81,0x85,0xA7,0xC2,0x0B,0xA2,0xDE,0x6F,0x41,0x72, + 0x05,0x50,0xE5,0xB4,0x10,0xD4,0xE7,0xF2,0x76,0x48,0xCC,0x2A,0x2C,0x44,0x74,0xF1, + 0x5E,0x0A,0xB5,0x02,0x55,0x25,0x54,0x29,0x92,0x6F,0x0A,0x78,0x33,0xBB,0x8C,0x01, + 0x1F,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x97,0x30,0x81,0x94,0x30,0x0C,0x06,0x03, + 0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D, + 0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x13,0x06,0x03,0x55,0x1D, + 0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30, + 0x1F,0x06,0x03,0x55,0x1D,0x11,0x04,0x18,0x30,0x16,0x82,0x14,0x74,0x65,0x73,0x74, + 0x73,0x65,0x72,0x76,0x65,0x72,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x1F,0xBA,0x32,0x4F,0x63, + 0xBA,0x31,0x1E,0xA3,0x91,0xFC,0x59,0x84,0x62,0xA9,0x52,0x22,0xC6,0xF1,0xAB,0x30, + 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xE7,0xC3,0x06,0x5B, + 0x22,0xE0,0xEC,0xDA,0x8C,0x80,0x00,0xD9,0x0C,0xAC,0x0B,0x78,0xD4,0x68,0xC5,0xB7, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x86,0xFF,0xC5,0xB6,0xB6,0x57,0x9A,0x6B,0xA3,0x83,0xFA,0x97, + 0xA3,0xCB,0x4F,0xA3,0x44,0xB9,0x0A,0x89,0xC7,0x09,0xE3,0x9F,0x61,0x45,0x80,0x11, + 0x1C,0x8F,0x81,0x12,0x96,0x55,0x91,0xD7,0x93,0x70,0x7A,0x24,0x1D,0xA5,0xFE,0x8C, + 0xD9,0x0C,0x74,0x2A,0xB8,0x0C,0xF9,0xBC,0xA7,0xFE,0xC8,0x03,0x1F,0xC8,0x55,0xEF, + 0xC2,0x54,0x81,0x4D,0xA1,0x88,0x1F,0x88,0x74,0x12,0xE3,0xA2,0x58,0x9D,0x66,0x89, + 0x8F,0xBB,0x0F,0xB7,0xE5,0x9F,0xF0,0x81,0x0E,0xFC,0x0E,0x3D,0x33,0xB1,0x9D,0xDD, + 0x82,0x3E,0xF8,0xF2,0x10,0x50,0x1B,0xEB,0x19,0x44,0x5F,0x74,0x2E,0x98,0x68,0x3C, + 0xF7,0x08,0x2F,0x8B,0xB7,0x67,0x14,0xC5,0xC1,0x33,0xBB,0xA8,0xDF,0x47,0xFE,0x3D, + 0x24,0x36,0xD3,0xA7,0x8F,0xAC,0x9E,0x2E,0x49,0xFC,0xB1,0x68,0x93,0x9E,0x10,0x99, + 0x35,0x7F,0xC6,0xBF,0xFD,0x90,0x32,0xCB,0x73,0x57,0x65,0x11,0xDF,0xEB,0x64,0x23, + 0xDD,0x67,0xCC,0x8A,0x00,0xDA,0x0F,0x09,0x66,0xEE,0x72,0xCC,0x73,0x93,0x92,0xC5, + 0x53,0xF4,0x60,0xF1,0xAB,0x3E,0x8B,0x4B,0xEF,0x2C,0xCF,0xDA,0x70,0x4D,0x50,0xB0, + 0x10,0x87,0x97,0x87,0x26,0xA2,0x39,0x16,0xD2,0xEA,0xDC,0x42,0xE7,0xF0,0xED,0x53, + 0xD5,0xFF,0x61,0x1E,0x93,0x22,0xD7,0x59,0xDA,0xAC,0xCD,0x81,0x9E,0xD8,0x72,0x13, + 0x52,0x6B,0xEE,0x86,0xA1,0x37,0x6C,0xBA,0xA2,0x60,0xB2,0xCC,0xA1,0x51,0xA8,0x57, + 0x80,0xCA,0x9C,0xAF,0x03,0xAB,0xBD,0xC3,0x13,0xAA,0x46,0xBD,0x3B,0x99,0xE6,0x6F, + 0x7B,0x93,0x90,0xB6, +}; + +#endif /* _TRUSTTESTS_ALLOWLIST_BLOCKLIST_TESTS_ */ diff --git a/tests/TrustTests/EvaluationTests/CAIssuerTests.m b/tests/TrustTests/EvaluationTests/CAIssuerTests.m new file mode 100644 index 00000000..da4d364f --- /dev/null +++ b/tests/TrustTests/EvaluationTests/CAIssuerTests.m @@ -0,0 +1,176 @@ +/* +* Copyright (c) 2006-2019 Apple Inc. All Rights Reserved. +*/ + +#include +#import +#include +#include +#include +#include +#include +#include +#include + +#import "../TestMacroConversions.h" +#import "../TrustEvaluationTestHelpers.h" +#import "TrustEvaluationTestCase.h" + +#import "CAIssuerTests_data.h" + +@interface CAIssuerTests: TrustEvaluationTestCase +@end + +@implementation CAIssuerTests + +#if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE +- (void) test_aia +{ + if (!ping_host("crt.comodoca.com")) { + XCTAssert(false, "Unable to contact required network resource"); + return; + } + + SecCertificateRef ovh = NULL, comodo_ev = NULL, comodo_aia = NULL; + CFMutableArrayRef certs = NULL, policies = NULL; + SecPolicyRef sslPolicy = NULL, revPolicy = NULL; + CFDateRef verifyDate = NULL; + SecTrustRef trust = NULL; + SecTrustResultType trustResult = kSecTrustResultInvalid; + + /* Initialize common variables */ + isnt(ovh = SecCertificateCreateWithBytes(NULL, ovh_certificate, + sizeof(ovh_certificate)), NULL, "create ovh cert"); + isnt(comodo_ev = SecCertificateCreateWithBytes(NULL, comodo_ev_certificate, + sizeof(comodo_ev_certificate)), NULL, "create comodo_ev cert"); + isnt(comodo_aia = SecCertificateCreateWithBytes(NULL, + comodo_aia_certificate, sizeof(comodo_aia_certificate)), NULL, + "create comodo_aia cert"); + certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + policies = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + sslPolicy = SecPolicyCreateSSL(false, NULL); // For now, use SSL client policy to avoid SHA-1 deprecation + revPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); + CFArrayAppendValue(policies, sslPolicy); + CFArrayAppendValue(policies, revPolicy); + /* May 9th 2018. */ + verifyDate = CFDateCreate(NULL, 547600500); + + /* First run with no intermediate and disallow network fetching. + * Evaluation should fail because it couldn't get the intermediate. */ + CFArrayAppendValue(certs, ovh); + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), + "create trust"); + ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); + ok_status(SecTrustSetNetworkFetchAllowed(trust, false), "set no network"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, + "trust is kSecTrustResultRecoverableTrustFailure"); + + /* Now allow networking. Evaluation should succeed after fetching + * the intermediate. */ + ok_status(SecTrustSetNetworkFetchAllowed(trust, true), "set allow network"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultUnspecified, + "trust is kSecTrustResultUnspecified"); + CFReleaseNull(trust); + + /* Common variable cleanup. */ + CFReleaseSafe(sslPolicy); + CFReleaseSafe(revPolicy); + CFReleaseSafe(certs); + CFReleaseSafe(policies); + CFReleaseSafe(comodo_aia); + CFReleaseSafe(comodo_ev); + CFReleaseSafe(ovh); + CFReleaseSafe(verifyDate); +} + +- (void) test_aia_https { + SecCertificateRef leaf = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFArrayRef certs = NULL; + CFDateRef verifyDate = NULL; + CFErrorRef error = NULL; + + leaf = SecCertificateCreateWithBytes(NULL, _caissuer_https, sizeof(_caissuer_https)); + const void *v_certs[] = { leaf }; + + certs = CFArrayCreate(NULL, v_certs, 1, &kCFTypeArrayCallBacks); + policy = SecPolicyCreateSSL(true, CFSTR("example.com")); + require_noerr_action(SecTrustCreateWithCertificates(certs, policy, &trust), errOut, fail("failed to create trust object")); + + verifyDate = CFDateCreate(NULL, 546700000.0); // April 29, 2018 at 6:06:40 AM PDT + require_noerr_action(SecTrustSetVerifyDate(trust, verifyDate), errOut, fail("failed to set verify date")); + + /* Evaluate trust. This cert does not chain to anything trusted and we can't fetch an + * intermediate because the URI is https. */ + is(SecTrustEvaluateWithError(trust, &error), false, "leaf with missing intermediate and https CAIssuer URI succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecCreateChainFailed, "got wrong error code for revoked cert, got %ld, expected %d", + (long)CFErrorGetCode(error), errSecCreateChainFailed); + } else { + fail("expected trust evaluation to fail and it did not."); + } + +errOut: + CFReleaseNull(leaf); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(certs); + CFReleaseNull(verifyDate); + CFReleaseNull(error); +} +#else /* TARGET_OS_WATCH || TARGET_OS_BRIDGE */ +- (void) testNoNetworking +{ + SecCertificateRef ovh = NULL, comodo_ev = NULL, comodo_aia = NULL; + CFMutableArrayRef certs = NULL, policies = NULL; + SecPolicyRef sslPolicy = NULL, revPolicy = NULL; + CFDateRef verifyDate = NULL; + SecTrustRef trust = NULL; + SecTrustResultType trustResult = kSecTrustResultInvalid; + + /* Initialize common variables */ + isnt(ovh = SecCertificateCreateWithBytes(NULL, ovh_certificate, + sizeof(ovh_certificate)), NULL, "create ovh cert"); + isnt(comodo_ev = SecCertificateCreateWithBytes(NULL, comodo_ev_certificate, + sizeof(comodo_ev_certificate)), NULL, "create comodo_ev cert"); + isnt(comodo_aia = SecCertificateCreateWithBytes(NULL, + comodo_aia_certificate, sizeof(comodo_aia_certificate)), NULL, + "create comodo_aia cert"); + certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + policies = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + sslPolicy = SecPolicyCreateSSL(false, NULL); // For now, use SSL client policy to avoid SHA-1 deprecation + revPolicy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); + CFArrayAppendValue(policies, sslPolicy); + CFArrayAppendValue(policies, revPolicy); + /* May 9th 2018. */ + verifyDate = CFDateCreate(NULL, 547600500); + + /* Evaluation should fail because it couldn't get the intermediate. */ + CFArrayAppendValue(certs, ovh); + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), + "create trust"); + ok_status(SecTrustSetVerifyDate(trust, verifyDate), "set date"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, + "trust is kSecTrustResultRecoverableTrustFailure"); + + /* Common variable cleanup. */ + CFReleaseSafe(sslPolicy); + CFReleaseSafe(revPolicy); + CFReleaseSafe(certs); + CFReleaseSafe(policies); + CFReleaseSafe(comodo_aia); + CFReleaseSafe(comodo_ev); + CFReleaseSafe(ovh); + CFReleaseSafe(verifyDate); +} +#endif + +@end diff --git a/tests/TrustTests/EvaluationTests/CAIssuerTests_data.h b/tests/TrustTests/EvaluationTests/CAIssuerTests_data.h new file mode 100644 index 00000000..5ccd431a --- /dev/null +++ b/tests/TrustTests/EvaluationTests/CAIssuerTests_data.h @@ -0,0 +1,413 @@ +/* +* Copyright (c) 2006-2019 Apple Inc. All Rights Reserved. +*/ + +#ifndef _TRUSTTESTS_CA_ISSUER_TESTS_H_ +#define _TRUSTTESTS_CA_ISSUER_TESTS_H_ + +/* subject:/serialNumber=424761419/jurisdictionC=FR/businessCategory=Private Organization/C=FR/postalCode=59100/ST=Nord/L=Roubaix/street=2 rue Kellermann/O=OVH SAS/OU=IT/OU=COMODO EV SSL/CN=ovh.com */ +/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ +static unsigned char ovh_certificate[1884]={ + 0x30,0x82,0x07,0x58,0x30,0x82,0x06,0x40,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x40, + 0x46,0x47,0xDC,0xC2,0x4B,0x04,0x42,0xD4,0x89,0x8D,0x08,0x4D,0x4B,0xC2,0x01,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81, + 0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, + 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, + 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, + 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, + 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, + 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55, + 0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45, + 0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69, + 0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72, + 0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x37,0x30,0x34,0x32,0x38,0x30,0x30,0x30, + 0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x39,0x30,0x34,0x32,0x38,0x32,0x33,0x35,0x39, + 0x35,0x39,0x5A,0x30,0x81,0xEA,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x05,0x13, + 0x09,0x34,0x32,0x34,0x37,0x36,0x31,0x34,0x31,0x39,0x31,0x13,0x30,0x11,0x06,0x0B, + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,0x13,0x02,0x46,0x52,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0F,0x13,0x14,0x50,0x72,0x69,0x76,0x61,0x74, + 0x65,0x20,0x4F,0x72,0x67,0x61,0x6E,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x46,0x52,0x31,0x0E,0x30,0x0C,0x06, + 0x03,0x55,0x04,0x11,0x13,0x05,0x35,0x39,0x31,0x30,0x30,0x31,0x0D,0x30,0x0B,0x06, + 0x03,0x55,0x04,0x08,0x13,0x04,0x4E,0x6F,0x72,0x64,0x31,0x10,0x30,0x0E,0x06,0x03, + 0x55,0x04,0x07,0x13,0x07,0x52,0x6F,0x75,0x62,0x61,0x69,0x78,0x31,0x19,0x30,0x17, + 0x06,0x03,0x55,0x04,0x09,0x13,0x10,0x32,0x20,0x72,0x75,0x65,0x20,0x4B,0x65,0x6C, + 0x6C,0x65,0x72,0x6D,0x61,0x6E,0x6E,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x0A, + 0x13,0x07,0x4F,0x56,0x48,0x20,0x53,0x41,0x53,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x0B,0x13,0x02,0x49,0x54,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x0B,0x13, + 0x0D,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x45,0x56,0x20,0x53,0x53,0x4C,0x31,0x10, + 0x30,0x0E,0x06,0x03,0x55,0x04,0x03,0x13,0x07,0x6F,0x76,0x68,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,0x93,0xA1,0x5D,0x05,0x5F,0x1A,0x26,0x56,0x3D,0xDC,0xC2,0x7C,0x1B,0xA1,0x7A, + 0x63,0x16,0x4F,0xBD,0xE0,0x77,0x85,0x04,0xB0,0x9B,0x49,0xE9,0x2B,0x5C,0xB1,0x51, + 0xFD,0x8A,0x14,0x51,0xC7,0xD9,0x50,0xDE,0x64,0x2F,0xFE,0x8C,0x27,0xC3,0x01,0x48, + 0x64,0x7C,0x85,0x3F,0x93,0xD4,0x09,0xE6,0x42,0xDF,0xC1,0xE4,0xEB,0x6A,0xC0,0x87, + 0x90,0xA5,0xF6,0x9C,0xD4,0x6B,0x08,0x77,0xFB,0x56,0x44,0x2B,0x8A,0xE0,0x05,0x73, + 0x14,0x6B,0x02,0x7D,0x76,0x44,0x7B,0x3E,0xA6,0xE5,0x23,0xA9,0xE1,0x8F,0x99,0xDD, + 0x15,0xCD,0xD9,0xD9,0x6D,0xB9,0x95,0x5B,0xE8,0xB6,0xE2,0x52,0xDD,0xF0,0xB0,0x80, + 0x1B,0xC1,0x95,0x4B,0x2C,0x9D,0x5E,0x8D,0x02,0x6B,0x59,0x6C,0x26,0x8B,0xC3,0x19, + 0x0D,0x3E,0xA8,0x34,0xD0,0x43,0x81,0xD7,0xBD,0xB3,0xA7,0x04,0xE1,0x05,0x82,0xA6, + 0x1F,0x4D,0x70,0x67,0x05,0x96,0x88,0xE8,0xE9,0x2E,0x95,0xD2,0x36,0x75,0xD6,0xC8, + 0x0C,0x59,0xBF,0x9F,0x1F,0x9F,0xB4,0xFF,0xF0,0x10,0x8C,0xC3,0xE6,0x8B,0x9F,0xE2, + 0x8E,0x00,0x60,0x58,0xCB,0x6F,0xAD,0x84,0x7B,0xA5,0x36,0xDB,0xB2,0xA4,0xEB,0xC6, + 0xC8,0xD8,0x61,0x6E,0x4A,0xDC,0x5C,0x3E,0x2C,0x33,0xCB,0x1E,0x16,0x8B,0x8C,0xA3, + 0x5F,0x0F,0x30,0x4E,0x0A,0x5D,0xA0,0x53,0x7C,0xCE,0xAB,0x29,0x9A,0xC6,0x64,0xC5, + 0x5A,0xD7,0x94,0x3D,0x81,0xB1,0x05,0x3F,0x2A,0x6D,0xD7,0xB8,0x9D,0xF1,0x6D,0x13, + 0xFD,0x82,0xB4,0xF9,0x88,0x77,0xAB,0xB8,0x2C,0x7A,0x81,0x6E,0x68,0xFF,0x6E,0x04, + 0xC1,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x03,0x4E,0x30,0x82,0x03,0x4A,0x30,0x1F, + 0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x39,0xDA,0xFF,0xCA,0x28, + 0x14,0x8A,0xA8,0x74,0x13,0x08,0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30, + 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x0B,0x0F,0xAD,0xA6,0xC3,0xBF, + 0x98,0xA1,0xEC,0xCD,0x20,0xB3,0x2C,0x75,0x03,0x56,0x3A,0xA6,0xD3,0xE6,0x30,0x0E, + 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x0C, + 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03, + 0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x46,0x06,0x03,0x55, + 0x1D,0x20,0x04,0x3F,0x30,0x3D,0x30,0x3B,0x06,0x0C,0x2B,0x06,0x01,0x04,0x01,0xB2, + 0x31,0x01,0x02,0x01,0x05,0x01,0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x02,0x01,0x16,0x1D,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65, + 0x63,0x75,0x72,0x65,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F, + 0x43,0x50,0x53,0x30,0x56,0x06,0x03,0x55,0x1D,0x1F,0x04,0x4F,0x30,0x4D,0x30,0x4B, + 0xA0,0x49,0xA0,0x47,0x86,0x45,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C, + 0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F, + 0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x56, + 0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x53,0x65,0x63,0x75,0x72,0x65,0x53, + 0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x6C,0x30,0x81,0x87,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x7B,0x30,0x79,0x30,0x51,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x45,0x68,0x74,0x74,0x70,0x3A,0x2F, + 0x2F,0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F, + 0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x45,0x78,0x74,0x65,0x6E, + 0x64,0x65,0x64,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x53,0x65,0x63, + 0x75,0x72,0x65,0x53,0x65,0x72,0x76,0x65,0x72,0x43,0x41,0x2E,0x63,0x72,0x74,0x30, + 0x24,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74, + 0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63, + 0x61,0x2E,0x63,0x6F,0x6D,0x30,0x1F,0x06,0x03,0x55,0x1D,0x11,0x04,0x18,0x30,0x16, + 0x82,0x07,0x6F,0x76,0x68,0x2E,0x63,0x6F,0x6D,0x82,0x0B,0x77,0x77,0x77,0x2E,0x6F, + 0x76,0x68,0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01,0x7E,0x06,0x0A,0x2B,0x06,0x01,0x04, + 0x01,0xD6,0x79,0x02,0x04,0x02,0x04,0x82,0x01,0x6E,0x04,0x82,0x01,0x6A,0x01,0x68, + 0x00,0x76,0x00,0xA4,0xB9,0x09,0x90,0xB4,0x18,0x58,0x14,0x87,0xBB,0x13,0xA2,0xCC, + 0x67,0x70,0x0A,0x3C,0x35,0x98,0x04,0xF9,0x1B,0xDF,0xB8,0xE3,0x77,0xCD,0x0E,0xC8, + 0x0D,0xDC,0x10,0x00,0x00,0x01,0x5B,0xB5,0x7B,0xC8,0x2D,0x00,0x00,0x04,0x03,0x00, + 0x47,0x30,0x45,0x02,0x21,0x00,0xD5,0x1B,0x6C,0xAE,0x75,0x46,0x62,0x0C,0x8B,0x2E, + 0x14,0xB1,0xDE,0x7C,0xA5,0xFE,0x5C,0x4F,0x3E,0xB0,0xFF,0xFF,0x33,0xA2,0x84,0x58, + 0x51,0x57,0x97,0x09,0xAF,0x09,0x02,0x20,0x49,0xD7,0x12,0x12,0x6C,0x2A,0x00,0x21, + 0x5E,0x48,0xF8,0xD0,0xF2,0xA5,0x81,0x2A,0x4E,0xE9,0x22,0x0A,0x4E,0x46,0x8F,0xDB, + 0xA5,0x9C,0x4B,0x43,0x7E,0x51,0x24,0xE4,0x00,0x76,0x00,0x56,0x14,0x06,0x9A,0x2F, + 0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7,0x46,0x76,0xB9,0xBC,0x99, + 0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00,0x01,0x5B,0xB5, + 0x7B,0xC5,0xC8,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x36,0xA9,0x1D, + 0x52,0x63,0x04,0x11,0x1F,0x65,0xC6,0x97,0x7C,0x17,0xFC,0x17,0x8D,0xDB,0x9D,0xA7, + 0xB7,0x84,0x66,0x03,0x55,0x95,0x7D,0x42,0x39,0x98,0x60,0xDE,0x19,0x02,0x21,0x00, + 0x8B,0xB7,0x16,0xC0,0x20,0x17,0xBF,0x31,0x36,0xBD,0xBC,0x1C,0x12,0x61,0x42,0xC0, + 0x5C,0x19,0x97,0x0A,0xFA,0x85,0xDB,0x5D,0xC3,0x65,0xBE,0x18,0xBF,0x89,0x6F,0xB9, + 0x00,0x76,0x00,0xEE,0x4B,0xBD,0xB7,0x75,0xCE,0x60,0xBA,0xE1,0x42,0x69,0x1F,0xAB, + 0xE1,0x9E,0x66,0xA3,0x0F,0x7E,0x5F,0xB0,0x72,0xD8,0x83,0x00,0xC4,0x7B,0x89,0x7A, + 0xA8,0xFD,0xCB,0x00,0x00,0x01,0x5B,0xB5,0x7B,0xC7,0xFA,0x00,0x00,0x04,0x03,0x00, + 0x47,0x30,0x45,0x02,0x21,0x00,0xF8,0xFE,0x02,0xC9,0xAF,0x02,0x18,0xF4,0x12,0x00, + 0x39,0x3C,0x15,0xE0,0x9C,0x78,0x04,0x19,0x55,0xAE,0x8F,0xB4,0x22,0xB9,0x08,0x66, + 0x9E,0x21,0x3E,0xF0,0x7D,0xC6,0x02,0x20,0x47,0x45,0x31,0xC7,0x2C,0xC3,0xBE,0xC7, + 0x5B,0xD8,0x31,0x0A,0xD6,0xAF,0x9D,0xAF,0x04,0x45,0xAA,0x51,0x7D,0x43,0xEF,0x35, + 0x4D,0x81,0xB3,0x0A,0x2F,0x8D,0xD8,0x61,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6C,0x8E,0xB5,0x58, + 0x8A,0xC5,0x66,0xAC,0x99,0x68,0xF9,0x80,0x68,0x8E,0xC5,0x10,0xF7,0xD7,0x37,0x5E, + 0x09,0x8C,0x6B,0xCF,0x30,0x2B,0x98,0x3F,0x76,0x4D,0x69,0xBA,0xE8,0x61,0x1D,0xDE, + 0x1A,0x14,0x4F,0x5A,0x0B,0x54,0x0F,0x66,0xEF,0xB9,0xB3,0x51,0x6C,0x9B,0x86,0x1D, + 0xB9,0x13,0xC8,0x54,0x24,0x6C,0x82,0x6E,0x4B,0x3C,0x53,0xC7,0x7D,0x0B,0x40,0x4A, + 0x7E,0x23,0xF2,0x79,0x6B,0xC3,0xFF,0x9D,0xDF,0xC0,0x16,0x7B,0xFF,0x7B,0x04,0xC9, + 0xE0,0xEB,0x3F,0x28,0xC6,0xD2,0x79,0xEE,0xAE,0x7E,0x38,0x5F,0x0D,0xDF,0x71,0xE7, + 0xAA,0x38,0x7E,0xF3,0x28,0xE8,0xB2,0xAC,0x69,0xB9,0x69,0xD4,0x05,0x8E,0xF1,0x00, + 0x71,0x77,0x97,0x7F,0x94,0x36,0x45,0xE5,0x9C,0x15,0xA3,0xF1,0x40,0xD7,0xB5,0xEA, + 0x95,0x56,0x75,0x60,0x86,0xFB,0xCD,0xB7,0x81,0x5A,0x34,0x1A,0x83,0x1E,0xC2,0x50, + 0xA2,0x57,0x16,0x13,0x53,0x95,0xFA,0x95,0xD0,0x64,0x1E,0x09,0x45,0x50,0x05,0x63, + 0x3A,0x86,0xB2,0x1D,0x9B,0x19,0x0E,0x89,0x7E,0x75,0x17,0xDA,0xC5,0x4D,0x4F,0x71, + 0x55,0x82,0x3E,0x5F,0x41,0x25,0x2F,0x86,0x9E,0x3D,0xF1,0x32,0xFA,0x77,0x7C,0x30, + 0x6C,0x50,0x2F,0xE7,0x11,0x7B,0xE1,0x3F,0xA8,0x2E,0xEF,0xAC,0x36,0x94,0x8F,0xF0, + 0x92,0xB4,0xCA,0x1A,0x53,0x8E,0x12,0x26,0x48,0xC4,0xA8,0x25,0x19,0x96,0x19,0x11, + 0xA2,0xA2,0x48,0xEB,0x8C,0x12,0x59,0x7F,0xCE,0xFC,0x4B,0xC9,0x19,0x10,0x61,0x2B, + 0xB3,0xA6,0x6B,0xB4,0xBA,0x68,0xB9,0x22,0x58,0xE4,0x82,0x27, +}; + +/* This is the cert the ssl server returns to us. */ +/* subject:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ +/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority */ +static unsigned char comodo_ev_certificate[1554]={ + 0x30,0x82,0x06,0x0E,0x30,0x82,0x03,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x06, + 0xA7,0x43,0x80,0xD4,0xEB,0xFE,0xD4,0x35,0xB5,0xA3,0xF7,0xE1,0x6A,0xBD,0xD8,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x30,0x81, + 0x85,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, + 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, + 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, + 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, + 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, + 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x2B,0x30,0x29,0x06,0x03,0x55, + 0x04,0x03,0x13,0x22,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x43, + 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74, + 0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x31,0x32,0x30,0x32,0x31,0x32, + 0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x37,0x30,0x32,0x31,0x31,0x32, + 0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x81,0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13, + 0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72,0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73, + 0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61, + 0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11, + 0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43,0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65, + 0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F, + 0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20, + 0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72, + 0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,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,0x95,0x56,0xDE,0x54, + 0xB4,0xDF,0xD5,0x02,0x49,0x7B,0xD1,0x5B,0x5C,0xA2,0xB2,0x1E,0x8F,0x9C,0x2B,0x62, + 0x4C,0x2B,0x8D,0x12,0x28,0xF3,0x1A,0x95,0xA3,0xC6,0x10,0xFD,0x29,0xDE,0xE1,0x9F, + 0x0B,0x38,0x40,0x93,0xD1,0xEF,0x6E,0x95,0x10,0xFC,0xE1,0x90,0x17,0x77,0x2C,0xEE, + 0x75,0x3E,0x7B,0x63,0xEC,0x61,0x92,0x6E,0x4F,0x3B,0xAB,0x80,0x49,0x6B,0xDF,0x00, + 0xEA,0x03,0x00,0x7F,0x2F,0x75,0xD5,0x28,0x2F,0xEC,0x56,0x67,0x8F,0x80,0x83,0xA3, + 0xBD,0xDC,0x03,0x99,0x93,0x8B,0x94,0x91,0x56,0x5B,0xA1,0xB8,0x6A,0x3A,0x3F,0x06, + 0xBD,0x0E,0x92,0xCC,0x60,0x9C,0xFD,0xB5,0xE0,0x9F,0x66,0x30,0x5F,0xDB,0xE6,0x94, + 0xF0,0x95,0x6A,0xAF,0xC8,0x8A,0xAF,0x80,0xD9,0xE6,0x88,0x39,0x01,0x7C,0x1C,0xC0, + 0xC5,0x2A,0xF7,0x7B,0x95,0xA0,0xF2,0x76,0xAB,0x6D,0x9B,0x72,0x39,0x30,0xEB,0xD1, + 0x57,0x55,0x01,0x9D,0x58,0x11,0x9D,0x7C,0x6D,0x84,0x8F,0x49,0xE8,0x9D,0x09,0xFC, + 0x3C,0xFD,0x0A,0x4A,0x76,0x14,0x21,0x5C,0x16,0x73,0x40,0x23,0x19,0x74,0xC3,0xBA, + 0x58,0x0A,0xA6,0x96,0x2E,0xDE,0x36,0xE5,0x9F,0xD0,0xC2,0xF0,0xE1,0xE0,0xC1,0x62, + 0xE3,0xC2,0x18,0x45,0x19,0x51,0xAA,0x17,0x1E,0xE8,0x23,0x75,0xD4,0xC8,0xD0,0x96, + 0x13,0xFF,0xC7,0x24,0xD1,0x8C,0x0B,0x27,0xAE,0x9E,0x7A,0xDC,0x3A,0x61,0x63,0x60, + 0x88,0x97,0x2D,0x5D,0x05,0x0B,0xE5,0x3B,0xEB,0xAE,0xCE,0x3A,0x47,0x73,0x76,0xA8, + 0xFA,0x2C,0xDD,0xC0,0x87,0x17,0xE9,0xAC,0x30,0x99,0xF8,0x1F,0x02,0x03,0x01,0x00, + 0x01,0xA3,0x82,0x01,0x69,0x30,0x82,0x01,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23, + 0x04,0x18,0x30,0x16,0x80,0x14,0xBB,0xAF,0x7E,0x02,0x3D,0xFA,0xA6,0xF1,0x3C,0x84, + 0x8E,0xAD,0xEE,0x38,0x98,0xEC,0xD9,0x32,0x32,0xD4,0x30,0x1D,0x06,0x03,0x55,0x1D, + 0x0E,0x04,0x16,0x04,0x14,0x39,0xDA,0xFF,0xCA,0x28,0x14,0x8A,0xA8,0x74,0x13,0x08, + 0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, + 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13, + 0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x3E,0x06, + 0x03,0x55,0x1D,0x20,0x04,0x37,0x30,0x35,0x30,0x33,0x06,0x04,0x55,0x1D,0x20,0x00, + 0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1D, + 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65,0x63,0x75,0x72,0x65,0x2E,0x63, + 0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x4C,0x06, + 0x03,0x55,0x1D,0x1F,0x04,0x45,0x30,0x43,0x30,0x41,0xA0,0x3F,0xA0,0x3D,0x86,0x3B, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x63,0x6F,0x6D,0x6F,0x64, + 0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53, + 0x41,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x41,0x75, + 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x2E,0x63,0x72,0x6C,0x30,0x71,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3B,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D, + 0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x41,0x64,0x64,0x54,0x72,0x75, + 0x73,0x74,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, + 0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x03,0x82,0x02, + 0x01,0x00,0x44,0x42,0x9D,0x41,0x51,0x2B,0x48,0x88,0x5D,0x97,0x9B,0x79,0x5E,0x11, + 0x01,0x4A,0x52,0x19,0x7B,0x41,0x2C,0xC7,0x89,0x3C,0xD0,0x72,0xDC,0x85,0xFA,0x58, + 0xAF,0xD5,0x25,0xE4,0x13,0xF8,0x58,0x65,0x67,0x9F,0x0D,0xFF,0x57,0x8B,0xA9,0x85, + 0x5E,0xCA,0xA6,0x4B,0xB0,0xA7,0xB2,0x2D,0xE0,0x8C,0x22,0xCD,0xFB,0xFF,0x79,0xA4, + 0x8C,0x2B,0x8D,0xFE,0x02,0x3D,0x24,0xDE,0xA9,0x5D,0x5F,0xE4,0x0F,0x47,0xD0,0xDB, + 0x66,0x25,0x3E,0x87,0x47,0x0C,0xAE,0x22,0xC5,0x50,0x22,0x84,0xD7,0xED,0x4A,0x59, + 0x1A,0xF6,0x93,0xA5,0x93,0xB0,0xE0,0x1B,0x81,0xF2,0x56,0xC4,0xC8,0x10,0x53,0xE4, + 0xD4,0x76,0xB1,0xD1,0x5B,0x69,0x4B,0x77,0xB2,0xE0,0x4F,0xC4,0x84,0xE7,0xD4,0xA0, + 0x50,0xEE,0x3C,0xFA,0x44,0xFC,0xD0,0x57,0xB9,0xE1,0x28,0x53,0xFD,0x53,0xCD,0xDC, + 0xB9,0x1F,0x7A,0x40,0xBD,0x30,0x3F,0xD8,0x6C,0xD2,0xF3,0xE7,0x07,0x9F,0x1F,0x22, + 0xB5,0xEA,0x22,0x71,0xCB,0x2A,0xF0,0x56,0x7C,0xFE,0xAC,0xA8,0xD1,0x06,0x0F,0x14, + 0x14,0x52,0x4C,0xFE,0x64,0x2B,0x0C,0x69,0x2A,0xB8,0x0D,0x50,0x6E,0x3E,0x04,0x07, + 0xBF,0x7A,0x20,0x8B,0xF8,0xEE,0x65,0x09,0xE1,0xC7,0x49,0x08,0x32,0x3D,0x0D,0x28, + 0x7E,0x49,0x1D,0xB7,0x4A,0xEF,0x02,0xE7,0x0D,0x80,0x17,0xC8,0x5C,0xE0,0x61,0x62, + 0xCB,0xEC,0xB3,0x60,0x79,0x25,0xDA,0x1A,0x65,0x73,0x9C,0x38,0x10,0xA0,0x26,0x3A, + 0xB0,0xC8,0x16,0x7D,0x93,0x31,0x22,0xEE,0x74,0x0B,0x88,0xC0,0x5C,0x89,0x41,0x00, + 0x28,0xA9,0x47,0x31,0xDF,0x7D,0x49,0x45,0x9A,0xF5,0xE6,0xA7,0x45,0x1A,0xD2,0x8E, + 0x13,0x10,0xDF,0x83,0xAF,0x9B,0x0D,0xAD,0x7E,0x7E,0x9D,0x35,0x50,0x34,0x04,0xCE, + 0xE9,0x20,0xD6,0x9E,0xDB,0x9D,0xD4,0xA8,0xDA,0x64,0xB4,0xD1,0x2F,0x59,0x2E,0x5E, + 0xA2,0x36,0x61,0xD4,0x24,0xA0,0x82,0x33,0x33,0x8A,0xA1,0xD1,0x6C,0xEF,0x61,0x68, + 0xA3,0xE5,0xD2,0x56,0xAD,0xC5,0xFD,0x5E,0x62,0xEB,0x15,0xA8,0x74,0x12,0x4C,0x2F, + 0x31,0x8C,0xE9,0xC1,0xDF,0x10,0x4B,0x01,0xEA,0xF6,0x54,0x1B,0xCD,0x7F,0x3B,0xBD, + 0x5C,0x9F,0xC1,0xDB,0xCF,0x01,0xCA,0xF2,0xBA,0x60,0x12,0x21,0x31,0xED,0xA9,0x64, + 0xB8,0xB2,0x49,0x58,0x17,0x6D,0x5A,0xD7,0xCD,0x8C,0x6D,0xBE,0x9E,0x7F,0xE2,0x02, + 0x58,0xA7,0xDB,0xC3,0x2D,0x58,0xF6,0x74,0x06,0x6A,0x9A,0xF6,0x61,0xF9,0xF6,0x00, + 0xB6,0x69,0xD8,0x3A,0x8B,0x31,0x59,0xDD,0x91,0xE6,0x7C,0x27,0x23,0x87,0xDD,0x03, + 0x0F,0x8F,0x2A,0x8C,0x1E,0x83,0x01,0x4E,0x01,0x61,0x0C,0x52,0x73,0x6D,0xFC,0x08, + 0xA2,0xB9,0x2A,0x66,0xE4,0x76,0x4D,0x31,0xA0,0x56,0x9B,0xD9,0x53,0x8D,0xA2,0xB6, + 0x8F,0x02,0xC8,0xE6,0x3A,0xA6,0x04,0xD1,0x48,0xFB,0xC3,0x4A,0x02,0x76,0xFD,0x2F, + 0xD2,0xBC,0x13,0xB6,0xE8,0x6D,0x34,0x24,0xFA,0x9D,0x29,0x8A,0xC7,0xA1,0x2B,0x14, + 0xF1,0x96,0x00,0x73,0xB9,0x13,0xE9,0xC0,0xB9,0x3A,0x47,0x56,0x02,0x71,0x80,0x27, + 0xA4,0xBC,0x25,0xB6,0xE9,0xBD,0xE4,0xE9,0x98,0x74,0x16,0xF1,0x37,0x84,0x81,0x07, + 0xB4,0x82, +}; + +/* This is the cert we get when we get the url in the AIA extension of the ovh leaf. */ +/* subject:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Extended Validation Secure Server CA */ +/* issuer :/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority */ +static unsigned char comodo_aia_certificate[1554]={ + 0x30,0x82,0x06,0x0E,0x30,0x82,0x03,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x06, + 0xA7,0x43,0x80,0xD4,0xEB,0xFE,0xD4,0x35,0xB5,0xA3,0xF7,0xE1,0x6A,0xBD,0xD8,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x30,0x81, + 0x85,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B, + 0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13,0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72, + 0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73,0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06, + 0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61,0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30, + 0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43, + 0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x2B,0x30,0x29,0x06,0x03,0x55, + 0x04,0x03,0x13,0x22,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x43, + 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74, + 0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x31,0x32,0x30,0x32,0x31,0x32, + 0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x37,0x30,0x32,0x31,0x31,0x32, + 0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x81,0x92,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x47,0x42,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x08,0x13, + 0x12,0x47,0x72,0x65,0x61,0x74,0x65,0x72,0x20,0x4D,0x61,0x6E,0x63,0x68,0x65,0x73, + 0x74,0x65,0x72,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x53,0x61, + 0x6C,0x66,0x6F,0x72,0x64,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x0A,0x13,0x11, + 0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x20,0x43,0x41,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65, + 0x64,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x03,0x13,0x2F,0x43,0x4F,0x4D,0x4F, + 0x44,0x4F,0x20,0x52,0x53,0x41,0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20, + 0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F,0x6E,0x20,0x53,0x65,0x63,0x75,0x72, + 0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x41,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,0x95,0x56,0xDE,0x54, + 0xB4,0xDF,0xD5,0x02,0x49,0x7B,0xD1,0x5B,0x5C,0xA2,0xB2,0x1E,0x8F,0x9C,0x2B,0x62, + 0x4C,0x2B,0x8D,0x12,0x28,0xF3,0x1A,0x95,0xA3,0xC6,0x10,0xFD,0x29,0xDE,0xE1,0x9F, + 0x0B,0x38,0x40,0x93,0xD1,0xEF,0x6E,0x95,0x10,0xFC,0xE1,0x90,0x17,0x77,0x2C,0xEE, + 0x75,0x3E,0x7B,0x63,0xEC,0x61,0x92,0x6E,0x4F,0x3B,0xAB,0x80,0x49,0x6B,0xDF,0x00, + 0xEA,0x03,0x00,0x7F,0x2F,0x75,0xD5,0x28,0x2F,0xEC,0x56,0x67,0x8F,0x80,0x83,0xA3, + 0xBD,0xDC,0x03,0x99,0x93,0x8B,0x94,0x91,0x56,0x5B,0xA1,0xB8,0x6A,0x3A,0x3F,0x06, + 0xBD,0x0E,0x92,0xCC,0x60,0x9C,0xFD,0xB5,0xE0,0x9F,0x66,0x30,0x5F,0xDB,0xE6,0x94, + 0xF0,0x95,0x6A,0xAF,0xC8,0x8A,0xAF,0x80,0xD9,0xE6,0x88,0x39,0x01,0x7C,0x1C,0xC0, + 0xC5,0x2A,0xF7,0x7B,0x95,0xA0,0xF2,0x76,0xAB,0x6D,0x9B,0x72,0x39,0x30,0xEB,0xD1, + 0x57,0x55,0x01,0x9D,0x58,0x11,0x9D,0x7C,0x6D,0x84,0x8F,0x49,0xE8,0x9D,0x09,0xFC, + 0x3C,0xFD,0x0A,0x4A,0x76,0x14,0x21,0x5C,0x16,0x73,0x40,0x23,0x19,0x74,0xC3,0xBA, + 0x58,0x0A,0xA6,0x96,0x2E,0xDE,0x36,0xE5,0x9F,0xD0,0xC2,0xF0,0xE1,0xE0,0xC1,0x62, + 0xE3,0xC2,0x18,0x45,0x19,0x51,0xAA,0x17,0x1E,0xE8,0x23,0x75,0xD4,0xC8,0xD0,0x96, + 0x13,0xFF,0xC7,0x24,0xD1,0x8C,0x0B,0x27,0xAE,0x9E,0x7A,0xDC,0x3A,0x61,0x63,0x60, + 0x88,0x97,0x2D,0x5D,0x05,0x0B,0xE5,0x3B,0xEB,0xAE,0xCE,0x3A,0x47,0x73,0x76,0xA8, + 0xFA,0x2C,0xDD,0xC0,0x87,0x17,0xE9,0xAC,0x30,0x99,0xF8,0x1F,0x02,0x03,0x01,0x00, + 0x01,0xA3,0x82,0x01,0x69,0x30,0x82,0x01,0x65,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23, + 0x04,0x18,0x30,0x16,0x80,0x14,0xBB,0xAF,0x7E,0x02,0x3D,0xFA,0xA6,0xF1,0x3C,0x84, + 0x8E,0xAD,0xEE,0x38,0x98,0xEC,0xD9,0x32,0x32,0xD4,0x30,0x1D,0x06,0x03,0x55,0x1D, + 0x0E,0x04,0x16,0x04,0x14,0x39,0xDA,0xFF,0xCA,0x28,0x14,0x8A,0xA8,0x74,0x13,0x08, + 0xB9,0xE4,0x0E,0xA9,0xD2,0xFA,0x7E,0x9D,0x69,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, + 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x12,0x06,0x03,0x55,0x1D,0x13, + 0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x3E,0x06, + 0x03,0x55,0x1D,0x20,0x04,0x37,0x30,0x35,0x30,0x33,0x06,0x04,0x55,0x1D,0x20,0x00, + 0x30,0x2B,0x30,0x29,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1D, + 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x73,0x65,0x63,0x75,0x72,0x65,0x2E,0x63, + 0x6F,0x6D,0x6F,0x64,0x6F,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x50,0x53,0x30,0x4C,0x06, + 0x03,0x55,0x1D,0x1F,0x04,0x45,0x30,0x43,0x30,0x41,0xA0,0x3F,0xA0,0x3D,0x86,0x3B, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x63,0x6F,0x6D,0x6F,0x64, + 0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53, + 0x41,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x41,0x75, + 0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x2E,0x63,0x72,0x6C,0x30,0x71,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x65,0x30,0x63,0x30,0x3B,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x2F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x63,0x72,0x74,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D, + 0x2F,0x43,0x4F,0x4D,0x4F,0x44,0x4F,0x52,0x53,0x41,0x41,0x64,0x64,0x54,0x72,0x75, + 0x73,0x74,0x43,0x41,0x2E,0x63,0x72,0x74,0x30,0x24,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73, + 0x70,0x2E,0x63,0x6F,0x6D,0x6F,0x64,0x6F,0x63,0x61,0x2E,0x63,0x6F,0x6D,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,0x05,0x00,0x03,0x82,0x02, + 0x01,0x00,0x44,0x42,0x9D,0x41,0x51,0x2B,0x48,0x88,0x5D,0x97,0x9B,0x79,0x5E,0x11, + 0x01,0x4A,0x52,0x19,0x7B,0x41,0x2C,0xC7,0x89,0x3C,0xD0,0x72,0xDC,0x85,0xFA,0x58, + 0xAF,0xD5,0x25,0xE4,0x13,0xF8,0x58,0x65,0x67,0x9F,0x0D,0xFF,0x57,0x8B,0xA9,0x85, + 0x5E,0xCA,0xA6,0x4B,0xB0,0xA7,0xB2,0x2D,0xE0,0x8C,0x22,0xCD,0xFB,0xFF,0x79,0xA4, + 0x8C,0x2B,0x8D,0xFE,0x02,0x3D,0x24,0xDE,0xA9,0x5D,0x5F,0xE4,0x0F,0x47,0xD0,0xDB, + 0x66,0x25,0x3E,0x87,0x47,0x0C,0xAE,0x22,0xC5,0x50,0x22,0x84,0xD7,0xED,0x4A,0x59, + 0x1A,0xF6,0x93,0xA5,0x93,0xB0,0xE0,0x1B,0x81,0xF2,0x56,0xC4,0xC8,0x10,0x53,0xE4, + 0xD4,0x76,0xB1,0xD1,0x5B,0x69,0x4B,0x77,0xB2,0xE0,0x4F,0xC4,0x84,0xE7,0xD4,0xA0, + 0x50,0xEE,0x3C,0xFA,0x44,0xFC,0xD0,0x57,0xB9,0xE1,0x28,0x53,0xFD,0x53,0xCD,0xDC, + 0xB9,0x1F,0x7A,0x40,0xBD,0x30,0x3F,0xD8,0x6C,0xD2,0xF3,0xE7,0x07,0x9F,0x1F,0x22, + 0xB5,0xEA,0x22,0x71,0xCB,0x2A,0xF0,0x56,0x7C,0xFE,0xAC,0xA8,0xD1,0x06,0x0F,0x14, + 0x14,0x52,0x4C,0xFE,0x64,0x2B,0x0C,0x69,0x2A,0xB8,0x0D,0x50,0x6E,0x3E,0x04,0x07, + 0xBF,0x7A,0x20,0x8B,0xF8,0xEE,0x65,0x09,0xE1,0xC7,0x49,0x08,0x32,0x3D,0x0D,0x28, + 0x7E,0x49,0x1D,0xB7,0x4A,0xEF,0x02,0xE7,0x0D,0x80,0x17,0xC8,0x5C,0xE0,0x61,0x62, + 0xCB,0xEC,0xB3,0x60,0x79,0x25,0xDA,0x1A,0x65,0x73,0x9C,0x38,0x10,0xA0,0x26,0x3A, + 0xB0,0xC8,0x16,0x7D,0x93,0x31,0x22,0xEE,0x74,0x0B,0x88,0xC0,0x5C,0x89,0x41,0x00, + 0x28,0xA9,0x47,0x31,0xDF,0x7D,0x49,0x45,0x9A,0xF5,0xE6,0xA7,0x45,0x1A,0xD2,0x8E, + 0x13,0x10,0xDF,0x83,0xAF,0x9B,0x0D,0xAD,0x7E,0x7E,0x9D,0x35,0x50,0x34,0x04,0xCE, + 0xE9,0x20,0xD6,0x9E,0xDB,0x9D,0xD4,0xA8,0xDA,0x64,0xB4,0xD1,0x2F,0x59,0x2E,0x5E, + 0xA2,0x36,0x61,0xD4,0x24,0xA0,0x82,0x33,0x33,0x8A,0xA1,0xD1,0x6C,0xEF,0x61,0x68, + 0xA3,0xE5,0xD2,0x56,0xAD,0xC5,0xFD,0x5E,0x62,0xEB,0x15,0xA8,0x74,0x12,0x4C,0x2F, + 0x31,0x8C,0xE9,0xC1,0xDF,0x10,0x4B,0x01,0xEA,0xF6,0x54,0x1B,0xCD,0x7F,0x3B,0xBD, + 0x5C,0x9F,0xC1,0xDB,0xCF,0x01,0xCA,0xF2,0xBA,0x60,0x12,0x21,0x31,0xED,0xA9,0x64, + 0xB8,0xB2,0x49,0x58,0x17,0x6D,0x5A,0xD7,0xCD,0x8C,0x6D,0xBE,0x9E,0x7F,0xE2,0x02, + 0x58,0xA7,0xDB,0xC3,0x2D,0x58,0xF6,0x74,0x06,0x6A,0x9A,0xF6,0x61,0xF9,0xF6,0x00, + 0xB6,0x69,0xD8,0x3A,0x8B,0x31,0x59,0xDD,0x91,0xE6,0x7C,0x27,0x23,0x87,0xDD,0x03, + 0x0F,0x8F,0x2A,0x8C,0x1E,0x83,0x01,0x4E,0x01,0x61,0x0C,0x52,0x73,0x6D,0xFC,0x08, + 0xA2,0xB9,0x2A,0x66,0xE4,0x76,0x4D,0x31,0xA0,0x56,0x9B,0xD9,0x53,0x8D,0xA2,0xB6, + 0x8F,0x02,0xC8,0xE6,0x3A,0xA6,0x04,0xD1,0x48,0xFB,0xC3,0x4A,0x02,0x76,0xFD,0x2F, + 0xD2,0xBC,0x13,0xB6,0xE8,0x6D,0x34,0x24,0xFA,0x9D,0x29,0x8A,0xC7,0xA1,0x2B,0x14, + 0xF1,0x96,0x00,0x73,0xB9,0x13,0xE9,0xC0,0xB9,0x3A,0x47,0x56,0x02,0x71,0x80,0x27, + 0xA4,0xBC,0x25,0xB6,0xE9,0xBD,0xE4,0xE9,0x98,0x74,0x16,0xF1,0x37,0x84,0x81,0x07, + 0xB4,0x82, +}; + +uint8_t _caissuer_https[] = { + 0x30,0x82,0x04,0x68,0x30,0x82,0x03,0x50,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x7A, + 0x22,0xA1,0x88,0x18,0x9E,0x75,0x77,0xE6,0xEF,0x7E,0xC0,0x33,0x8E,0xE8,0x90,0xE8, + 0x7B,0xC4,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x30,0x81,0x81,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C, + 0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, + 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x15, + 0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x0C,0x0C,0x54,0x65,0x73,0x74,0x20,0x52,0x6F, + 0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x38,0x30,0x34,0x32,0x38,0x32, + 0x30,0x32,0x31,0x34,0x31,0x5A,0x17,0x0D,0x31,0x39,0x30,0x34,0x32,0x38,0x32,0x30, + 0x32,0x31,0x34,0x31,0x5A,0x30,0x81,0x8D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A, + 0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03, + 0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65, + 0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69, + 0x6E,0x67,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x48,0x54,0x54, + 0x50,0x53,0x20,0x43,0x41,0x49,0x73,0x73,0x75,0x65,0x72,0x20,0x54,0x65,0x73,0x74, + 0x20,0x43,0x65,0x72,0x74,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,0xC1,0x68,0xC2,0x47,0x1E,0x07,0x82,0x66,0x47,0xC9, + 0x5C,0x22,0xDD,0x8B,0x93,0x6A,0xA7,0x22,0x00,0xB8,0xDA,0x8C,0x3C,0x52,0xA7,0x47, + 0x73,0xBB,0x7A,0xD7,0x8C,0x1E,0xAE,0xDA,0x34,0x25,0x4E,0xEB,0x1F,0x33,0x0B,0x8A, + 0xC7,0x6D,0x2A,0x93,0xDB,0x0D,0xD0,0x47,0x85,0x9C,0x14,0xD5,0x23,0xE3,0xE4,0x94, + 0xE0,0x17,0x9F,0x56,0x64,0x8E,0xE0,0x08,0xE9,0x1B,0x4C,0x7C,0x77,0xF9,0x35,0x74, + 0x52,0x43,0x90,0x13,0xFA,0x51,0x9A,0xA2,0x93,0x47,0x94,0xE7,0xBD,0x07,0xE5,0xFB, + 0x67,0x8B,0xF0,0xE2,0x0C,0x97,0xFD,0x29,0x51,0xBD,0x85,0x6C,0xBE,0x36,0xFD,0xDD, + 0xCC,0x99,0x4D,0x68,0x37,0x96,0xB2,0x20,0x85,0x55,0xA5,0x99,0xA4,0x7E,0xD7,0x19, + 0x06,0x15,0x20,0x10,0x50,0x51,0x2E,0x74,0x5C,0x43,0x49,0x94,0x6B,0x0E,0x9E,0xFB, + 0xDF,0xB2,0xEB,0xD9,0x28,0xA8,0xF1,0x25,0x49,0xC8,0xFE,0x3B,0xE1,0x45,0x95,0x47, + 0xD1,0x53,0xCD,0x34,0x9A,0x6F,0xC4,0x3F,0x63,0xC2,0x60,0xC6,0x40,0xBB,0xF7,0x20, + 0x8A,0xB8,0xB7,0xD7,0xC2,0xBB,0x48,0x24,0x64,0xA2,0x4A,0xE4,0x2A,0x17,0x68,0xE2, + 0xAC,0x47,0x2D,0xCC,0xBD,0xB7,0xCE,0x73,0xDF,0x96,0x8C,0x12,0x56,0xE3,0x29,0xE3, + 0x4D,0xB4,0x55,0x28,0xAB,0x28,0x24,0x45,0x7F,0x55,0x66,0xCD,0x46,0x29,0x89,0x58, + 0xFF,0xA6,0xD1,0x67,0xAC,0x50,0xEE,0x55,0x6D,0x6A,0x2A,0xCF,0xD6,0x09,0xE9,0xDA, + 0x22,0xB0,0xAF,0x90,0xD7,0x02,0xB2,0xCE,0x5F,0x09,0x96,0x5E,0x88,0xAE,0xB5,0xB6, + 0xA1,0xC3,0x9D,0x1A,0x2F,0x2D,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xCA,0x30,0x81, + 0xC7,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30, + 0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x01,0x30,0x16,0x06,0x03,0x55,0x1D,0x11,0x04,0x0F,0x30,0x0D,0x82, + 0x0B,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xDF,0xC7,0x68,0x26,0x64,0x95,0x5D,0x73,0x36, + 0x84,0xE8,0xE3,0x1D,0xC8,0x28,0x5E,0xA8,0x27,0x73,0x8C,0x30,0x1F,0x06,0x03,0x55, + 0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xB5,0xA9,0x53,0x08,0x10,0x38,0x1A,0xA5, + 0xB3,0x84,0xC9,0xEE,0xC4,0xAB,0x0F,0xB8,0x5F,0x68,0x10,0xA2,0x30,0x3A,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x2E,0x30,0x2C,0x30,0x2A,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A, + 0x2F,0x2F,0x65,0x78,0x61,0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74,0x65, + 0x73,0x74,0x43,0x41,0x2E,0x64,0x65,0x72,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xC4,0x48,0xDF,0x5E, + 0x73,0xD1,0x43,0x28,0x7D,0x69,0x71,0x32,0x1F,0xCC,0x1A,0xEB,0x5B,0x98,0x9D,0xCE, + 0xFF,0xCA,0x16,0xA9,0x96,0xE7,0x4D,0xC4,0xAE,0x53,0xE2,0x5D,0xDB,0xDA,0x40,0x80, + 0xE5,0xFB,0xF3,0xD7,0x21,0x9A,0x77,0x1D,0x67,0xFC,0x04,0x62,0x18,0xFF,0x10,0x59, + 0xF4,0xDD,0xF4,0xC6,0x8F,0xB4,0xEF,0x9F,0x05,0xA6,0xF1,0xCB,0x44,0x24,0x02,0x19, + 0x75,0xF9,0x3C,0x28,0x8A,0xAA,0x57,0x6B,0xFF,0x64,0xFF,0xD7,0xE2,0x62,0x67,0x70, + 0x20,0x4D,0xAE,0xD2,0x67,0xED,0x92,0xA4,0xFA,0x8A,0xC3,0x24,0x9C,0x2F,0x4D,0x2C, + 0xA9,0xA5,0x92,0x5E,0x5C,0x6F,0xDB,0xAB,0x96,0xA6,0xB1,0x5B,0xF1,0x8D,0x97,0x08, + 0xBC,0x5B,0x27,0xD5,0x9E,0x2D,0xF0,0x49,0x68,0xA6,0x92,0x00,0x13,0xAD,0x60,0x9E, + 0x78,0x72,0xC2,0x18,0xB8,0xE5,0x9D,0x72,0xA5,0x87,0x61,0xA8,0x95,0x8A,0x2B,0xB2, + 0xCC,0xCA,0x7F,0x1E,0x1E,0xC5,0xFB,0x5A,0x0C,0x77,0x17,0xB0,0xBE,0x7B,0x5A,0x50, + 0x05,0x32,0x40,0x98,0x3A,0x8B,0x22,0x3F,0x3B,0xA5,0xA8,0xA9,0x59,0x3B,0x55,0x92, + 0xD1,0x8A,0x34,0x73,0xA6,0xD6,0x5D,0x5E,0x85,0x59,0x00,0xD5,0x55,0x94,0x80,0xC1, + 0xB9,0xF1,0xCA,0x2B,0xC5,0x96,0xEE,0x49,0x6A,0x2C,0xDD,0x62,0x98,0xB3,0x74,0x09, + 0x09,0xDE,0x3D,0x59,0x5B,0x21,0x76,0x6E,0x27,0x66,0xED,0x7B,0x74,0x7F,0xE7,0xA9, + 0xAE,0xEB,0x40,0x83,0xB9,0xBC,0xE6,0x0C,0x1E,0x53,0xB2,0xEA,0x79,0xC4,0xA9,0x30, + 0x2B,0x1F,0xC4,0x34,0x82,0x3E,0xFC,0x1E,0x2D,0x66,0x75,0xD0, +}; + +#endif /* _TRUSTTESTS_CA_ISSUER_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/CTTests.m b/tests/TrustTests/EvaluationTests/CTTests.m index 7d058ee7..40fdd7c4 100644 --- a/tests/TrustTests/EvaluationTests/CTTests.m +++ b/tests/TrustTests/EvaluationTests/CTTests.m @@ -34,7 +34,10 @@ #include "trust/trustd/OTATrustUtilities.h" #if !TARGET_OS_BRIDGE +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" #import +#pragma clang diagnostic pop #endif #if TARGET_OS_IPHONE @@ -1894,4 +1897,50 @@ errOut: CFReleaseNull(trust); } +- (void) testCheckCTRequired { + SecCertificateRef system_root = NULL, system_server_after = NULL; + SecTrustRef trust = NULL; + NSArray *enforce_anchors = nil; + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:562340800.0]; // October 27, 2018 at 6:46:40 AM PDT + CFErrorRef error = nil; + + // A policy with CTRequired set + SecPolicyRef policy = SecPolicyCreateBasicX509(); + SecPolicySetOptionsValue(policy, kSecPolicyCheckCTRequired, kCFBooleanTrue); + + require_action(system_root = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_root"], + errOut, fail("failed to create system root")); + require_action(system_server_after = (__bridge SecCertificateRef)[CTTests SecCertificateCreateFromResource:@"enforcement_system_server_after"], + errOut, fail("failed to create system server cert issued after flag day")); + + enforce_anchors = @[ (__bridge id)system_root ]; + require_noerr_action(SecTrustCreateWithCertificates(system_server_after, policy, &trust), errOut, fail("failed to create trust")); + require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)enforce_anchors), errOut, fail("failed to set anchors")); + require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)date), errOut, fail("failed to set verify date")); + + require_noerr_action(SecTrustSetTrustedLogs(trust, (__bridge CFArrayRef)trustedCTLogs), errOut, fail("failed to set trusted logs")); + + // test system cert without CT fails (with trusted logs) +#if !TARGET_OS_BRIDGE + is(SecTrustEvaluateWithError(trust, &error), false, "system post-flag-date non-CT cert with trusted logs succeeded"); + if (error) { + is(CFErrorGetCode(error), errSecNotTrusted, "got wrong error code for non-ct cert, got %ld, expected %d", + (long)CFErrorGetCode(error), (int)errSecNotTrusted); + } else { + fail("expected trust evaluation to fail and it did not."); + } +#else + /* BridgeOS doesn't enforce */ + ok(SecTrustEvaluateWithError(trust, NULL), "system post-flag-date non-CT cert with trusted logs failed"); +#endif + +errOut: + CFReleaseNull(system_root); + CFReleaseNull(system_server_after); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(error); + +} + @end diff --git a/tests/TrustTests/EvaluationTests/KeySizeTests.m b/tests/TrustTests/EvaluationTests/KeySizeTests.m index e905b822..f0aae4b9 100644 --- a/tests/TrustTests/EvaluationTests/KeySizeTests.m +++ b/tests/TrustTests/EvaluationTests/KeySizeTests.m @@ -108,7 +108,7 @@ errOut: ok_status(SecTrustSetVerifyDate(trust, date), "set owa.prt-forest.fi trust date to May 2013"); - SecKeyRef pubkey = SecTrustCopyPublicKey(trust); + SecKeyRef pubkey = SecTrustCopyKey(trust); isnt(pubkey, NULL, "pubkey returned"); CFReleaseNull(certs); diff --git a/tests/TrustTests/EvaluationTests/NameConstraintsTests.m b/tests/TrustTests/EvaluationTests/NameConstraintsTests.m index 7f6a8d75..f0871ab7 100644 --- a/tests/TrustTests/EvaluationTests/NameConstraintsTests.m +++ b/tests/TrustTests/EvaluationTests/NameConstraintsTests.m @@ -493,6 +493,8 @@ exit: return result; } +#if !TARGET_OS_WATCH +// Skip test on watchOS due to size constraints (rdar://66792084) - (void) testBetterTLS { NSArray *testsArray = [self getTestsArray]; if([self untar_test_certs]) { @@ -539,5 +541,6 @@ exit: [[NSFileManager defaultManager] removeItemAtURL:tmpCertsDir error:nil]; } +#endif //!TARGET_OS_WATCH @end diff --git a/tests/TrustTests/EvaluationTests/PathParseTests.m b/tests/TrustTests/EvaluationTests/PathParseTests.m index 2d65d23f..10364389 100644 --- a/tests/TrustTests/EvaluationTests/PathParseTests.m +++ b/tests/TrustTests/EvaluationTests/PathParseTests.m @@ -76,20 +76,17 @@ const NSString *kSecTestPathFailureResources = @"si-18-certificate-parse/PathFai - (void)testUnparseableExtensions { SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _bad_extension_leaf, sizeof(_bad_extension_leaf)); - SecCertificateRef root = NULL; + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _bad_extension_root, sizeof(_bad_extension_root)); SecTrustRef trust = NULL; SecPolicyRef policy = SecPolicyCreateBasicX509(); CFErrorRef error = NULL; - - NSURL *rootURL = [[NSBundle bundleForClass:[self class]]URLForResource:@"root" withExtension:@".cer" subdirectory:@"si-18-certificate-parse"]; - XCTAssert(root = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)[NSData dataWithContentsOfURL:rootURL]), "Unable to create root cert"); NSArray *anchors = @[(__bridge id)root]; require_noerr_action(SecTrustCreateWithCertificates(leaf, policy, &trust), errOut, fail("Unable to create trust with certificate with unparseable extension")); require_noerr_action(SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)anchors), errOut, fail("Unable to set trust anchors")); - require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)[NSDate dateWithTimeIntervalSinceReferenceDate:507200000.0]), + require_noerr_action(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)[NSDate dateWithTimeIntervalSinceReferenceDate:620000000.0]), errOut, fail("Unable to set verify date")); XCTAssertFalse(SecTrustEvaluateWithError(trust, &error), "Got wrong trust result cert"); XCTAssert(error != NULL); diff --git a/tests/TrustTests/EvaluationTests/PathParseTests_data.h b/tests/TrustTests/EvaluationTests/PathParseTests_data.h index 507cb672..af473be4 100644 --- a/tests/TrustTests/EvaluationTests/PathParseTests_data.h +++ b/tests/TrustTests/EvaluationTests/PathParseTests_data.h @@ -5,50 +5,90 @@ #ifndef _TRUSTTESTS_EVALUATION_PATH_PARSE_TESTS_H_ #define _TRUSTTESTS_EVALUATION_PATH_PARSE_TESTS_H_ -/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=CoreTrust Test Leaf 1 */ -/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=CoreTrust Test CA */ +const uint8_t _bad_extension_root[] = { + 0x30,0x82,0x02,0x55,0x30,0x82,0x01,0xFD,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xA7,0x97,0x3B,0x17,0xE9,0x68,0x62,0x01,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE, + 0x3D,0x04,0x01,0x30,0x81,0x8D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61, + 0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04, + 0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75, + 0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67, + 0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x4F,0x43,0x53,0x50,0x20, + 0x52,0x65,0x73,0x70,0x6F,0x6E,0x64,0x65,0x72,0x20,0x54,0x65,0x73,0x74,0x20,0x52, + 0x6F,0x6F,0x74,0x30,0x1E,0x17,0x0D,0x32,0x30,0x30,0x37,0x31,0x33,0x32,0x30,0x31, + 0x30,0x31,0x37,0x5A,0x17,0x0D,0x33,0x30,0x30,0x37,0x31,0x31,0x32,0x30,0x31,0x30, + 0x31,0x37,0x5A,0x30,0x81,0x8D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61, + 0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04, + 0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75, + 0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67, + 0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x4F,0x43,0x53,0x50,0x20, + 0x52,0x65,0x73,0x70,0x6F,0x6E,0x64,0x65,0x72,0x20,0x54,0x65,0x73,0x74,0x20,0x52, + 0x6F,0x6F,0x74,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,0x45,0xA3, + 0x6E,0x77,0x59,0x2B,0x7D,0xD4,0x9D,0x44,0xD7,0xDA,0x3E,0x5C,0xE1,0xB3,0xF8,0x34, + 0xE8,0xE8,0xEC,0x53,0x5A,0x5B,0x88,0x79,0x62,0x20,0x00,0xE1,0x82,0x42,0x3F,0x9D, + 0x78,0xCD,0x6D,0x1C,0xF2,0xF6,0x7A,0x66,0xCA,0x1B,0xEA,0x40,0xFD,0x9B,0x9D,0x8B, + 0x31,0x63,0xE7,0x95,0x10,0xB8,0x91,0x24,0xAE,0xF3,0x30,0xE4,0x1F,0x35,0xA3,0x45, + 0x30,0x43,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06, + 0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF, + 0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0x59,0xB5,0xB1,0x6E,0x89,0x9B,0xAC,0x7E,0x19,0x13,0x2C,0x75,0x68,0x3D,0x9F, + 0x05,0x15,0x54,0x05,0x16,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01, + 0x03,0x47,0x00,0x30,0x44,0x02,0x20,0x48,0x3A,0xED,0x1D,0x9A,0xA1,0x82,0x4B,0x49, + 0x7D,0x92,0xF0,0xAD,0x8E,0x04,0x8E,0x0C,0x95,0x02,0x7A,0x7D,0x93,0xFD,0xDD,0x4D, + 0xDA,0x00,0xDA,0xBA,0x85,0x8A,0x6F,0x02,0x20,0x38,0xB0,0x4B,0x32,0xD0,0x61,0x6A, + 0x3A,0xBB,0x4C,0x24,0x6B,0x73,0x7A,0x97,0x44,0x63,0xEA,0x77,0xAB,0xB9,0x55,0xBF, + 0x40,0x96,0xEC,0xD5,0x2C,0x30,0x47,0x4E,0x2C, +}; + const uint8_t _bad_extension_leaf[] = { - 0x30,0x82,0x02,0x85,0x30,0x82,0x02,0x2C,0xA0,0x03,0x02,0x01,0x02,0x02,0x15,0x00, - 0xD5,0xEC,0xDB,0x27,0x18,0xA7,0xEC,0x88,0x42,0xBA,0xC8,0xCD,0xE6,0xFC,0x34,0x9A, - 0x4D,0x36,0xD3,0x4C,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x30, - 0x81,0x86,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, - 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, - 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, - 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, - 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, - 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1A,0x30,0x18, - 0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x43,0x6F,0x72,0x65,0x54,0x72,0x75,0x73,0x74, - 0x20,0x54,0x65,0x73,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x37,0x30,0x31, - 0x32,0x36,0x32,0x33,0x32,0x33,0x33,0x32,0x5A,0x17,0x0D,0x31,0x37,0x30,0x31,0x32, - 0x37,0x32,0x33,0x32,0x33,0x33,0x32,0x5A,0x30,0x81,0x8A,0x31,0x0B,0x30,0x09,0x06, - 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, - 0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30, - 0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E, - 0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, - 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, - 0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15, - 0x43,0x6F,0x72,0x65,0x54,0x72,0x75,0x73,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x4C, - 0x65,0x61,0x66,0x20,0x31,0x30,0x56,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, - 0x02,0x01,0x06,0x05,0x2B,0x81,0x04,0x00,0x0A,0x03,0x42,0x00,0x04,0xFA,0x43,0x00, - 0x5E,0xEF,0xEF,0x33,0xBA,0x03,0x5F,0x7B,0x42,0xE2,0xCF,0x7D,0x2A,0x61,0x69,0xE2, - 0xEB,0x7A,0xE1,0x98,0x49,0x60,0x0D,0xD8,0xCB,0x99,0x09,0x91,0x4E,0x8B,0x12,0xA4, - 0x7F,0x19,0xAE,0xF4,0x62,0x8D,0x36,0x1A,0x34,0x9C,0x64,0xFE,0xE9,0xB2,0x02,0x3E, - 0xFD,0x83,0x9D,0x7E,0x40,0x7D,0x21,0x0E,0xD4,0xDA,0x97,0x12,0xE2,0xA3,0x75,0x30, - 0x73,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, - 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30, - 0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x31,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x03,0x02,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xBB, - 0x3E,0xCE,0xF4,0xBA,0x9A,0xBC,0x9F,0x1E,0xF9,0x73,0xDB,0x11,0xEB,0x55,0x93,0xA3, - 0x59,0x5B,0x6C,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, - 0xEC,0xC0,0x39,0x7A,0xDF,0x66,0x7B,0x15,0xB1,0x13,0x9E,0x8D,0xD6,0xB2,0x77,0xA6, - 0xBA,0xEE,0x2A,0xA1,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x03, - 0x48,0x00,0x30,0x45,0x02,0x20,0x2B,0x9C,0xC9,0xD3,0x86,0x66,0x7A,0xCD,0x58,0xFC, - 0x48,0x06,0xF6,0xC6,0xCC,0xE2,0x0F,0xA8,0xE4,0x66,0x16,0x2C,0xA8,0xCC,0x51,0xB6, - 0x1B,0x56,0xAC,0xBB,0x9F,0xD4,0x02,0x21,0x00,0xA2,0x51,0xAC,0x76,0xE6,0x3B,0x3B, - 0x0D,0x79,0xCD,0xB6,0x71,0x66,0x9E,0xEF,0x3C,0xB8,0x56,0xEA,0xBF,0x64,0x48,0x5B, - 0x0B,0x9B,0x38,0x06,0xBE,0xBA,0xE5,0xC9,0x17, + 0x30,0x82,0x02,0x94,0x30,0x82,0x02,0x3A,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x25, + 0xF3,0xFF,0xBB,0x76,0x44,0x44,0x8A,0xC2,0xC2,0xF6,0xC6,0x0D,0xEF,0x53,0x19,0xBE, + 0x01,0x1F,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x30,0x81, + 0x8D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x21,0x30,0x1F,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x18,0x4F,0x43,0x53,0x50,0x20,0x52,0x65,0x73,0x70,0x6F, + 0x6E,0x64,0x65,0x72,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x30,0x1E, + 0x17,0x0D,0x32,0x30,0x30,0x37,0x31,0x34,0x30,0x30,0x30,0x34,0x30,0x37,0x5A,0x17, + 0x0D,0x32,0x31,0x30,0x37,0x31,0x34,0x30,0x30,0x30,0x34,0x30,0x37,0x5A,0x30,0x81, + 0x8F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75, + 0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x23,0x30,0x21,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x1A,0x4F,0x43,0x53,0x50,0x20,0x52,0x65,0x73,0x70,0x6F, + 0x6E,0x64,0x65,0x72,0x20,0x54,0x65,0x73,0x74,0x3A,0x20,0x56,0x61,0x6C,0x69,0x64, + 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,0x4D,0xFC,0xED,0x57,0xD8, + 0xEA,0x29,0xC6,0xE5,0x25,0x87,0x51,0xAA,0x73,0x6A,0x5F,0x00,0x4C,0x64,0x42,0xE0, + 0x53,0xAE,0xEE,0x9E,0x3F,0x4B,0xBC,0x2B,0x7B,0xFB,0x24,0x33,0x53,0x9F,0x42,0x33, + 0x99,0xC4,0x1A,0x33,0xC8,0x09,0xCC,0x8E,0x50,0x74,0xC1,0x3E,0x9A,0x42,0x9E,0x6F, + 0x46,0x4E,0x73,0x34,0xE4,0xF1,0x7A,0x7E,0xE1,0x40,0x61,0xA3,0x75,0x30,0x73,0x30, + 0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x82,0x30,0x13,0x06, + 0x03,0x55,0x1D,0x25,0x04,0x0C,0x31,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x03,0x09,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x09,0x35,0xC3, + 0xB1,0x7D,0x12,0x8D,0xBC,0xB0,0x3C,0xF7,0xC4,0xA9,0x7D,0xA1,0x2A,0x84,0x9C,0xEE, + 0x67,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x59,0xB5, + 0xB1,0x6E,0x89,0x9B,0xAC,0x7E,0x19,0x13,0x2C,0x75,0x68,0x3D,0x9F,0x05,0x15,0x54, + 0x05,0x16,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03,0x48, + 0x00,0x30,0x45,0x02,0x20,0x13,0x00,0x46,0x93,0x44,0x1D,0x80,0x74,0x0A,0x59,0xE3, + 0x79,0x43,0xFD,0x04,0x2A,0x6C,0x19,0x5A,0x79,0x53,0x46,0x9E,0x8F,0x3A,0x31,0x47, + 0x05,0x9F,0xF8,0xE0,0xB4,0x02,0x21,0x00,0xAA,0x3D,0xBC,0x3E,0x68,0x47,0x71,0xCC, + 0x36,0x90,0x33,0xF3,0xC4,0xEA,0x12,0xF4,0x4C,0x96,0x65,0xE3,0x65,0xB4,0x7E,0x24, + 0xAB,0x6C,0x64,0xFA,0x13,0x6C,0xF9,0x4C, }; diff --git a/tests/TrustTests/EvaluationTests/PolicyTests.m b/tests/TrustTests/EvaluationTests/PolicyTests.m index e844ab74..f1161142 100644 --- a/tests/TrustTests/EvaluationTests/PolicyTests.m +++ b/tests/TrustTests/EvaluationTests/PolicyTests.m @@ -50,9 +50,11 @@ #include #include +#include #include #include #include +#include #include #include @@ -61,6 +63,7 @@ #include "../TrustEvaluationTestHelpers.h" const NSString *kSecTrustTestPinningPolicyResources = @"si-20-sectrust-policies-data"; +const NSString *kSecTrustTestPinnningTest = @"PinningPolicyTrustTest"; @interface PolicyTests : TrustEvaluationTestCase @end @@ -74,8 +77,8 @@ const NSString *kSecTrustTestPinningPolicyResources = @"si-20-sectrust-policies- testPlist = [[NSBundle bundleForClass:[self class]] URLForResource:@"debugging" withExtension:@"plist" subdirectory:(NSString *)kSecTrustTestPinningPolicyResources]; if (!testPlist) { - testPlist = [[NSBundle bundleForClass:[self class]] URLForResource:nil withExtension:@"plist" - subdirectory:(NSString *)kSecTrustTestPinningPolicyResources ]; + testPlist = [[NSBundle bundleForClass:[self class]] URLForResource:(NSString *)kSecTrustTestPinnningTest withExtension:@"plist" + subdirectory:(NSString *)kSecTrustTestPinningPolicyResources]; } if (!testPlist) { fail("Failed to get tests plist from %@", kSecTrustTestPinningPolicyResources); @@ -142,4 +145,164 @@ errOut: CFReleaseNull(trust); } +- (void)testSecPolicyReconcilePinningRequiredIfInfoSpecified +{ + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("www.example.org")); + CFMutableArrayRef emptySPKISHA256 = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + + CFMutableArrayRef nonemtpySPKISHA256 = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + uint8_t _random_data256[256/sizeof(uint8_t)]; + (void)SecRandomCopyBytes(NULL, sizeof(_random_data256), _random_data256); + CFDataRef random_data256 = CFDataCreate(kCFAllocatorDefault, _random_data256, sizeof(_random_data256)); + CFArrayAppendValue(nonemtpySPKISHA256, random_data256); + CFReleaseNull(random_data256); + + // kSecPolicyCheckPinningRequired should be unset after reconciliation. + // Empty values for both SPKI policies signal a pinning exception. + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + SecPolicySetOptionsValue(policy, kSecPolicyCheckLeafSPKISHA256, emptySPKISHA256); + SecPolicySetOptionsValue(policy, kSecPolicyCheckCAspkiSHA256, emptySPKISHA256); + CFDictionaryRef policyOptions = SecPolicyGetOptions(policy); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), true); + SecPolicyReconcilePinningRequiredIfInfoSpecified((CFMutableDictionaryRef)policyOptions); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), false); + + // kSecPolicyCheckPinningRequired overrules the other two policies. + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + SecPolicySetOptionsValue(policy, kSecPolicyCheckLeafSPKISHA256, nonemtpySPKISHA256); + SecPolicySetOptionsValue(policy, kSecPolicyCheckCAspkiSHA256, emptySPKISHA256); + policyOptions = SecPolicyGetOptions(policy); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), true); + SecPolicyReconcilePinningRequiredIfInfoSpecified((CFMutableDictionaryRef)policyOptions); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), false); + + // kSecPolicyCheckPinningRequired overrules the other two policies. + SecPolicySetOptionsValue(policy, kSecPolicyCheckPinningRequired, kCFBooleanTrue); + SecPolicySetOptionsValue(policy, kSecPolicyCheckLeafSPKISHA256, emptySPKISHA256); + SecPolicySetOptionsValue(policy, kSecPolicyCheckCAspkiSHA256, nonemtpySPKISHA256); + policyOptions = SecPolicyGetOptions(policy); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), true); + SecPolicyReconcilePinningRequiredIfInfoSpecified((CFMutableDictionaryRef)policyOptions); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), false); + + // In the absence of kSecPolicyCheckPinningRequired there is nothing to reconcile. + CFReleaseNull(policy); + policy = SecPolicyCreateSSL(true, CFSTR("www.example.org")); + SecPolicySetOptionsValue(policy, kSecPolicyCheckLeafSPKISHA256, emptySPKISHA256); + SecPolicySetOptionsValue(policy, kSecPolicyCheckCAspkiSHA256, emptySPKISHA256); + policyOptions = SecPolicyGetOptions(policy); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), true); + SecPolicyReconcilePinningRequiredIfInfoSpecified((CFMutableDictionaryRef)policyOptions); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckPinningRequired), false); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckLeafSPKISHA256), true); + is(CFDictionaryContainsKey(policyOptions, kSecPolicyCheckCAspkiSHA256), true); + + CFReleaseNull(policy); + CFReleaseNull(emptySPKISHA256); + CFReleaseNull(nonemtpySPKISHA256); +} + +- (CFDictionaryRef)getNSPinnedDomainsFromDictionaryInfoFile:(NSString *)fileName +{ + NSURL *infoPlist = [[NSBundle bundleForClass:[self class]] URLForResource:fileName withExtension:@"plist" + subdirectory:(NSString *)kSecTrustTestPinningPolicyResources]; + if (!infoPlist) { + fail("Failed to access plist file \"%@\"", fileName); + return NULL; + } + + NSDictionary *infoDictionary = [NSDictionary dictionaryWithContentsOfURL:infoPlist]; + if (!infoDictionary) { + fail("Failed to create dictionary from plist file \"%@\"", fileName); + return NULL; + } + + CFTypeRef nsAppTransportSecurityDict = CFDictionaryGetValue((__bridge CFDictionaryRef)infoDictionary, CFSTR("NSAppTransportSecurity")); + if (!isDictionary(nsAppTransportSecurityDict)) { + fail("NSAppTransportSecurity dictionary entry is missing from plist file \"%@\"", fileName); + return NULL; + } + + CFDictionaryRef nsPinnedDomainsDict = CFDictionaryGetValue(nsAppTransportSecurityDict, CFSTR("NSPinnedDomains")); + if (!isDictionary(nsPinnedDomainsDict)) { + fail("NSPinnedDomains dictionary entry is missing from plist file \"%@\"", fileName); + return NULL; + } + + return nsPinnedDomainsDict; +} + +- (void)testParseNSPinnedDomains +{ + NSURL *testPlist = nil; + NSArray *testsArray = nil; + + + testPlist = [[NSBundle bundleForClass:[self class]] URLForResource:@"NSPinnedDomainsParsingTest_debugging" withExtension:@"plist" + subdirectory:(NSString *)kSecTrustTestPinningPolicyResources]; + if (!testPlist) { + testPlist = [[NSBundle bundleForClass:[self class]] URLForResource:@"NSPinnedDomainsParsingTest" withExtension:@"plist" + subdirectory:(NSString *)kSecTrustTestPinningPolicyResources]; + } + if (!testPlist) { + fail("Failed to get tests plist from \"%@\"", kSecTrustTestPinningPolicyResources); + return; + } + + testsArray = [NSArray arrayWithContentsOfURL: testPlist]; + if (!testsArray) { + fail("Failed to create array from plist"); + return; + } + + [testsArray enumerateObjectsUsingBlock:^(NSDictionary *testDict, NSUInteger idx, BOOL * _Nonnull stop) { + NSString *plistFileName = testDict[@"PlistFileName"]; + if (!plistFileName) { + fail("Failed to read plist file name from \"%@\":%lu", plistFileName, (unsigned long)idx); + return; + } + + NSDictionary *expectedProperties = testDict[@"ExpectedProperties"]; + if (!expectedProperties) { + fail("Missing the expected results in \"%@\"", plistFileName); + return; + } + bool hasNSPinnedLeafIdentities = [expectedProperties[@"NSPinnedLeafIdentities"] boolValue]; + int NSPinnedLeafIdentitiesCount = [expectedProperties[@"NSPinnedLeafIdentitiesCount"] intValue]; + bool hasNSPinnedCAIdentities = [expectedProperties[@"NSPinnedCAIdentities"] boolValue]; + int NSPinnedCAIdentitiesCount = [expectedProperties[@"NSPinnedCAIdentitiesCount"] intValue]; + bool hasNSIncludesSubdomains = [expectedProperties[@"NSIncludesSubdomains"] boolValue]; + + CFDictionaryRef nsPinnedDomainsDict = [self getNSPinnedDomainsFromDictionaryInfoFile:plistFileName]; + if (!isDictionary(nsPinnedDomainsDict)) { + fail("Unable to read %@", plistFileName); + return; + } + CFArrayRef leafSPKISHA256 = parseNSPinnedDomains(nsPinnedDomainsDict, CFSTR("example.org"), CFSTR("NSPinnedLeafIdentities")); + is(leafSPKISHA256 != NULL, hasNSPinnedLeafIdentities, "leafSPKISHA256 test failed in \"%@\"", plistFileName); + is(leafSPKISHA256 != NULL && CFArrayGetCount(leafSPKISHA256) != 0, NSPinnedLeafIdentitiesCount != 0, "leafSPKISHA256 count test failed in \"%@\"", plistFileName); + + CFArrayRef caSPKISHA256 = parseNSPinnedDomains(nsPinnedDomainsDict, CFSTR("example.org"), CFSTR("NSPinnedCAIdentities")); + is(caSPKISHA256 != NULL, hasNSPinnedCAIdentities, "caSPKISHA256 test failed in \"%@\"", plistFileName); + is(caSPKISHA256 != NULL && CFArrayGetCount(caSPKISHA256) != 0, NSPinnedCAIdentitiesCount != 0, "caSPKISHA256 count test failed in \"%@\"", plistFileName); + + caSPKISHA256 = parseNSPinnedDomains(nsPinnedDomainsDict, CFSTR("subdomain.example.org."), CFSTR("NSPinnedCAIdentities")); + is(caSPKISHA256 != NULL, hasNSIncludesSubdomains, "caSPKISHA256 subdomain test failed in \"%@\"", plistFileName); + }]; +} + @end diff --git a/tests/TrustTests/EvaluationTests/SMIMEPolicyTests.m b/tests/TrustTests/EvaluationTests/SMIMEPolicyTests.m new file mode 100644 index 00000000..5f95a8ff --- /dev/null +++ b/tests/TrustTests/EvaluationTests/SMIMEPolicyTests.m @@ -0,0 +1,439 @@ +// +// SMIMEPolicyTests.m +// Security +// +// Created by Bailey Basile on 11/5/19. +// + +#import + +#include +#include + +#import "../TrustEvaluationTestHelpers.h" +#import "TrustEvaluationTestCase.h" + +@interface SMIMEPolicyTests : TrustEvaluationTestCase +@end + +NSString *testDir = @"SMIMEPolicyTests-data"; +const CFStringRef emailAddr = CFSTR("test@example.com"); + +@implementation SMIMEPolicyTests + +- (NSArray *)anchors +{ + id root = [self SecCertificateCreateFromResource:@"root" subdirectory:testDir]; + NSArray *anchors = @[root]; + CFRelease((SecCertificateRef)root); + return anchors; +} + +- (NSDate *)verifyDate +{ + return [NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]; // January 6, 2020 at 2:40:00 AM PST +} + +- (bool)runTrustEvalForLeaf:(id)leaf policy:(SecPolicyRef)policy +{ + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[leaf] policies:@[(__bridge id)policy]]; + XCTAssertNotNil(eval); + [eval setAnchors:[self anchors]]; + [eval setVerifyDate:[self verifyDate]]; + return [eval evaluate:nil]; +} + +// MARK: Expiration tests + +- (void)testCheckExpiration +{ + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, emailAddr); + id leaf = [self SecCertificateCreateFromResource:@"email_protection" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Within validity + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[leaf] policies:@[(__bridge id)policy]]; + XCTAssertNotNil(eval); + [eval setAnchors:[self anchors]]; + [eval setVerifyDate:[self verifyDate]]; + XCTAssert([eval evaluate:nil]); + + // Expired + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:630000000.0]]; // December 18, 2020 at 8:00:00 AM PST + XCTAssertFalse([eval evaluate:nil]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testIgnoreExpiration +{ + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage | kSecIgnoreExpirationSMIMEUsage, emailAddr); + id leaf = [self SecCertificateCreateFromResource:@"email_protection" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Within validity + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[leaf] policies:@[(__bridge id)policy]]; + XCTAssertNotNil(eval); + [eval setAnchors:[self anchors]]; + [eval setVerifyDate:[self verifyDate]]; + XCTAssert([eval evaluate:nil]); + + // Expired + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:630000000.0]]; // December 18, 2020 at 8:00:00 AM PST + XCTAssert([eval evaluate:nil]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +// MARK: Name tests + +- (void)testNoEmailName +{ + id leaf = [self SecCertificateCreateFromResource:@"no_name" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Check Email name + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // Skip email name check + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, NULL); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testEmailNameSAN +{ + id leaf = [self SecCertificateCreateFromResource:@"san_name" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Address match + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Address mismatch + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, CFSTR("wrong@example.com")); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // Case-insensitive match + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, CFSTR("TEST@example.com")); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testEmailCommonName +{ + id leaf = [self SecCertificateCreateFromResource:@"common_name" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Address match but common name matches not supported + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testEmailAddressField +{ + id leaf = [self SecCertificateCreateFromResource:@"email_field" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Address match but subject name matches not supported + SecPolicyRef policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Address mismatch + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, CFSTR("wrong@example.com")); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // Case-insensitive match + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME | kSecSignSMIMEUsage, CFSTR("TEST@example.com")); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +// MARK: KU tests +- (void)testNoKU +{ + id leaf = [self SecCertificateCreateFromResource:@"san_name" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for sign KU (which allows unspecified KU) + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for sign KU or any encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage | kSecAnyEncryptSMIME, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // Don't look at KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(0, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testSignKU +{ + id leaf = [self SecCertificateCreateFromResource:@"digital_signature" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for sign KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for sign KU or any encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage | kSecAnyEncryptSMIME, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testNonRepudiationKU +{ + id leaf = [self SecCertificateCreateFromResource:@"non_repudiation" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for sign KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for sign KU or any encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage | kSecAnyEncryptSMIME, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + // No KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(0, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testKeyEncipherKU +{ + id leaf = [self SecCertificateCreateFromResource:@"key_encipher" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Key Encipher KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for any encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Data Encipher KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecDataEncryptSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testDataEncipherKU +{ + id leaf = [self SecCertificateCreateFromResource:@"data_encipher" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Data Encipher KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecDataEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for any encrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Encipher KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyEncryptSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testKeyAgreementKU +{ + id leaf = [self SecCertificateCreateFromResource:@"key_agreement" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Key Agreement Encrypt KU /* */ + SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyExchangeEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Decrypt KU /* */ + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeDecryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Both KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Digital Signature KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testKeyAgreementEncipherOnlyKU +{ + id leaf = [self SecCertificateCreateFromResource:@"key_agreement_encipher_only" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Key Agreement Encrypt KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyExchangeEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Decrypt KU /* */ + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeDecryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Both KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Digital Signature KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testKeyAgreementDecipherOnlyKU +{ + id leaf = [self SecCertificateCreateFromResource:@"key_agreement_decipher_only" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Key Agreement Encrypt KU /* */ + SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyExchangeEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Decrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeDecryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Both KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Digital Signature KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testKeyAgreementBothKU +{ + id leaf = [self SecCertificateCreateFromResource:@"key_agreement_encipher_decipher" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + // Look for Key Agreement Encrypt KU + SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyExchangeEncryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Decrypt KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeDecryptSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Key Agreement Both KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + // Look for Digital Signature KU + CFReleaseNull(policy); + policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +// MARK: EKU tests +- (void)testNoEKU +{ + id leaf = [self SecCertificateCreateFromResource:@"digital_signature" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testAnyEKU +{ + id leaf = [self SecCertificateCreateFromResource:@"any_eku" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssertFalse([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +- (void)testEmailEKU +{ + id leaf = [self SecCertificateCreateFromResource:@"email_protection" subdirectory:testDir]; + XCTAssertNotNil(leaf); + + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]); + + CFReleaseNull(policy); + CFRelease((SecCertificateRef)leaf); +} + +@end diff --git a/tests/TrustTests/EvaluationTests/SSLPolicyTests.m b/tests/TrustTests/EvaluationTests/SSLPolicyTests.m index 79f32b67..df056ea2 100644 --- a/tests/TrustTests/EvaluationTests/SSLPolicyTests.m +++ b/tests/TrustTests/EvaluationTests/SSLPolicyTests.m @@ -36,6 +36,8 @@ #include "SSLPolicyTests_data.h" #import "TrustEvaluationTestCase.h" +NSString * const testDirectory = @"ssl-policy-certs"; + @interface SSLPolicyTests : TrustEvaluationTestCase @end @@ -43,7 +45,7 @@ - (void)testSSLPolicyCerts { - NSArray *testPlistURLs = [[NSBundle bundleForClass:[self class]] URLsForResourcesWithExtension:@"plist" subdirectory:@"ssl-policy-certs"]; + NSArray *testPlistURLs = [[NSBundle bundleForClass:[self class]] URLsForResourcesWithExtension:@"plist" subdirectory:testDirectory]; if (testPlistURLs.count != 1) { fail("failed to find the test plist"); return; @@ -75,7 +77,7 @@ require_action_quiet(file, cleanup, fail("%@: Unable to load filename from plist", test_name)); /* get leaf certificate from file */ - cert_file_url = [[NSBundle bundleForClass:[self class]] URLForResource:(__bridge NSString *)file withExtension:@"cer" subdirectory:@"ssl-policy-certs"]; + cert_file_url = [[NSBundle bundleForClass:[self class]] URLForResource:(__bridge NSString *)file withExtension:@"cer" subdirectory:testDirectory]; require_action_quiet(cert_file_url, cleanup, fail("%@: Unable to get url for cert file %@", test_name, file)); @@ -153,9 +155,14 @@ } - (BOOL)runTrustEvaluation:(NSArray *)certs anchors:(NSArray *)anchors error:(NSError **)error +{ + return [self runTrustEvaluation:certs anchors:anchors date:590000000.0 error:error]; // September 12, 2019 at 9:53:20 AM PDT +} + +- (BOOL)runTrustEvaluation:(NSArray *)certs anchors:(NSArray *)anchors date:(NSTimeInterval)evalTime error:(NSError **)error { SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("example.com")); - NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:590000000.0]; // September 12, 2019 at 9:53:20 AM PDT + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:evalTime]; SecTrustRef trustRef = NULL; BOOL result = NO; CFErrorRef cferror = NULL; @@ -224,6 +231,116 @@ errOut: CFReleaseNull(root); } +- (void)testSystemTrust_subCAMissingEKU +{ + SecCertificateRef systemRoot = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_Root" + subdirectory:testDirectory]; + NSData *rootHash = CFBridgingRelease(SecCertificateCopySHA256Digest(systemRoot)); + [self setTestRootAsSystem:(const uint8_t *)[rootHash bytes]]; + + SecCertificateRef subCa = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_noEKU_ca" + subdirectory:testDirectory]; + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_noEKU_leaf" + subdirectory:testDirectory]; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCa]; + NSError *error = nil; + XCTAssertTrue([self runTrustEvaluation:certs anchors:@[(__bridge id)systemRoot] date:620000000.0 error:&error], //August 24, 2020 at 3:13:20 PM PDT + "system-trusted no EKU subCA cert failed: %@", error); + + [self removeTestRootAsSystem]; + CFReleaseNull(systemRoot); + CFReleaseNull(subCa); + CFReleaseNull(leaf); +} + +- (void)testSystemTrust_subCAAnyEKU +{ + SecCertificateRef systemRoot = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_Root" + subdirectory:testDirectory]; + NSData *rootHash = CFBridgingRelease(SecCertificateCopySHA256Digest(systemRoot)); + [self setTestRootAsSystem:(const uint8_t *)[rootHash bytes]]; + + SecCertificateRef subCa = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_anyEKU_ca" + subdirectory:testDirectory]; + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_anyEKU_leaf" + subdirectory:testDirectory]; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCa]; + NSError *error = nil; + XCTAssertTrue([self runTrustEvaluation:certs anchors:@[(__bridge id)systemRoot] date:620000000.0 error:&error], //August 24, 2020 at 3:13:20 PM PDT + "system-trusted anyEKU subCA cert failed: %@", error); + + [self removeTestRootAsSystem]; + CFReleaseNull(systemRoot); + CFReleaseNull(subCa); + CFReleaseNull(leaf); +} + +- (void)testSystemTrust_subCAServerAuthEKU +{ + SecCertificateRef systemRoot = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_Root" + subdirectory:testDirectory]; + NSData *rootHash = CFBridgingRelease(SecCertificateCopySHA256Digest(systemRoot)); + [self setTestRootAsSystem:(const uint8_t *)[rootHash bytes]]; + + SecCertificateRef subCa = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_ssl_ca" + subdirectory:testDirectory]; + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_ssl_leaf" + subdirectory:testDirectory]; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCa]; + NSError *error = nil; + XCTAssertTrue([self runTrustEvaluation:certs anchors:@[(__bridge id)systemRoot] date:620000000.0 error:&error], //August 24, 2020 at 3:13:20 PM PDT + "system-trusted SSL EKU subCA cert failed: %@", error); + + [self removeTestRootAsSystem]; + CFReleaseNull(systemRoot); + CFReleaseNull(subCa); + CFReleaseNull(leaf); +} + +- (void)testSystemTrust_subCA_SMIME_EKU +{ + SecCertificateRef systemRoot = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_Root" + subdirectory:testDirectory]; + NSData *rootHash = CFBridgingRelease(SecCertificateCopySHA256Digest(systemRoot)); + [self setTestRootAsSystem:(const uint8_t *)[rootHash bytes]]; + + SecCertificateRef subCa = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_smime_ca" + subdirectory:testDirectory]; + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_smime_leaf" + subdirectory:testDirectory]; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCa]; + NSError *error = nil; + XCTAssertFalse([self runTrustEvaluation:certs anchors:@[(__bridge id)systemRoot] date:620000000.0 error:&error], //August 24, 2020 at 3:13:20 PM PDT + "system-trusted SMIME subCA cert succeeded"); + XCTAssertNotNil(error); + if (error) { + XCTAssertEqual(error.code, errSecInvalidExtendedKeyUsage); + } + + [self removeTestRootAsSystem]; + CFReleaseNull(systemRoot); + CFReleaseNull(subCa); + CFReleaseNull(leaf); +} + +- (void)testAppTrust_subCA_SMIME_EKU +{ + SecCertificateRef systemRoot = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_Root" + subdirectory:testDirectory]; + SecCertificateRef subCa = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_smime_ca" + subdirectory:testDirectory]; + SecCertificateRef leaf = (__bridge SecCertificateRef)[self SecCertificateCreateFromResource:@"subCA_EKU_smime_leaf" + subdirectory:testDirectory]; + NSArray *certs = @[(__bridge id)leaf, (__bridge id)subCa]; + NSError *error = nil; + XCTAssertTrue([self runTrustEvaluation:certs anchors:@[(__bridge id)systemRoot] date:620000000.0 error:&error], //August 24, 2020 at 3:13:20 PM PDT + "app-trusted smime subCA cert failed: %@", error); + + CFReleaseNull(systemRoot); + CFReleaseNull(subCa); + CFReleaseNull(leaf); +} + // Other app trust of root SSL EKU tests of certs issued before July 2019 occur in testSSLPolicyCerts (Test4, Test17) - (void)testAppTrustRoot_AnyEKU_BeforeJul2019 @@ -396,4 +513,74 @@ errOut: } #endif // !TARGET_OS_BRIDGE +- (void)testIPAddressInDNSField +{ + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _ipAddress_dnsField, sizeof(_ipAddress_dnsField)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("10.0.0.1")); + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)cert] + policies:@[(__bridge id)policy]]; + [eval setAnchors:@[(__bridge id)cert]]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; + XCTAssertFalse([eval evaluate:nil]); + + CFReleaseNull(cert); + CFReleaseNull(policy); +} + +- (void)testIPAddressInSAN_Match +{ + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _ipAddress_SAN, sizeof(_ipAddress_SAN)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("10.0.0.1")); + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)cert] + policies:@[(__bridge id)policy]]; + [eval setAnchors:@[(__bridge id)cert]]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; + XCTAssert([eval evaluate:nil]); + + CFReleaseNull(cert); + CFReleaseNull(policy); +} + +- (void)testIPAddressInSAN_Mismatch +{ + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _ipAddress_SAN, sizeof(_ipAddress_SAN)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("10.0.0.2")); + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)cert] + policies:@[(__bridge id)policy]]; + [eval setAnchors:@[(__bridge id)cert]]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; + XCTAssertFalse([eval evaluate:nil]); + + CFReleaseNull(cert); + CFReleaseNull(policy); +} + +- (void)testIPAddressInCN +{ + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _ipAddress_CN, sizeof(_ipAddress_CN)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("10.0.0.1")); + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)cert] + policies:@[(__bridge id)policy]]; + [eval setAnchors:@[(__bridge id)cert]]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; + XCTAssertFalse([eval evaluate:nil]); + + CFReleaseNull(cert); + CFReleaseNull(policy); +} + +- (void)testBadIPAddressInSAN +{ + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _ipAddress_bad, sizeof(_ipAddress_bad)); + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("10.0.0.1")); + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[(__bridge id)cert] + policies:@[(__bridge id)policy]]; + [eval setAnchors:@[(__bridge id)cert]]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; + XCTAssertFalse([eval evaluate:nil]); + + CFReleaseNull(cert); + CFReleaseNull(policy); +} + @end diff --git a/tests/TrustTests/EvaluationTests/SSLPolicyTests_data.h b/tests/TrustTests/EvaluationTests/SSLPolicyTests_data.h index 3a03abbf..52fcd7ca 100644 --- a/tests/TrustTests/EvaluationTests/SSLPolicyTests_data.h +++ b/tests/TrustTests/EvaluationTests/SSLPolicyTests_data.h @@ -619,4 +619,294 @@ const uint8_t _anyEKU_AfterJul2019[] = { 0x49,0x64,0x81,0x31,0x5C,0x52,0x1A,0x7C,0x32,0x4A,0xB8,0xA6,0xE7,0xDD,0x95,0xD3, 0x2A,0x2C,0x2D,0x1C,0x57,0xC2,0x69,0xA2,0x3F,0xF9,0x6D,0xD3,0x0B, }; + +/* X509v3 Subject Alternative Name: + DNS:10.0.0.1 */ +const uint8_t _ipAddress_dnsField[] = { + 0x30,0x82,0x04,0x4D,0x30,0x82,0x03,0x35,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xD6,0xAF,0xD0,0x9F,0x40,0x03,0x75,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x9E,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x32,0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x0C,0x29,0x53, + 0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63,0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A, + 0x20,0x49,0x50,0x20,0x61,0x64,0x64,0x72,0x65,0x73,0x73,0x20,0x69,0x6E,0x20,0x44, + 0x4E,0x53,0x20,0x66,0x69,0x65,0x6C,0x64,0x30,0x1E,0x17,0x0D,0x31,0x39,0x31,0x31, + 0x30,0x38,0x30,0x30,0x30,0x32,0x30,0x39,0x5A,0x17,0x0D,0x32,0x30,0x31,0x31,0x30, + 0x37,0x30,0x30,0x30,0x32,0x30,0x39,0x5A,0x30,0x81,0x9E,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30, + 0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E, + 0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, + 0x65,0x72,0x69,0x6E,0x67,0x31,0x32,0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x0C,0x29, + 0x53,0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63,0x79,0x20,0x54,0x65,0x73,0x74,0x73, + 0x3A,0x20,0x49,0x50,0x20,0x61,0x64,0x64,0x72,0x65,0x73,0x73,0x20,0x69,0x6E,0x20, + 0x44,0x4E,0x53,0x20,0x66,0x69,0x65,0x6C,0x64,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,0xCD,0x1E,0x25,0xBC,0xE6,0xAA, + 0x54,0x69,0x1C,0xA2,0x0F,0x2F,0x25,0xA5,0xFB,0xB3,0x05,0xAB,0x88,0x6A,0x8E,0x0C, + 0x00,0xC7,0x5C,0x1A,0x3C,0x2A,0xBA,0xCE,0xEA,0x0B,0xEC,0x20,0xA4,0xC1,0xEB,0x80, + 0xDB,0x04,0xE5,0x17,0xFA,0x9C,0x6A,0x3C,0xE1,0xB5,0x29,0x74,0x43,0x49,0x6C,0xAB, + 0x11,0x10,0xB9,0xF3,0xB4,0x8C,0x62,0xA0,0x26,0x9B,0x54,0xDA,0x5F,0x6C,0x09,0x95, + 0xFB,0xE3,0xBA,0x3E,0xB4,0x68,0x28,0x19,0x36,0xB4,0x7C,0x13,0x48,0xE8,0x68,0xA5, + 0x15,0x3B,0xBD,0x57,0xD7,0x21,0x2C,0xC1,0x26,0x82,0xC1,0x66,0x96,0x71,0xF8,0x72, + 0xBD,0xB5,0x8A,0x93,0x9A,0xF2,0x26,0xC8,0xEE,0x15,0x1F,0xBF,0x82,0x5D,0x14,0x52, + 0x69,0x12,0x14,0x2A,0x6F,0x0E,0x2C,0xEE,0x67,0x6A,0xEB,0xC0,0xF9,0x38,0x27,0xD1, + 0x4E,0xF3,0x94,0x2E,0x0B,0x93,0xB9,0x0F,0x81,0xA0,0x1E,0x6E,0x0D,0x6E,0x35,0x82, + 0x96,0x1F,0x1A,0x76,0xEA,0x5C,0x89,0x09,0xFE,0x6F,0x8B,0x56,0x82,0xB6,0x02,0x5A, + 0x38,0x31,0x87,0x15,0xE0,0x55,0xFF,0xE9,0xF4,0x39,0xF7,0xFA,0xC0,0xE5,0xA2,0x1B, + 0x2A,0xAF,0x53,0xF0,0x4F,0xB8,0xE8,0xA6,0x01,0xF9,0x84,0xFE,0x6F,0xAE,0xFF,0xFD, + 0x65,0x7C,0x7A,0xFF,0xC4,0xB4,0xA5,0x69,0xD0,0x6F,0xDF,0x19,0xC6,0xEC,0x42,0x1C, + 0x2D,0x5D,0xCC,0x71,0x3E,0x02,0xE3,0x5A,0xCA,0xDB,0x62,0x06,0x19,0xBE,0xCB,0x1E, + 0xDD,0x27,0x7D,0x00,0x8F,0x31,0x73,0x43,0x27,0x0A,0x5B,0x5C,0x9B,0xDF,0x20,0x5F, + 0xF1,0x76,0x31,0xAB,0x34,0xA9,0x20,0x1A,0xCB,0xE7,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x81,0x8B,0x30,0x81,0x88,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, + 0x02,0x07,0x80,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x13,0x06,0x03,0x55,0x1D,0x11,0x04, + 0x0C,0x30,0x0A,0x82,0x08,0x31,0x30,0x2E,0x30,0x2E,0x30,0x2E,0x31,0x30,0x1D,0x06, + 0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x83,0xE0,0x4A,0x14,0xAD,0x61,0x5B,0xD2, + 0x79,0xA2,0x5E,0x9C,0x45,0xAC,0xD8,0x35,0x8B,0xF4,0x43,0x09,0x30,0x1F,0x06,0x03, + 0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x83,0xE0,0x4A,0x14,0xAD,0x61,0x5B, + 0xD2,0x79,0xA2,0x5E,0x9C,0x45,0xAC,0xD8,0x35,0x8B,0xF4,0x43,0x09,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01, + 0x00,0x45,0x79,0xD6,0x5F,0x71,0x88,0x20,0x8C,0x6D,0x5C,0x89,0x7D,0xD8,0x6E,0x48, + 0x21,0x8B,0xA7,0x14,0xD3,0xC5,0xA7,0xE1,0xFE,0xB4,0x9A,0x6A,0x72,0xD5,0x40,0xFF, + 0xBE,0x02,0x49,0x89,0x13,0x4D,0xAE,0xCD,0x9E,0x27,0xA2,0x0E,0xD1,0xBA,0xA5,0xB9, + 0x08,0x30,0xEB,0x8E,0xE9,0xCF,0xD5,0x80,0xA0,0x0A,0x0D,0x38,0x71,0x2B,0x31,0x02, + 0x14,0x42,0x98,0x41,0x3F,0x26,0x32,0x8D,0x1B,0x56,0xAB,0x9F,0x3D,0x94,0xFD,0xBB, + 0xD2,0xF7,0x2E,0xE2,0xA9,0xD3,0xFF,0x0C,0xDA,0x8D,0x8B,0x56,0x55,0x80,0x9A,0xF3, + 0xA2,0x44,0xB8,0x23,0xD5,0x03,0x27,0x11,0xC9,0x03,0x64,0xE9,0x24,0xAA,0x60,0x4A, + 0x93,0x04,0xF8,0xEA,0x66,0x9C,0x7A,0xE9,0x99,0x7E,0xA2,0x22,0x72,0x37,0xA7,0xCC, + 0xD5,0x0A,0xFA,0xC2,0xEA,0x25,0x0A,0xD0,0x7A,0xAD,0x60,0xD6,0x81,0xA3,0x80,0xD6, + 0xE6,0xB2,0xA9,0x6E,0x88,0xC2,0x58,0xD0,0xC7,0x0B,0xBD,0xD8,0xF6,0xD0,0x51,0x08, + 0x00,0x93,0x07,0x35,0x35,0x29,0x7B,0xA7,0x59,0x4E,0xD8,0x17,0x15,0x50,0xE6,0xEA, + 0xA2,0xB6,0x94,0x78,0xE9,0x76,0x3A,0xFF,0xB0,0xD5,0x9E,0xE8,0xBE,0xD5,0xD8,0x3F, + 0xA1,0xA0,0xC6,0x79,0x54,0x4A,0x1A,0xE0,0xAA,0xFE,0x51,0x82,0x3B,0x75,0xC8,0x03, + 0xD9,0x02,0x98,0xE9,0x30,0x79,0x58,0x93,0xD1,0x27,0x1F,0x11,0x58,0x49,0x33,0x82, + 0xE5,0x09,0x6F,0xE2,0xD0,0xA2,0x9D,0x29,0x49,0x85,0xAF,0x5E,0xB2,0xE7,0x9C,0x56, + 0x4E,0x73,0x5E,0x85,0x64,0x58,0x7D,0xE6,0xB4,0x07,0x8B,0x7B,0x12,0x80,0x6F,0x7A, + 0x3C, +}; + +/* X509v3 Subject Alternative Name: + IP Address:10.0.0.1 */ +const uint8_t _ipAddress_SAN[] = { + 0x30,0x82,0x04,0x37,0x30,0x82,0x03,0x1F,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xC7,0x90,0xC5,0x69,0xCA,0xE3,0xB4,0x07,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27,0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53, + 0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63,0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A, + 0x20,0x49,0x50,0x20,0x41,0x64,0x64,0x72,0x65,0x73,0x73,0x20,0x53,0x41,0x4E,0x30, + 0x1E,0x17,0x0D,0x31,0x39,0x31,0x31,0x30,0x38,0x30,0x30,0x31,0x34,0x32,0x31,0x5A, + 0x17,0x0D,0x32,0x30,0x31,0x31,0x30,0x37,0x30,0x30,0x31,0x34,0x32,0x31,0x5A,0x30, + 0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53,0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63, + 0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A,0x20,0x49,0x50,0x20,0x41,0x64,0x64,0x72, + 0x65,0x73,0x73,0x20,0x53,0x41,0x4E,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,0xC1,0x80,0xDE,0x51,0x33,0xB8,0x28,0xA8, + 0x7D,0x94,0x12,0x73,0x6F,0x0E,0xFC,0xF5,0xF0,0xC6,0x18,0xD2,0x87,0xB8,0x37,0xEE, + 0xF9,0xB1,0x69,0x1D,0xF9,0xE1,0x65,0x8D,0x47,0x34,0x50,0xBD,0x72,0x41,0x32,0x7A, + 0x02,0x0F,0x72,0x85,0xB8,0xE1,0x3D,0x7C,0x78,0x90,0x0A,0x81,0x06,0x25,0x9B,0x13, + 0xCA,0xD6,0xAA,0x77,0xDC,0x4A,0x9B,0x32,0xB7,0x1D,0xF1,0xEF,0x52,0x33,0xE3,0x5D, + 0x80,0xE0,0xE1,0xBB,0xF2,0x5E,0x91,0x55,0xA1,0xF8,0xE4,0x25,0x62,0xAB,0xBA,0x3D, + 0x42,0xEB,0x9B,0xD7,0x95,0x92,0x18,0x26,0x5F,0xB1,0x28,0x9B,0x01,0xDB,0x52,0x18, + 0xFE,0xF4,0x4F,0xD6,0x3A,0x49,0x13,0xE2,0xB0,0x06,0xEF,0x28,0x6C,0x89,0xFD,0x23, + 0x19,0x56,0xF7,0x1A,0x51,0x89,0x5C,0x13,0xDD,0xD6,0x55,0x70,0x17,0xCA,0x05,0x59, + 0x77,0xEA,0x75,0xA4,0x44,0x05,0x49,0xD3,0xD6,0xE4,0x04,0x74,0xC8,0x5F,0xF9,0x19, + 0x75,0x27,0xB2,0x17,0x6B,0x2E,0x45,0xE5,0x07,0xBD,0x17,0x70,0xFD,0xA2,0x6A,0xF7, + 0xF1,0xD8,0x43,0xBC,0xF6,0xCD,0xD1,0x2D,0xE0,0xF0,0x55,0xE7,0x60,0xA5,0x09,0x42, + 0xE6,0x67,0xB6,0x40,0x56,0x4E,0x3E,0xDF,0x7B,0x89,0x44,0x36,0x78,0x83,0x30,0x25, + 0x12,0xFF,0x48,0x97,0xC1,0x04,0x87,0xC7,0xA3,0x06,0xCE,0x06,0xCE,0x2F,0xAE,0x01, + 0x42,0x57,0x62,0x3B,0xDA,0xEB,0xD8,0xDB,0x96,0x5E,0xFC,0x1E,0x30,0x4B,0xE4,0x80, + 0xE1,0xD9,0x34,0x03,0x9C,0xD4,0x92,0x39,0x17,0xA8,0xCD,0xCA,0x96,0x54,0xEB,0x2D, + 0x12,0x77,0xE3,0x96,0x09,0x6D,0xBB,0x93,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x87, + 0x30,0x81,0x84,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, + 0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x0F,0x06,0x03,0x55,0x1D,0x11,0x04,0x08,0x30, + 0x06,0x87,0x04,0x0A,0x00,0x00,0x01,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0xE0,0xA6,0x7D,0x62,0x28,0x6C,0xC0,0xCE,0x46,0xC8,0x04,0xB0,0xBA,0xB9, + 0x9B,0xF6,0x4A,0x60,0xBF,0xA9,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30, + 0x16,0x80,0x14,0xE0,0xA6,0x7D,0x62,0x28,0x6C,0xC0,0xCE,0x46,0xC8,0x04,0xB0,0xBA, + 0xB9,0x9B,0xF6,0x4A,0x60,0xBF,0xA9,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x55,0xBB,0x48,0x72,0x61, + 0x8F,0xAF,0x7F,0x18,0x2F,0x31,0xF9,0xAA,0xFF,0x4A,0xC1,0x5B,0xBF,0x45,0xFE,0x82, + 0x3C,0xBE,0xFC,0xBB,0x58,0xA7,0x4A,0xF3,0x84,0xF8,0x10,0xB4,0x51,0x33,0x91,0xA0, + 0x58,0x1C,0x5F,0x67,0x91,0x31,0xD8,0xEC,0xA0,0x6A,0x85,0x84,0x71,0xBE,0xB5,0x18, + 0xAC,0xB8,0x7E,0xC3,0xFC,0x1C,0x74,0x84,0x48,0x2C,0x99,0xE9,0x52,0xBB,0x36,0x00, + 0x35,0x8C,0x50,0xC8,0x13,0x2A,0xFA,0x1E,0xF8,0x15,0x72,0xEF,0xF0,0x20,0x28,0xA0, + 0xCD,0xC7,0x85,0xEF,0x48,0x8C,0x27,0xF9,0x0E,0x15,0x9F,0xB8,0x54,0xD1,0x44,0x08, + 0x31,0xB0,0xC8,0x24,0x53,0x4A,0x63,0x97,0xB5,0xB3,0x83,0x07,0xCD,0x6D,0xC5,0x10, + 0xDD,0xC0,0x90,0xA2,0xFF,0x8E,0xD5,0x2F,0xC4,0xBC,0x8A,0xE0,0x90,0xAA,0x79,0x09, + 0xB5,0x23,0x72,0x6A,0xFB,0x9B,0xE5,0x0E,0xD9,0x30,0x41,0x70,0xF1,0x17,0x9C,0x5F, + 0xD7,0x0A,0x10,0x8E,0x77,0xD9,0x2F,0x59,0xE4,0xB4,0xF6,0x8D,0x16,0x90,0x84,0xBB, + 0xB6,0xAF,0xEE,0x86,0x4D,0x21,0xAE,0x3E,0x7B,0x2F,0xAD,0xBD,0xC4,0x38,0x9C,0x9E, + 0xB5,0x7C,0x8D,0x36,0x72,0x2C,0x78,0xC7,0xD4,0x54,0xD9,0x93,0x18,0xC8,0x00,0x5E, + 0xFE,0x12,0xE4,0x50,0x90,0x88,0xFB,0x82,0xFE,0x94,0xA5,0x4C,0xEB,0x7F,0xB7,0x39, + 0x99,0x24,0x0B,0x23,0xF9,0xB4,0x92,0xA8,0x6F,0xA6,0x46,0xBB,0xFB,0xDA,0xCD,0x8F, + 0xB9,0x14,0xE8,0x9B,0xBB,0x1B,0x80,0x9E,0x9D,0x9A,0x16,0xFF,0xF1,0x55,0xFF,0xDF, + 0x3E,0x32,0x73,0x16,0x9D,0xEA,0xF0,0xB1,0x5A,0x12,0xAB, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=10.0.0.1 */ +const uint8_t _ipAddress_CN[] = { + 0x30,0x82,0x03,0xF2,0x30,0x82,0x02,0xDA,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xD8,0xED,0xBE,0x22,0x56,0xD4,0x12,0x16,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x7D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, + 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06, + 0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53, + 0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72, + 0x69,0x6E,0x67,0x31,0x11,0x30,0x0F,0x06,0x03,0x55,0x04,0x03,0x0C,0x08,0x31,0x30, + 0x2E,0x30,0x2E,0x30,0x2E,0x31,0x30,0x1E,0x17,0x0D,0x31,0x39,0x31,0x31,0x30,0x38, + 0x30,0x31,0x32,0x32,0x32,0x32,0x5A,0x17,0x0D,0x32,0x30,0x31,0x31,0x30,0x37,0x30, + 0x31,0x32,0x32,0x32,0x32,0x5A,0x30,0x7D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A, + 0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03, + 0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65, + 0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69, + 0x6E,0x67,0x31,0x11,0x30,0x0F,0x06,0x03,0x55,0x04,0x03,0x0C,0x08,0x31,0x30,0x2E, + 0x30,0x2E,0x30,0x2E,0x31,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,0xF3,0x54,0x35,0x8B,0xF0,0x54,0x65,0xA4,0x26,0x6D, + 0xFE,0x08,0x28,0x12,0x36,0x03,0x05,0xD7,0x23,0x92,0x7A,0xEB,0x61,0x9D,0xEE,0x67, + 0x5E,0x48,0x86,0x1F,0x2F,0x66,0x6B,0x71,0x56,0xC3,0xA0,0x20,0x13,0x76,0xEC,0x6A, + 0x53,0x59,0xAE,0xD3,0x61,0x1E,0xE7,0xEC,0x15,0xBD,0xB7,0x46,0x6C,0x8D,0x65,0x1F, + 0xAA,0x1C,0x7C,0x9A,0xB6,0xFD,0xEF,0x94,0x63,0xDC,0x12,0x0A,0x65,0x86,0x6D,0x1B, + 0xAC,0xD7,0xD0,0x47,0x92,0x10,0x9E,0x21,0x50,0xD5,0x2D,0x2F,0xA3,0xB8,0x1F,0xA3, + 0xB4,0xB6,0xA9,0x5C,0xED,0x3B,0x49,0xB7,0x3B,0xEA,0x02,0x9F,0xFB,0xE3,0x1C,0x6A, + 0xBB,0xE4,0x10,0x64,0x77,0xF9,0x8A,0x7B,0x4D,0x3E,0xC7,0xFF,0xE4,0x41,0x10,0xDE, + 0xB5,0xDD,0xB9,0xFA,0x02,0x3B,0xBA,0x10,0x83,0x0C,0x82,0x5C,0x6D,0xEF,0x64,0xEC, + 0xA8,0x12,0xAA,0x0B,0xC9,0x48,0x43,0xD0,0x6F,0x06,0x6E,0x8F,0xB6,0x87,0xBC,0x57, + 0x01,0xB7,0xD0,0x2F,0xC7,0x6F,0xAC,0x95,0xDA,0xE0,0xD7,0x64,0x9B,0xD5,0xE0,0xFD, + 0x62,0xF8,0xD1,0x46,0x20,0xD8,0x67,0x45,0xD3,0xC0,0x48,0x54,0xFD,0x0E,0x0D,0xBE, + 0x05,0xAB,0x81,0x23,0x25,0x90,0x51,0xB8,0x4D,0xA8,0x97,0xDE,0x2F,0xD3,0x7B,0x1B, + 0x24,0xEF,0x83,0x0B,0xC1,0x25,0x9C,0x7D,0x6E,0x47,0x1D,0x3A,0xE0,0x4D,0x64,0x03, + 0x11,0x79,0x15,0xB4,0xB2,0x88,0x29,0x37,0x02,0x71,0xF4,0x3A,0x73,0xB2,0x03,0x4F, + 0xD6,0x5B,0xEB,0x2E,0xB5,0xF6,0x1B,0x0E,0x14,0xD5,0x89,0x79,0xBC,0x38,0xA2,0xF1, + 0x9F,0x26,0xB5,0xC1,0x26,0xC7,0x02,0x03,0x01,0x00,0x01,0xA3,0x75,0x30,0x73,0x30, + 0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x13,0x06, + 0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x03,0x01,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x40,0x73,0xD8, + 0x0F,0xE3,0xF0,0x6B,0x0A,0x00,0x5B,0x94,0x31,0x23,0x56,0xC1,0xC2,0x12,0xF6,0xA8, + 0x33,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x40,0x73, + 0xD8,0x0F,0xE3,0xF0,0x6B,0x0A,0x00,0x5B,0x94,0x31,0x23,0x56,0xC1,0xC2,0x12,0xF6, + 0xA8,0x33,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x03,0x82,0x01,0x01,0x00,0xBA,0x76,0xA7,0x28,0x46,0xFD,0x2A,0x5A,0x96,0x51, + 0xEC,0xC7,0x5A,0x6A,0x98,0x76,0x7C,0x41,0x2B,0xE0,0xF5,0xD6,0x85,0x59,0x5F,0xCA, + 0x5F,0x10,0xC0,0xE9,0x23,0x58,0x89,0xCB,0x89,0xCD,0x8F,0xB7,0x37,0xA0,0x47,0x28, + 0x70,0x3A,0x17,0x0A,0x87,0x87,0x10,0x61,0xB1,0xBD,0x57,0x32,0x1F,0x03,0xD6,0x14, + 0x5D,0x53,0xB0,0xBA,0x91,0x2E,0x86,0x62,0xB9,0xB7,0xC8,0xFF,0x5A,0xC7,0xF9,0xA3, + 0x6D,0x9F,0x12,0x1B,0x9C,0x7B,0xB6,0x0B,0x9D,0x12,0xE6,0x1A,0x2A,0xD3,0x9C,0x2E, + 0x1C,0x75,0x0C,0xC3,0xAC,0xD6,0x4F,0x41,0x31,0xDB,0x2D,0x62,0x39,0xE7,0xB6,0x2B, + 0xFC,0xA8,0x21,0x15,0xEF,0xD3,0x8A,0xB8,0x1E,0xD9,0x5C,0xB6,0x04,0xE0,0xCB,0x0F, + 0x0C,0xC1,0xE5,0x91,0xAB,0x3A,0x30,0xBA,0xD5,0x0A,0xE0,0x88,0x2B,0x97,0x7C,0x79, + 0x50,0xBC,0x8F,0xB5,0x3D,0xA2,0x70,0xC8,0xB4,0x30,0xC4,0xDE,0x12,0x25,0x14,0xAA, + 0x82,0xAB,0x36,0x9A,0x24,0xA5,0x16,0xE0,0xB2,0x47,0xA6,0x5E,0x7E,0xD0,0xDA,0x95, + 0xA2,0xEF,0x46,0x6B,0xEB,0xD3,0x30,0xD8,0xC1,0xEC,0x92,0x21,0xD0,0x54,0x8D,0x12, + 0xD1,0x27,0x5F,0xA6,0x3D,0x9F,0x92,0x3A,0x81,0x66,0xB4,0xF0,0x54,0xD0,0xED,0xC7, + 0xC1,0x88,0x68,0xC3,0xD8,0x63,0xD0,0x3C,0x11,0x46,0x31,0x70,0xC1,0x88,0xC1,0x37, + 0x7C,0x84,0x7E,0xCA,0xF9,0x6F,0x97,0x47,0x1D,0x4C,0x09,0x1C,0x36,0xF9,0x89,0x11, + 0x1D,0x89,0x48,0xB0,0x23,0x2F,0x58,0xE6,0x8F,0xB7,0xED,0x69,0xF2,0xAD,0x45,0xD7, + 0x03,0x4E,0xAB,0xB6,0x81,0x0C, +}; + +/* subjectAltName=DER:30:07:87:05:0a:00:00:00:01 + * (IP address with 5 bytes) */ +const uint8_t _ipAddress_bad[] = { + 0x30,0x82,0x04,0x38,0x30,0x82,0x03,0x20,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xD5,0x17,0xAC,0x1D,0x94,0x23,0xB1,0x70,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27,0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53, + 0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63,0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A, + 0x20,0x42,0x61,0x64,0x20,0x49,0x50,0x20,0x41,0x64,0x64,0x72,0x65,0x73,0x73,0x30, + 0x1E,0x17,0x0D,0x31,0x39,0x31,0x31,0x30,0x38,0x30,0x32,0x35,0x34,0x32,0x33,0x5A, + 0x17,0x0D,0x32,0x30,0x31,0x31,0x30,0x37,0x30,0x32,0x35,0x34,0x32,0x33,0x5A,0x30, + 0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53,0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63, + 0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A,0x20,0x42,0x61,0x64,0x20,0x49,0x50,0x20, + 0x41,0x64,0x64,0x72,0x65,0x73,0x73,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,0xBB,0x94,0xF8,0x59,0x6D,0x04,0x9E,0x53, + 0x0C,0xC2,0x96,0x89,0x7A,0xE8,0x66,0x9B,0x1D,0x1A,0x5A,0x12,0x86,0x61,0xAB,0x5D, + 0x00,0xC9,0x40,0x2D,0x1F,0x4C,0x5F,0x76,0xFF,0xD4,0xBE,0xD0,0x08,0xD6,0x0C,0x1C, + 0xE5,0xC6,0xE3,0xA5,0xDC,0x65,0x2A,0x53,0xAB,0xC9,0x64,0x27,0x0C,0xAF,0x56,0x00, + 0x93,0x53,0x99,0x16,0x59,0x29,0xD8,0x7A,0x89,0x0B,0x11,0xCD,0x47,0xFD,0xD3,0xBD, + 0xF0,0x8A,0x4E,0x97,0xFA,0xA1,0x0F,0xCD,0xBA,0xD3,0x18,0x29,0x44,0xBD,0x27,0x59, + 0x3C,0xF6,0x43,0x30,0xB8,0xB2,0x0F,0xE4,0xE5,0x2A,0x77,0x6A,0xC1,0x35,0x96,0x2E, + 0x9A,0x0D,0x75,0x23,0x09,0xDF,0x37,0x30,0x76,0xAC,0xF2,0x30,0x5E,0x38,0xC9,0x96, + 0x53,0x6B,0x78,0xB7,0xCF,0x23,0x34,0xA4,0x79,0xEC,0xFD,0x23,0x93,0xB2,0x92,0x24, + 0x7E,0x84,0xB4,0x09,0x84,0x4F,0xD6,0x99,0x06,0x60,0x52,0xE7,0x3C,0x13,0x27,0x72, + 0x34,0x5F,0x8D,0xE3,0x0E,0x81,0xCF,0x6E,0x66,0x79,0xBA,0xA2,0x2B,0x62,0xE1,0xBF, + 0x5D,0xFA,0x66,0x47,0x26,0x7A,0x2A,0xAC,0x89,0x2D,0x44,0x35,0x40,0x60,0xA5,0x92, + 0xA0,0xF5,0x8C,0x86,0xF1,0x04,0x55,0xAB,0xF1,0x1E,0xEA,0x42,0x26,0x0D,0x5D,0x80, + 0x20,0x8F,0xF7,0x2A,0xF8,0x73,0x6F,0x7B,0xED,0xBA,0x9B,0xFB,0xB4,0x57,0x13,0xC2, + 0xB5,0x11,0x8B,0x29,0x37,0x52,0xCD,0x86,0x47,0xE0,0x80,0xB4,0x7B,0xF8,0x92,0xA4, + 0xCC,0x52,0x29,0x52,0xB1,0xC9,0x5A,0x12,0xE4,0x70,0xFB,0xB2,0x29,0xAF,0xC5,0x8A, + 0x00,0xDF,0xD1,0xEC,0x16,0xDE,0x41,0x4D,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x88, + 0x30,0x81,0x85,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, + 0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x10,0x06,0x03,0x55,0x1D,0x11,0x04,0x09,0x30, + 0x07,0x87,0x05,0x0A,0x00,0x00,0x00,0x01,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04, + 0x16,0x04,0x14,0x5B,0xE9,0x2F,0x45,0xBA,0x5B,0x72,0x64,0x55,0x96,0x5B,0xB9,0x29, + 0x94,0x08,0xB9,0x4E,0x79,0x8C,0x28,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18, + 0x30,0x16,0x80,0x14,0x5B,0xE9,0x2F,0x45,0xBA,0x5B,0x72,0x64,0x55,0x96,0x5B,0xB9, + 0x29,0x94,0x08,0xB9,0x4E,0x79,0x8C,0x28,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xB5,0xA9,0xF0,0x60, + 0xC1,0xD6,0xC5,0x35,0xA2,0x01,0x7B,0xBD,0x0F,0x3D,0x19,0xFE,0xED,0x51,0xCA,0x2B, + 0xCE,0x3C,0xB2,0x0B,0xFF,0x33,0xD2,0x72,0x74,0x93,0xD1,0x93,0xB6,0xA3,0xCF,0x61, + 0x4B,0x18,0xA5,0x07,0x71,0xCF,0x9D,0xA9,0xDC,0x20,0xA5,0xD2,0x71,0x77,0x4A,0xAC, + 0x66,0x08,0x3D,0x6C,0x0E,0x6F,0x4E,0xFE,0x85,0x4F,0xF1,0xE2,0xFD,0x44,0x06,0xA2, + 0xA0,0x02,0xCA,0x33,0x09,0x40,0xBA,0xCE,0xD6,0xAB,0xBA,0x07,0x79,0x20,0x81,0x7A, + 0x12,0x89,0x19,0x82,0x5C,0xFB,0xDC,0x3F,0x8C,0x72,0x31,0x2D,0x08,0x1A,0x19,0x2F, + 0xF2,0x13,0x89,0x7A,0xF3,0xCD,0x93,0x29,0x1C,0x76,0xBF,0x7A,0xE1,0x94,0xE9,0xBF, + 0xF0,0xC7,0x8A,0x63,0xA9,0x90,0x0F,0xDA,0x2C,0x6B,0x49,0x14,0x8D,0xCC,0x30,0x40, + 0xEC,0xD3,0x6B,0x07,0x12,0x0E,0x63,0x21,0x79,0xD3,0x52,0x23,0xA9,0x2F,0xA9,0xA6, + 0x72,0x60,0x83,0x2F,0xED,0xB9,0xFC,0x77,0x2B,0xD8,0xAD,0x3C,0x6F,0x9B,0x67,0x48, + 0x69,0x35,0x26,0xF0,0xEA,0x9D,0x29,0xD6,0x96,0x68,0x53,0xA9,0xB7,0x87,0x5E,0xFE, + 0xCA,0x0D,0xAA,0x17,0x4C,0x8E,0x7C,0xEA,0x50,0x9E,0xB5,0xE2,0x92,0xC4,0x4B,0x8E, + 0x93,0x26,0x0F,0x65,0xCF,0x3A,0x65,0xB8,0x39,0x73,0xD7,0x6C,0x49,0x8C,0x94,0xD5, + 0x80,0x1F,0xE2,0xAD,0x16,0xF7,0xE9,0xCB,0xED,0x61,0xEB,0xD5,0xA2,0x69,0x3E,0xDD, + 0x17,0xF6,0x52,0x8A,0x33,0x7C,0x8A,0xDD,0x51,0x3F,0x15,0x09,0x96,0x0B,0x6C,0x79, + 0xC1,0xF3,0x86,0x30,0xB9,0xDB,0x5A,0x70,0x6B,0xE8,0x23,0xF2, +}; + #endif /* _TRUSTTESTS_EVALUATION_SSL_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.h b/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.h index 021a4a16..967d8b47 100644 --- a/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.h +++ b/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.h @@ -51,6 +51,12 @@ CF_RETURNS_RETAINED _Nullable SecCertificateRef SecFrameworkCertificateCreate(const uint8_t * der_bytes, CFIndex der_length); CF_RETURNS_RETAINED _Nullable SecCertificateRef SecFrameworkCertificateCreateFromTestCert(SecCertificateRef cert); +CF_RETURNS_RETAINED +SecPolicyRef SecFrameworkPolicyCreateSSL(Boolean server, CFStringRef __nullable hostname); +CF_RETURNS_RETAINED +SecPolicyRef SecFrameworkPolicyCreateBasicX509(void); +CF_RETURNS_RETAINED +SecPolicyRef SecFrameworkPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef __nullable email); NS_ASSUME_NONNULL_END diff --git a/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m b/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m index 712566e9..ff29a3ef 100644 --- a/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m +++ b/tests/TrustTests/EvaluationTests/TrustEvaluationTestCase.m @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include "OSX/utilities/SecCFWrappers.h" @@ -339,11 +340,13 @@ exit: @end -typedef SecCertificateRef (*create_f)(CFAllocatorRef allocator, +/* MARK: Framework type conversion functions */ + +typedef SecCertificateRef (*cert_create_f)(CFAllocatorRef allocator, const UInt8 *der_bytes, CFIndex der_length); CF_RETURNS_RETAINED _Nullable SecCertificateRef SecFrameworkCertificateCreate(const uint8_t * _Nonnull der_bytes, CFIndex der_length) { - static create_f FrameworkCertCreateFunctionPtr = NULL; + static cert_create_f FrameworkCertCreateFunctionPtr = NULL; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -364,3 +367,63 @@ SecCertificateRef SecFrameworkCertificateCreate(const uint8_t * _Nonnull der_byt SecCertificateRef SecFrameworkCertificateCreateFromTestCert(SecCertificateRef cert) { return SecFrameworkCertificateCreate(SecCertificateGetBytePtr(cert), SecCertificateGetLength(cert)); } + +typedef SecPolicyRef (*ssl_policy_create_f)(Boolean server, CFStringRef hostname); +SecPolicyRef SecFrameworkPolicyCreateSSL(Boolean server, CFStringRef __nullable hostname) { + static ssl_policy_create_f FrameworkPolicyCreateFunctionPtr = NULL; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + void *framework = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY); + if (framework) { + FrameworkPolicyCreateFunctionPtr = dlsym(framework, "SecPolicyCreateSSL"); + } + }); + + if (FrameworkPolicyCreateFunctionPtr) { + return FrameworkPolicyCreateFunctionPtr(server, hostname); + } else { + NSLog(@"WARNING: not using Security framework policy"); + return SecPolicyCreateSSL(server, hostname); + } +} + +typedef SecPolicyRef (*basic_policy_create_f)(void); +SecPolicyRef SecFrameworkPolicyCreateBasicX509(void) { + static basic_policy_create_f FrameworkPolicyCreateFunctionPtr = NULL; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + void *framework = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY); + if (framework) { + FrameworkPolicyCreateFunctionPtr = dlsym(framework, "SecPolicyCreateBasicX509"); + } + }); + + if (FrameworkPolicyCreateFunctionPtr) { + return FrameworkPolicyCreateFunctionPtr(); + } else { + NSLog(@"WARNING: not using Security framework policy"); + return SecPolicyCreateBasicX509(); + } +} + +typedef SecPolicyRef (*smime_policy_create_f)(CFIndex smimeUsage, CFStringRef email); +SecPolicyRef SecFrameworkPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email) { + static smime_policy_create_f FrameworkPolicyCreateFunctionPtr = NULL; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + void *framework = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY); + if (framework) { + FrameworkPolicyCreateFunctionPtr = dlsym(framework, "SecPolicyCreateSMIME"); + } + }); + + if (FrameworkPolicyCreateFunctionPtr) { + return FrameworkPolicyCreateFunctionPtr(smimeUsage, email); + } else { + NSLog(@"WARNING: not using Security framework policy"); + return SecPolicyCreateSMIME(smimeUsage, email); + } +} diff --git a/OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.m b/tests/TrustTests/EvaluationTests/TrustSettingsTests.m similarity index 77% rename from OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.m rename to tests/TrustTests/EvaluationTests/TrustSettingsTests.m index 3e24ded8..070093e5 100644 --- a/OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.m +++ b/tests/TrustTests/EvaluationTests/TrustSettingsTests.m @@ -23,13 +23,16 @@ #include #endif -#include "shared_regressions.h" +#include "../TestMacroConversions.h" +#include "TrustSettingsTests_data.h" +#import "TrustEvaluationTestCase.h" -#include "si-28-sectrustsettings.h" +@interface TrustSettingsTests : TrustEvaluationTestCase +@end + +/* bridgeOS doesn't support trust settings */ +#if !TARGET_OS_BRIDGE -/* Of course, the interface is different for OS X and iOS. */ -/* each call is 1 test */ -#define kNumberSetTSTests 1 #if TARGET_OS_IPHONE #define setTS(cert, settings) \ { \ @@ -38,11 +41,14 @@ } #else /* Use admin store on OS X to avoid user prompts. + * Need a framework cert since we're interacting with keychain and trust settings. * Sleep a little so trustd has time to get the KeychainEvent. */ #define setTS(cert, settings) \ { \ - ok_status(SecTrustSettingsSetTrustSettings(cert, kSecTrustSettingsDomainAdmin, \ + SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \ + ok_status(SecTrustSettingsSetTrustSettings(frameworkCert, kSecTrustSettingsDomainAdmin, \ settings), "set trust settings"); \ + CFReleaseNull(frameworkCert); \ usleep(20000); \ } #endif @@ -56,13 +62,13 @@ #else #define setTSFail(cert, settings) \ { \ - is(SecTrustSettingsSetTrustSettings(cert, kSecTrustSettingsDomainAdmin, \ + SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \ + is(SecTrustSettingsSetTrustSettings(frameworkCert, kSecTrustSettingsDomainAdmin, \ settings), errSecParam, "set trust settings"); \ + CFReleaseNull(frameworkCert); \ } #endif -/* each call is 1 test */ -#define kNumberRemoveTSTests 1 #if TARGET_OS_IPHONE #define removeTS(cert) \ { \ @@ -72,13 +78,13 @@ #else #define removeTS(cert) \ { \ + SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \ ok_status(SecTrustSettingsRemoveTrustSettings(cert, kSecTrustSettingsDomainAdmin), \ "remove trust settings"); \ + CFReleaseNull(frameworkCert); \ } #endif -/* each call is 4 tests */ -#define kNumberCheckTrustTests 4 #define check_trust(certs, policy, valid_date, expected) \ { \ SecTrustRef trust = NULL; \ @@ -87,7 +93,8 @@ "create trust with " #policy " policy"); \ ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)valid_date), \ "set trust verify date"); \ - ok_status(SecTrustEvaluate(trust, &trust_result), "evaluate trust"); \ + (void)SecTrustEvaluateWithError(trust, nil); \ + ok_status(SecTrustGetTrustResult(trust, &trust_result), "get trust result"); \ is(trust_result, expected, \ "check trust result for " #policy " policy"); \ CFReleaseSafe(trust); \ @@ -106,14 +113,18 @@ static NSDate *verify_date = nil; #if TARGET_OS_IPHONE static SecTrustStoreRef defaultStore = NULL; +#define sslFrameworkPolicy sslPolicy #else #define kSystemLoginKeychainPath "/Library/Keychains/System.keychain" static NSMutableArray *deleteMeCertificates = NULL; +static SecPolicyRef sslFrameworkPolicy = NULL; #endif +@implementation TrustSettingsTests -static void setup_globals(void) { - ++ (void)setUp +{ + [super setUp]; cert0 = SecCertificateCreateWithBytes(NULL, _trustSettingsRoot, sizeof(_trustSettingsRoot)); cert1 = SecCertificateCreateWithBytes(NULL, _trustSettingsInt, sizeof(_trustSettingsInt)); cert2 = SecCertificateCreateWithBytes(NULL, _trustSettingsSSLLeaf, sizeof(_trustSettingsSSLLeaf)); @@ -134,53 +145,66 @@ static void setup_globals(void) { #if TARGET_OS_IPHONE defaultStore = SecTrustStoreForDomain(kSecTrustStoreDomainUser); #else + /* We need a framework version of the policies in order to set policies in the trust settings */ + sslFrameworkPolicy = SecFrameworkPolicyCreateSSL(true, CFSTR("testserver.apple.com")); + /* Since we're putting trust settings in the admin domain, - * we need to add the certs to the system keychain. */ + * we need to add the certs to the system keychain. + * Need a framework cert since we're interacting with keychain. */ SecKeychainRef kcRef = NULL; CFArrayRef certRef = NULL; NSDictionary *attrs = nil; + SecCertificateRef frameworkCert = NULL; SecKeychainOpen(kSystemLoginKeychainPath, &kcRef); if (!kcRef) { - goto out; + return; } deleteMeCertificates = [[NSMutableArray alloc] init]; - attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert0, + frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert0); + attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert, (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef, (__bridge NSString*)kSecReturnPersistentRef: @YES}; if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0) [deleteMeCertificates addObject:(__bridge NSArray *)certRef]; CFReleaseNull(certRef); + CFReleaseNull(frameworkCert); - attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert1, + frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert1); + attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert, (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef, (__bridge NSString*)kSecReturnPersistentRef: @YES}; if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0) [deleteMeCertificates addObject:(__bridge NSArray *)certRef]; CFReleaseNull(certRef); + CFReleaseNull(frameworkCert); - attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert2, + frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert2); + attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert, (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef, (__bridge NSString*)kSecReturnPersistentRef: @YES}; if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0) [deleteMeCertificates addObject:(__bridge NSArray *)certRef]; CFReleaseNull(certRef); + CFReleaseNull(frameworkCert); - attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert3, + frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert3); + attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)frameworkCert, (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef, (__bridge NSString*)kSecReturnPersistentRef: @YES}; if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0) [deleteMeCertificates addObject:(__bridge NSArray *)certRef]; CFReleaseNull(certRef); + CFReleaseNull(frameworkCert); - out: CFReleaseNull(kcRef); #endif } -static void cleanup_globals(void) { ++ (void)tearDown +{ #if !TARGET_OS_IPHONE [deleteMeCertificates enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { SecItemDelete((CFDictionaryRef)@{ (__bridge NSString*)kSecValuePersistentRef: [obj objectAtIndex:0]}); @@ -192,14 +216,16 @@ static void cleanup_globals(void) { CFReleaseNull(cert2); CFReleaseNull(cert3); CFReleaseNull(sslPolicy); + CFReleaseNull(sslFrameworkPolicy); CFReleaseNull(smimePolicy); CFReleaseNull(basicPolicy); CFReleaseNull(sslChain); CFReleaseNull(smimeChain); + [super tearDown]; } -#define kNumberNoConstraintsTests (17+7*4) -static void test_no_constraints(void) { +- (void)test_no_constraints +{ /* root with the default TrustRoot result succeeds */ setTS(cert0, NULL); check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed); @@ -247,10 +273,10 @@ static void test_no_constraints(void) { removeTS(cert2); } -#define kNumberPolicyConstraintsTests (2+3*4) -static void test_policy_constraints(void) { +- (void)test_policy_constraints +{ /* Trust only for SSL server. SSL server policy succeeds. */ - NSDictionary *sslServerAllowed = @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + NSDictionary *sslServerAllowed = @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) }; setTS(cert1, (__bridge CFDictionaryRef)sslServerAllowed); check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed); @@ -265,12 +291,12 @@ static void test_policy_constraints(void) { removeTS(cert1); } -#define kNumberPolicyStringConstraintsTests (4+6*4) -static void test_policy_string_constraints(void) { - NSArray *hostnameAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, +- (void)test_policy_string_constraints +{ + NSArray *hostnameAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongname.apple.com"), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) }, - @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsPolicyString: @("testserver.apple.com"), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) } ]; @@ -289,10 +315,16 @@ static void test_policy_string_constraints(void) { CFReleaseNull(wrongnamePolicy); removeTS(cert2); - NSArray *emailAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimePolicy, +#if TARGET_OS_IPHONE + #define smimeFrameworkPolicy smimePolicy +#else + SecPolicyRef smimeFrameworkPolicy= SecFrameworkPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("username@apple.com")); +#endif + + NSArray *emailAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimeFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongemail@apple.com"), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) }, - @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimePolicy, + @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimeFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsPolicyString: @("username@apple.com"), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) } ]; @@ -310,21 +342,25 @@ static void test_policy_string_constraints(void) { check_trust(smimeChain, wrongemailPolicy, verify_date, kSecTrustResultDeny); CFReleaseNull(wrongemailPolicy); removeTS(cert3); + +#if TARGET_OS_OSX + CFReleaseNull(smimeFrameworkPolicy); +#endif } -#if TARGET_OS_IPHONE -#define kNumberApplicationsConstraintsTests 0 -static void test_application_constraints(void) {} -#else +#if TARGET_OS_OSX #include -#define kNumberApplicationsConstraintsTests (2+4+2*4) -static void test_application_constraints(void) { +- (void)test_application_constraints +{ SecTrustedApplicationRef thisApp = NULL, someOtherApp = NULL; - ok_status(SecTrustedApplicationCreateFromPath(NULL, &thisApp), + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + ok_status(SecTrustedApplicationCreateFromPath("/AppleInternal/CoreOS/tests/Security/TrustTests", &thisApp), "create TrustedApplicationRef for this app"); ok_status(SecTrustedApplicationCreateFromPath("/Applications/Safari.app", &someOtherApp), "create TrustedApplicationRef for Safari"); + #pragma clang diagnostic pop NSDictionary *thisAppTS = @{ (__bridge NSString*)kSecTrustSettingsApplication: (__bridge id)thisApp, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)}; @@ -345,10 +381,9 @@ static void test_application_constraints(void) { CFReleaseNull(thisApp); CFReleaseNull(someOtherApp); } -#endif +#endif // TARGET_OS_OSX -#define kNumberKeyUsageConstraintsTests (14+11*4) -static void test_key_usage_constraints(void) { +- (void)test_key_usage_constraints { /* any key usage succeeds */ NSDictionary *anyKeyUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseAny), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)}; @@ -423,8 +458,8 @@ static void test_key_usage_constraints(void) { CFReleaseNull(smimeMultiple); } -#define kNumberAllowedErrorsTests (14+8*4) -static void test_allowed_errors(void) { +- (void)test_allowed_errors +{ setTS(cert0, NULL); /* allow expired errors */ @@ -467,7 +502,7 @@ static void test_allowed_errors(void) { /* allowed error with a policy constraint */ NSDictionary *allowExpiredConstrained = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147409654), - (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)}; setTS(cert1, (__bridge CFDictionaryRef)allowExpiredConstrained) setTS(cert2, (__bridge CFDictionaryRef)allowExpiredConstrained); @@ -479,11 +514,11 @@ static void test_allowed_errors(void) { removeTS(cert0); } -#define kNumberMultipleConstraintsTests (8+9*4) -static void test_multiple_constraints(void) { +- (void)test_multiple_constraints +{ /* deny all but */ NSArray *denyAllBut = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy , + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy , (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)}, @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) } ]; @@ -494,7 +529,7 @@ static void test_multiple_constraints(void) { /* allow all but */ NSArray *allowAllBut = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy , + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy , (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)}, @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) } ]; @@ -503,11 +538,17 @@ static void test_multiple_constraints(void) { check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultRecoverableTrustFailure); removeTS(cert0); +#if TARGET_OS_IPHONE +#define basicFrameworkPolicy basicPolicy +#else + SecPolicyRef basicFrameworkPolicy = SecFrameworkPolicyCreateBasicX509(); +#endif + /* different results for specific policies */ NSArray *specifyPolicyResult = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)}, - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)basicPolicy, + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)basicFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) } ]; setTS(cert0, (__bridge CFArrayRef)specifyPolicyResult); @@ -518,11 +559,11 @@ static void test_multiple_constraints(void) { /* different results for additional constraint with same policy */ NSArray *policyConstraintResult = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongname.apple.com"), (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147408896), (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)}, - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy, + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy, (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) } ]; SecPolicyRef wrongNameSSL = NULL; @@ -534,13 +575,16 @@ static void test_multiple_constraints(void) { removeTS(cert2); CFReleaseNull(wrongNameSSL); +#if TARGET_OS_OSX + CFReleaseNull(basicFrameworkPolicy); +#endif } -#define kNumberChangeConstraintsTests (2*kNumberSetTSTests + kNumberRemoveTSTests + 4*kNumberCheckTrustTests) -static void test_change_constraints(void) { +- (void)test_change_constraints +{ /* allow all but */ NSArray *allowAllBut = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy , + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy , (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)}, @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) } ]; @@ -557,62 +601,89 @@ static void test_change_constraints(void) { removeTS(cert0); } -#define kNumberPolicyNamePinnningConstraintsTests (kNumberSetTSTests + kNumberRemoveTSTests + 5) -static void test_policy_name_pinning_constraints(void) { +- (void)test_policy_name_pinning_constraints +{ + /* need a new policy object for this test so we don't mess up the policy used by the other tests */ + SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com")); +#if TARGET_OS_IPHONE +#define frameworkPolicy policy +#else + SecPolicyRef frameworkPolicy = SecFrameworkPolicyCreateSSL(true, CFSTR("testserver.apple.com")); +#endif + /* allow all but */ NSArray *allowAllBut = @[ - @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy , + @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)frameworkPolicy , (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)}, @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) } ]; setTS(cert0, (__bridge CFArrayRef)allowAllBut); SecTrustRef trust = NULL; - SecTrustResultType trust_result; - ok_status(SecTrustCreateWithCertificates(sslChain, sslPolicy, &trust), "create trust with ssl policy"); + ok_status(SecTrustCreateWithCertificates(sslChain, policy, &trust), "create trust with ssl policy"); ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)verify_date), "set trust verify date"); ok_status(SecTrustSetPinningPolicyName(trust, CFSTR("not-a-db-policy-name")), "set policy name"); - ok_status(SecTrustEvaluate(trust, &trust_result), "evaluate trust"); - is(trust_result, kSecTrustResultRecoverableTrustFailure, "check trust result for sslServer policy with policy name"); + XCTAssertFalse(SecTrustEvaluateWithError(trust, nil), "evaluate trust"); CFReleaseSafe(trust); + CFReleaseNull(policy); + CFReleaseNull(frameworkPolicy); removeTS(cert0); } -int si_28_sectrustsettings(int argc, char *const *argv) +- (void)testDistrustSystemRoot { - plan_tests(kNumberNoConstraintsTests - + kNumberPolicyConstraintsTests - + kNumberPolicyStringConstraintsTests - + kNumberApplicationsConstraintsTests - + kNumberKeyUsageConstraintsTests - + kNumberAllowedErrorsTests - + kNumberMultipleConstraintsTests - + kNumberChangeConstraintsTests - + kNumberPolicyNamePinnningConstraintsTests - ); + // Users can distrust system roots + id systemRoot = [self SecCertificateCreateFromResource:@"DigiCertGlobalRootG3" subdirectory:@"si-20-sectrust-policies-data"]; + NSDictionary *deny = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)}; + id persistentRef = [self addTrustSettingsForCert:(__bridge SecCertificateRef)systemRoot trustSettings:deny]; + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[systemRoot] policies:nil]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; // January 6, 2020 at 2:40:00 AM PST + XCTAssertFalse([eval evaluate:nil]); + XCTAssertEqual(eval.trustResult, kSecTrustResultDeny); + [self removeTrustSettingsForCert:(__bridge SecCertificateRef)systemRoot persistentRef:persistentRef]; +} -#if !TARGET_OS_IPHONE - if (getuid() != 0) { - printf("Test must be run as root on OS X"); - return 0; - } -#endif +- (void)testDistrustAppleRoot +{ + // Users cannot distrust the Apple Roots + id appleRoot = [self SecCertificateCreateFromResource:@"AppleRootCA" subdirectory:@"si-20-sectrust-policies-data"]; + NSDictionary *deny = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)}; + id persistentRef = [self addTrustSettingsForCert:(__bridge SecCertificateRef)appleRoot trustSettings:deny]; + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[appleRoot] policies:nil]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:600000000.0]]; // January 6, 2020 at 2:40:00 AM PST + XCTAssert([eval evaluate:nil]); + XCTAssertEqual(eval.trustResult, kSecTrustResultProceed); + [self removeTrustSettingsForCert:(__bridge SecCertificateRef)appleRoot persistentRef:persistentRef]; +} - @autoreleasepool { - setup_globals(); - test_no_constraints(); - test_policy_constraints(); - test_policy_string_constraints(); - test_application_constraints(); - test_key_usage_constraints(); - test_allowed_errors(); - test_multiple_constraints(); - test_change_constraints(); - test_policy_name_pinning_constraints(); - cleanup_globals(); - } +- (void)testFatalResultsNonOverride +{ + id root = [self SecCertificateCreateFromPEMResource:@"ca-ki" subdirectory:@"si-88-sectrust-valid-data"]; + id revokedLeaf = [self SecCertificateCreateFromPEMResource:@"leaf-ki-revoked1" subdirectory:@"si-88-sectrust-valid-data"]; + TestTrustEvaluation *eval = [[TestTrustEvaluation alloc] initWithCertificates:@[revokedLeaf, root] policies:nil]; + [eval setVerifyDate:[NSDate dateWithTimeIntervalSinceReferenceDate:542400000.0]]; // March 10, 2018 at 10:40:00 AM PST + [eval setAnchors:@[root]]; + XCTAssertFalse([eval evaluate:nil]); + XCTAssertEqual(eval.trustResult, kSecTrustResultFatalTrustFailure); + + /* still fatal failure if trust settings on root */ + id persistentRef = [self addTrustSettingsForCert:(__bridge SecCertificateRef)root]; + [eval setNeedsEvaluation]; + XCTAssertFalse([eval evaluate:nil]); + XCTAssertEqual(eval.trustResult, kSecTrustResultFatalTrustFailure); + [self removeTrustSettingsForCert:(__bridge SecCertificateRef)root persistentRef:persistentRef]; +} + +@end - return 0; +#else // TARGET_OS_BRIDGE +@implementation TrustSettingsTests +- (void)testSkipTests +{ + XCTAssert(true); } +@end + +#endif diff --git a/OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.h b/tests/TrustTests/EvaluationTests/TrustSettingsTests_data.h similarity index 99% rename from OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.h rename to tests/TrustTests/EvaluationTests/TrustSettingsTests_data.h index e379eb34..19d7ad82 100644 --- a/OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.h +++ b/tests/TrustTests/EvaluationTests/TrustSettingsTests_data.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2016 Apple Inc. All Rights Reserved. + * Copyright (c) 2016-2019 Apple Inc. All Rights Reserved. */ -#ifndef si_28_sectrustsettings_h -#define si_28_sectrustsettings_h +#ifndef _TRUSTTESTS_EVALUATION_TRUST_SETTINGS_TESTS_H_ +#define _TRUSTTESTS_EVALUATION_TRUST_SETTINGS_TESTS_H_ /* subject:/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Root CA */ /* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Root CA */ @@ -525,4 +525,4 @@ uint8_t _corporateServerCert[] = { 0x05,0x15,0xA6,0xD5,0x1E,0x23,0xB7,0xC2, }; -#endif /* si_28_sectrustsettings_h */ +#endif /* _TRUSTTESTS_EVALUATION_TRUST_SETTINGS_TESTS_H_ */ diff --git a/tests/TrustTests/EvaluationTests/ValidTests.m b/tests/TrustTests/EvaluationTests/ValidTests.m new file mode 100644 index 00000000..016b53ff --- /dev/null +++ b/tests/TrustTests/EvaluationTests/ValidTests.m @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2017-2019 Apple Inc. All Rights Reserved. + * + */ + +#import +#import + +#include +#include +#include +#include +#include +#include "trust/trustd/OTATrustUtilities.h" + +#import "../TestMacroConversions.h" +#import "TrustEvaluationTestCase.h" + +enum { + kBasicPolicy = 0, + kSSLServerPolicy = 1, +}; + +@interface ValidTests : TrustEvaluationTestCase +@end + +@implementation ValidTests + +#if !TARGET_OS_BRIDGE +- (void) run_valid_trust_test:(SecCertificateRef)leaf + ca:(SecCertificateRef)ca + subca:(SecCertificateRef)subca + anchors:(CFArrayRef)anchors + date:(CFDateRef)date + policyID:(CFIndex)policyID + expected:(SecTrustResultType)expected + test_name:(const char *)test_name +{ + CFArrayRef policies=NULL; + SecPolicyRef policy=NULL; + SecTrustRef trust=NULL; + SecTrustResultType trustResult; + CFMutableArrayRef certs=NULL; + + printf("Starting %s\n", test_name); + isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array"); + if (certs) { + if (leaf) { + CFArrayAppendValue(certs, leaf); + } + if (ca) { + CFArrayAppendValue(certs, ca); + } + if (subca) { + CFArrayAppendValue(certs, subca); + } + } + + if (policyID == kSSLServerPolicy) { + isnt(policy = SecPolicyCreateSSL(true, NULL), NULL, "create ssl policy"); + } else { + isnt(policy = SecPolicyCreateBasicX509(), NULL, "create basic policy"); + } + isnt(policies = CFArrayCreate(kCFAllocatorDefault, (const void **)&policy, 1, &kCFTypeArrayCallBacks), NULL, "create policies"); + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust"); + + assert(trust); // silence analyzer + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "evaluate trust"); + ok(trustResult == expected, "trustResult %d expected (got %d) for %s", + (int)expected, (int)trustResult, test_name); + + CFReleaseSafe(certs); + CFReleaseSafe(policy); + CFReleaseSafe(policies); + CFReleaseSafe(trust); +} + +- (SecCertificateRef) CF_RETURNS_RETAINED createCertFromResource:(NSString *)name +{ + id cert = [self SecCertificateCreateFromPEMResource:name subdirectory:@"si-88-sectrust-valid-data"]; + return (__bridge SecCertificateRef)cert; +} + +- (void)test_date_constraints +{ + SecCertificateRef ca_na=NULL, ca_nb=NULL, root=NULL; + SecCertificateRef leaf_na_ok1=NULL, leaf_na_ok2=NULL; + SecCertificateRef leaf_nb_ok1=NULL, leaf_nb_ok2=NULL, leaf_nb_revoked1=NULL; + + isnt(ca_na = [self createCertFromResource:@"ca-na"], NULL, "create ca-na cert"); + isnt(ca_nb = [self createCertFromResource:@"ca-nb"], NULL, "create ca-nb cert"); + isnt(root = [self createCertFromResource:@"root"], NULL, "create root cert"); + isnt(leaf_na_ok1 = [self createCertFromResource:@"leaf-na-ok1"], NULL, "create leaf-na-ok1 cert"); + isnt(leaf_na_ok2 = [self createCertFromResource:@"leaf-na-ok2"], NULL, "create leaf-na-ok2 cert"); + isnt(leaf_nb_ok1 = [self createCertFromResource:@"leaf-nb-ok1"], NULL, "create leaf-nb-ok1 cert"); + isnt(leaf_nb_ok2 = [self createCertFromResource:@"leaf-nb-ok2"], NULL, "create leaf-nb-ok2 cert"); + isnt(leaf_nb_revoked1 = [self createCertFromResource:@"leaf-nb-revoked1"], NULL, "create leaf-nb-revoked1 cert"); + + CFMutableArrayRef anchors=NULL; + isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array"); + if (anchors && root) { + CFArrayAppendValue(anchors, root); + } + CFCalendarRef cal = NULL; + CFAbsoluteTime at; + CFDateRef date_20180102 = NULL; // a date when our test certs would all be valid, in the absence of Valid db info + + isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar"); + ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2018, 1, 2), "create verify absolute time 20180102"); + isnt(date_20180102 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20180102"); + + /* Case 0: leaf_na_ok1 (not revoked) */ + /* -- OK: cert issued 2017-10-20, before the CA not-after date of 2017-10-21 */ + /* test cert has no SCT, but is expected to be OK since we now only apply the CT restriction for SSL. */ + [self run_valid_trust_test:leaf_na_ok1 ca:ca_na subca:NULL anchors:anchors date:date_20180102 + policyID:kBasicPolicy expected:kSecTrustResultUnspecified + test_name:"leaf_na_ok1 basic"]; + + /* Case 1: leaf_na_ok1 (not revoked) */ + /* -- BAD: since a not-after date now requires CT (for SSL) and the test cert has no SCT, this is fatal. */ + /* Mock a successful mobile asset check-in so that we enforce CT */ + XCTAssertTrue(UpdateOTACheckInDate(), "failed to set check-in date as now"); + [self run_valid_trust_test:leaf_na_ok1 ca:ca_na subca:NULL anchors:anchors date:date_20180102 + policyID:kSSLServerPolicy expected:kSecTrustResultFatalTrustFailure + test_name:"leaf_na_ok1 ssl"]; + + /* Case 2: leaf_na_ok2 (revoked) */ + /* -- BAD: cert issued 2017-10-26, after the CA not-after date of 2017-10-21 */ + [self run_valid_trust_test:leaf_na_ok2 ca:ca_na subca:NULL anchors:anchors date:date_20180102 + policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure + test_name:"leaf_na_ok2 basic"]; + + /* Case 3: leaf_nb_ok1 (revoked) */ + /* -- BAD: cert issued 2017-10-20, before the CA not-before date of 2017-10-22 */ + [self run_valid_trust_test:leaf_nb_ok1 ca:ca_nb subca:NULL anchors:anchors date:date_20180102 + policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure + test_name:"leaf_nb_ok1 basic"]; + + /* Case 4: leaf_nb_ok2 (not revoked) */ + /* -- OK: cert issued 2017-10-26, after the CA not-before date of 2017-10-22 */ + [self run_valid_trust_test:leaf_nb_ok2 ca:ca_nb subca:NULL anchors:anchors date:date_20180102 + policyID:kBasicPolicy expected:kSecTrustResultUnspecified + test_name:"leaf_nb_ok2 basic"]; + + /* Case 5: leaf_nb_revoked1 (revoked) */ + /* -- BAD: cert issued 2017-10-20, before the CA not-before date of 2017-10-22 */ + [self run_valid_trust_test:leaf_nb_revoked1 ca:ca_nb subca:NULL anchors:anchors date:date_20180102 + policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure + test_name:"leaf_nb_revoked1 basic"]; + + CFReleaseSafe(ca_na); + CFReleaseSafe(ca_nb); + CFReleaseSafe(leaf_na_ok1); + CFReleaseSafe(leaf_na_ok2); + CFReleaseSafe(leaf_nb_ok1); + CFReleaseSafe(leaf_nb_ok2); + CFReleaseSafe(leaf_nb_revoked1); + CFReleaseSafe(root); + CFReleaseSafe(anchors); + CFReleaseSafe(cal); + CFReleaseSafe(date_20180102); +} + +- (void)test_known_intermediate +{ + SecCertificateRef ca_ki=NULL, root=NULL; + SecCertificateRef leaf_ki_ok1=NULL, leaf_ki_revoked1=NULL; + SecCertificateRef leaf_unknown=NULL, ca_unknown=NULL; + + isnt(ca_ki = [self createCertFromResource:@"ca-ki"], NULL, "create ca-ki cert"); + isnt(root = [self createCertFromResource:@"root"], NULL, "create root cert"); + isnt(leaf_ki_ok1 = [self createCertFromResource:@"leaf-ki-ok1"], NULL, "create leaf-ki-ok1 cert"); + isnt(leaf_ki_revoked1 = [self createCertFromResource:@"leaf-ki-revoked1"], NULL, "create leaf-ki-revoked1 cert"); + isnt(ca_unknown = [self createCertFromResource:@"ca-unknown"], NULL, "create ca-unknown cert"); + isnt(leaf_unknown = [self createCertFromResource:@"leaf-unknown"], NULL, "create leaf-unknown cert"); + + CFMutableArrayRef anchors=NULL; + isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array"); + if (anchors && root) { + CFArrayAppendValue(anchors, root); + } + CFCalendarRef cal = NULL; + CFAbsoluteTime at; + CFDateRef date_20180310 = NULL; // a date when our test certs would all be valid, in the absence of Valid db info + + isnt(cal = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar), NULL, "create calendar"); + ok(CFCalendarComposeAbsoluteTime(cal, &at, "yMd", 2018, 3, 10), "create verify absolute time 20180310"); + isnt(date_20180310 = CFDateCreate(kCFAllocatorDefault, at), NULL, "create verify date 20180310"); + + /* Case 1: leaf_ki_ok1 */ + /* -- OK: cert issued by a known intermediate */ + [self run_valid_trust_test:leaf_ki_ok1 ca:ca_ki subca:NULL anchors:anchors date:date_20180310 policyID:kBasicPolicy expected:kSecTrustResultUnspecified test_name:"leaf_ki_ok1"]; + + /* Case 2: leaf_ki_revoked1 */ + /* -- BAD: CA specifies known-only+complete serial blocklist; this cert is on the blocklist. */ + [self run_valid_trust_test:leaf_ki_revoked1 ca:ca_ki subca:NULL anchors:anchors date:date_20180310 policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure test_name:"leaf_ki_revoked"]; + + /* Case 3: leaf_unknown */ + /* -- BAD: ca_unknown issued from ca_ki, but is not a known intermediate. + * ca_ki has a path len of 0 which would normally result in kSecTrustResultRecoverableTrustFailure; + * however, since known-intermediates is asserted for ca_ki (non-overridable), we expect a fatal failure. */ + [self run_valid_trust_test:leaf_unknown ca:ca_unknown subca:ca_ki anchors:anchors date:date_20180310 policyID:kBasicPolicy expected:kSecTrustResultFatalTrustFailure test_name:"leaf_unknown test"]; + + CFReleaseSafe(ca_ki); + CFReleaseSafe(leaf_ki_ok1); + CFReleaseSafe(leaf_ki_revoked1); + CFReleaseSafe(ca_unknown); + CFReleaseSafe(leaf_unknown); + CFReleaseSafe(root); + CFReleaseSafe(anchors); + CFReleaseSafe(cal); + CFReleaseSafe(date_20180310); +} +#else /* TARGET_OS_BRIDGE */ +/* Valid is not supported on bridgeOS */ +- (void)testSkipTests +{ + XCTAssert(true); +} +#endif + +@end diff --git a/tests/TrustTests/EvaluationTests/VerifyDateTests.m b/tests/TrustTests/EvaluationTests/VerifyDateTests.m index d102547e..b980d64a 100644 --- a/tests/TrustTests/EvaluationTests/VerifyDateTests.m +++ b/tests/TrustTests/EvaluationTests/VerifyDateTests.m @@ -102,10 +102,10 @@ static SecTrustRef trust = nil; @implementation ValidityPeriodRestrictionTests // Note that the dates described in the test names are the issuance date not the VerifyDate -- (BOOL)runTrustEvaluation:(NSArray *)certs anchors:(NSArray *)anchors error:(NSError **)error +- (BOOL)runTrustEvaluation:(NSArray *)certs anchors:(NSArray *)anchors verifyTime:(NSTimeInterval)time error:(NSError **)error { SecPolicyRef policy = SecPolicyCreateSSL(true, CFSTR("example.com")); - NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:590000000.0]; // September 12, 2019 at 9:53:20 AM PDT + NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:time]; SecTrustRef trustRef = NULL; BOOL result = NO; CFErrorRef cferror = NULL; @@ -129,6 +129,11 @@ errOut: return result; } +- (BOOL)runTrustEvaluation:(NSArray *)certs anchors:(NSArray *)anchors error:(NSError **)error +{ + return [self runTrustEvaluation:certs anchors:anchors verifyTime:590000000.0 error:error]; // September 12, 2019 at 9:53:20 AM PDT +} + - (void)testSystemTrust_MoreThan5Years { [self setTestRootAsSystem:_testValidityPeriodsRootHash]; @@ -220,6 +225,42 @@ errOut: CFReleaseNull(leaf); } +- (void)testSystemTrust_MoreThan398Days_AfterSep2020 +{ + [self setTestRootAsSystem:_testValidityPeriodsRootHash]; + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _testValidityPeriodsRoot, sizeof(_testValidityPeriodsRoot)); + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _testLeaf_2Years, sizeof(_testLeaf_2Years)); + + NSError *error = nil; + XCTAssertFalse([self runTrustEvaluation:@[(__bridge id)leaf] + anchors:@[(__bridge id)root] + verifyTime:621000000.0 // September 5, 2020 at 5:00:00 AM PDT + error:&error], + "system-trusted 2 year cert issued after 1 Sept 2020 failed: %@", error); + + [self removeTestRootAsSystem]; + CFReleaseNull(root); + CFReleaseNull(leaf); +} + +- (void)testSystemTrust_398Days_AfterSep2020 +{ + [self setTestRootAsSystem:_testValidityPeriodsRootHash]; + SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _testValidityPeriodsRoot, sizeof(_testValidityPeriodsRoot)); + SecCertificateRef leaf = SecCertificateCreateWithBytes(NULL, _testLeaf_398Days, sizeof(_testLeaf_398Days)); + + NSError *error = nil; + XCTAssertTrue([self runTrustEvaluation:@[(__bridge id)leaf] + anchors:@[(__bridge id)root] + verifyTime:621000000.0 // September 5, 2020 at 5:00:00 AM PDT + error:&error], + "system-trusted 398 day cert issued after 1 Sept 2020 failed: %@", error); + + [self removeTestRootAsSystem]; + CFReleaseNull(root); + CFReleaseNull(leaf); +} + - (void)testAppTrustRoot_MoreThan825Days_AfterJul2019 { SecCertificateRef root = SecCertificateCreateWithBytes(NULL, _testValidityPeriodsRoot, sizeof(_testValidityPeriodsRoot)); diff --git a/tests/TrustTests/EvaluationTests/VerifyDateTests_data.h b/tests/TrustTests/EvaluationTests/VerifyDateTests_data.h index 3948974f..a03e8a08 100644 --- a/tests/TrustTests/EvaluationTests/VerifyDateTests_data.h +++ b/tests/TrustTests/EvaluationTests/VerifyDateTests_data.h @@ -825,4 +825,191 @@ const uint8_t _testLeaf_825Days[] = { 0x2B,0x61,0x37,0x1B,0x25,0xFF,0xC6,0x02,0x2F,0x83,0xEE,0xF3,0x27,0x00,0xE9,0x73, 0xC8,0xDC,0x49,0xDE,0x0B,0x80,0x4B,0x17,0x17,0x7B,0x13,0x79,0x56, }; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Validity Period Maximums 2 Year Leaf */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Validity Period Maximums Test Root */ +/* Not Before: Sep 1 00:05:55 2020 GMT + Not After : Sep 1 00:05:55 2022 GMT */ +const uint8_t _testLeaf_2Years[] = { + 0x30,0x82,0x05,0x58,0x30,0x82,0x03,0x40,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x4B, + 0x8D,0xD7,0x1D,0x8B,0x58,0x14,0x25,0xFD,0x5A,0xF1,0xBF,0xD9,0xA3,0x44,0x41,0x38, + 0xBA,0xF1,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x30,0x81,0x97,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C, + 0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, + 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x2B, + 0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x0C,0x22,0x56,0x61,0x6C,0x69,0x64,0x69,0x74, + 0x79,0x20,0x50,0x65,0x72,0x69,0x6F,0x64,0x20,0x4D,0x61,0x78,0x69,0x6D,0x75,0x6D, + 0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x30,0x1E,0x17,0x0D,0x32, + 0x30,0x30,0x39,0x30,0x31,0x30,0x30,0x30,0x35,0x35,0x35,0x5A,0x17,0x0D,0x32,0x32, + 0x30,0x39,0x30,0x31,0x30,0x30,0x30,0x35,0x35,0x35,0x5A,0x30,0x81,0x99,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, + 0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72, + 0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55, + 0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67, + 0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x24,0x56,0x61,0x6C,0x69,0x64,0x69,0x74,0x79,0x20,0x50,0x65,0x72,0x69, + 0x6F,0x64,0x20,0x4D,0x61,0x78,0x69,0x6D,0x75,0x6D,0x73,0x20,0x32,0x20,0x59,0x65, + 0x61,0x72,0x20,0x4C,0x65,0x61,0x66,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,0xC8,0xF2,0x3C,0xD6,0x71,0xC6,0xD7,0x8A, + 0xC1,0xC9,0xC4,0x99,0xD6,0x51,0x52,0x64,0xCB,0x8A,0x92,0x48,0x7C,0x83,0x15,0x82, + 0xE3,0x35,0x9E,0x2C,0x43,0xC3,0x38,0x7F,0xC0,0xF1,0xC9,0x44,0xC0,0x9D,0x52,0x3B, + 0x4A,0x0F,0x8A,0xD3,0x8E,0xA9,0xE9,0xA1,0x5D,0x93,0xA7,0xB3,0xD0,0x20,0x9C,0x53, + 0x62,0xE5,0x8D,0xBF,0xD8,0x3C,0x33,0x49,0x2C,0x82,0x65,0xF5,0x48,0xAA,0xF3,0xD7, + 0x8F,0x23,0x4B,0x3F,0x89,0xC3,0x8E,0xD2,0xAB,0xF6,0xFA,0x56,0x51,0xD2,0x42,0xBD, + 0x88,0x9D,0x43,0x75,0xE4,0xE8,0x6D,0xB7,0xF3,0xD1,0xEC,0x9F,0xD8,0xAB,0x23,0xEC, + 0xFC,0x5F,0x87,0xCB,0xB8,0xC4,0xD5,0xE5,0xDD,0x2B,0x79,0x53,0xCF,0x43,0x2A,0x57, + 0x10,0x19,0xA5,0x57,0x92,0x9A,0xD0,0xB7,0xF0,0xE8,0x7C,0xAA,0xCB,0xF1,0xB8,0xC3, + 0xC0,0x53,0x5C,0xDE,0x5D,0xB0,0x47,0x38,0xC2,0x81,0xE5,0xD3,0x39,0x84,0xB5,0x64, + 0xB0,0x59,0xE7,0x7C,0xEB,0x92,0x5B,0xB1,0xF9,0x82,0x95,0x45,0x14,0x5D,0x17,0x5C, + 0x4F,0x49,0x54,0x36,0xF0,0xCB,0xF5,0x7E,0x3E,0xAF,0x14,0x00,0x06,0x73,0x77,0x59, + 0xD7,0xB4,0xA8,0x49,0xCE,0x7C,0x55,0x1C,0xC4,0x79,0x6E,0x0D,0xD1,0x04,0xF0,0x2E, + 0xC5,0xF3,0x8A,0xA7,0xC5,0x9F,0xB0,0xED,0x3D,0x13,0x80,0x94,0x1E,0xDC,0xF3,0x81, + 0x97,0x52,0x4F,0x62,0x83,0xD6,0x02,0xFB,0x9B,0x03,0xE1,0x29,0xD0,0x7D,0x18,0x4B, + 0xDB,0xEE,0x69,0xF4,0xC7,0x98,0xA1,0xBB,0x62,0xCE,0xD2,0x7B,0x2E,0x0F,0xD5,0x06, + 0xE8,0x5E,0x47,0x00,0x20,0x00,0xC5,0x11,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x98, + 0x30,0x81,0x95,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, + 0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02, + 0x30,0x16,0x06,0x03,0x55,0x1D,0x11,0x04,0x0F,0x30,0x0D,0x82,0x0B,0x65,0x78,0x61, + 0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04, + 0x16,0x04,0x14,0xD3,0x39,0x1B,0x96,0x50,0xE7,0x23,0x59,0x7C,0x88,0xF9,0x64,0x2B, + 0xF9,0x60,0x70,0x72,0xE7,0x78,0xE6,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18, + 0x30,0x16,0x80,0x14,0xDE,0xEB,0xFD,0x98,0xFD,0xCA,0x44,0xC1,0xFA,0xB7,0xF9,0x2B, + 0xF5,0x96,0x67,0x08,0x11,0x35,0x27,0x75,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x02,0x01,0x00,0x37,0x45,0x43,0xE5, + 0x3A,0x7C,0xFC,0xFF,0x49,0xE2,0xC6,0x70,0xD8,0xB6,0x51,0x7D,0x61,0x6D,0x1A,0x87, + 0x5F,0x86,0x2B,0xE4,0xFF,0x30,0x5B,0xBB,0xD5,0x2D,0x4B,0x95,0x9C,0x7B,0xDA,0x57, + 0xC8,0xA7,0x12,0x12,0x55,0x48,0x16,0x04,0xBD,0xE2,0x2A,0xC1,0xE0,0x34,0x0D,0xC3, + 0x18,0x25,0xD1,0xA7,0x1E,0x74,0xF6,0x0A,0xB0,0x70,0x41,0xF3,0x80,0xDA,0xBC,0xF0, + 0xE3,0x84,0x5E,0x8A,0xFA,0x9C,0x2E,0x00,0x41,0x1B,0xB6,0x1D,0x82,0x3D,0x40,0xF4, + 0x00,0xF1,0x88,0xCC,0x00,0x06,0xFC,0x61,0x94,0x93,0x55,0xD2,0x21,0x9B,0x3D,0xFE, + 0xF7,0x82,0xE6,0x86,0xF6,0x39,0x4E,0xFA,0x3C,0x37,0x4E,0x25,0x7F,0x0A,0x5E,0x05, + 0x43,0x4D,0x4E,0x22,0xED,0xB0,0xAA,0xAC,0x81,0x29,0xD4,0x6C,0xE1,0x21,0x2D,0x8E, + 0x21,0x29,0x8A,0x44,0x29,0xD6,0x95,0x55,0x75,0x74,0x66,0xAB,0xC7,0xF2,0xC3,0xA6, + 0x9B,0xE5,0x55,0x80,0x84,0xB5,0x9F,0x0C,0x2F,0x89,0x8E,0x35,0x26,0xDC,0x0C,0xA0, + 0x72,0x1F,0xC2,0xCA,0x04,0x15,0x4D,0x4F,0xC6,0x01,0x25,0xDF,0xB4,0x76,0x8B,0x0F, + 0xF0,0xC3,0xE0,0x76,0x02,0x01,0x6B,0x84,0x9D,0xC2,0xE3,0x3B,0x7A,0x9F,0x54,0x0E, + 0xA0,0x0A,0x2A,0xC5,0x72,0x66,0x94,0x88,0x55,0xEC,0xCA,0x69,0x44,0x05,0x00,0x6C, + 0x03,0xF6,0xCB,0x73,0xD5,0xE9,0xAE,0xE0,0x85,0x92,0x39,0x62,0xEB,0xDB,0xCC,0xDD, + 0x89,0x82,0x07,0xA1,0xAB,0x60,0x97,0x4D,0x7A,0xC4,0xA1,0xA1,0x47,0xCA,0xA7,0xCC, + 0xB5,0xE7,0xB4,0xB6,0x01,0x38,0xF9,0x4C,0x2F,0xC2,0xC1,0x44,0xC6,0xAF,0x5C,0xDD, + 0x82,0xD8,0x8D,0xEE,0x42,0x8D,0xB5,0xE8,0x58,0x73,0x0E,0x0A,0xFC,0x0C,0xCC,0x35, + 0xFE,0x5E,0x09,0x12,0x70,0xD0,0xA5,0xD2,0x38,0x27,0xBB,0xD0,0xA0,0xF6,0x61,0x44, + 0xEA,0x2D,0xCE,0x54,0xEB,0xA4,0x57,0x52,0xF4,0x81,0xE2,0xFD,0x7B,0x0D,0x08,0x53, + 0xD4,0x0D,0x6E,0x8B,0x4F,0xA2,0xD4,0xCF,0xBF,0x01,0xB4,0x0B,0x34,0x37,0xEE,0x89, + 0x81,0xBD,0x36,0x87,0x39,0x5D,0x2D,0xE0,0x0E,0x19,0x28,0x26,0xDC,0x80,0xDB,0x22, + 0x49,0x4B,0x5E,0xAF,0x17,0xB8,0x83,0xC5,0x32,0x66,0xF3,0x81,0x01,0x36,0x95,0xC5, + 0xF2,0x49,0x81,0xDC,0xD8,0x07,0xF7,0x01,0xEE,0x8D,0x0F,0xDD,0x6A,0xDE,0x9E,0xDD, + 0x5D,0x98,0x82,0xCD,0x2C,0x2B,0x02,0xD4,0xEC,0x55,0x9F,0x95,0x63,0x4C,0x2B,0x58, + 0x16,0x8B,0x52,0x24,0x98,0x51,0x7C,0x0D,0xA9,0x47,0xE9,0xAA,0x70,0x94,0xC7,0xC1, + 0x41,0x55,0x44,0x71,0x55,0x1D,0x05,0x4C,0xF3,0xCE,0xEB,0x40,0x4A,0xED,0x40,0x3D, + 0xD1,0xAD,0x8A,0xF7,0xBF,0x0E,0x30,0xE0,0x20,0x60,0x64,0x0A,0xEB,0x9C,0x89,0x60, + 0xC8,0x8D,0xF3,0x3A,0xE4,0x76,0x50,0xE2,0x2B,0x92,0xB1,0x0D,0xCD,0x66,0xCC,0x48, + 0x16,0x84,0x26,0x54,0xF4,0x9F,0x0F,0x1C,0xC6,0x53,0x37,0xC9,0x11,0x18,0xAE,0x41, + 0xED,0xE4,0x17,0xBE,0x5D,0x54,0xF1,0x9E,0x10,0x34,0x5E,0x28,0x32,0x65,0xB2,0x46, + 0x25,0x63,0x5E,0x43,0xCB,0x6D,0x5E,0xEA,0xAC,0x4A,0x50,0x75,0x7E,0x6C,0x61,0xF4, + 0xE6,0x5B,0xB6,0x7B,0xF6,0x6B,0xAD,0x96,0xD7,0xF3,0xF8,0x44, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Validity Period Maximums 398 Day Leaf */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=Security Engineering/CN=Validity Period Maximums Test Root */ +/* Not Before: Sep 1 00:06:20 2020 GMT + Not After : Oct 4 00:06:20 2021 GMT */ +const uint8_t _testLeaf_398Days[] = { + 0x30,0x82,0x05,0x59,0x30,0x82,0x03,0x41,0xA0,0x03,0x02,0x01,0x02,0x02,0x13,0x4B, + 0x8D,0xD7,0x1D,0x8B,0x58,0x14,0x25,0xFD,0x5A,0xF1,0xBF,0xD9,0xA3,0x44,0x41,0x38, + 0xBA,0xF2,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05, + 0x00,0x30,0x81,0x97,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C, + 0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, + 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x2B, + 0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x0C,0x22,0x56,0x61,0x6C,0x69,0x64,0x69,0x74, + 0x79,0x20,0x50,0x65,0x72,0x69,0x6F,0x64,0x20,0x4D,0x61,0x78,0x69,0x6D,0x75,0x6D, + 0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x30,0x1E,0x17,0x0D,0x32, + 0x30,0x30,0x39,0x30,0x31,0x30,0x30,0x30,0x36,0x32,0x30,0x5A,0x17,0x0D,0x32,0x31, + 0x31,0x30,0x30,0x34,0x30,0x30,0x30,0x36,0x32,0x30,0x5A,0x30,0x81,0x9A,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, + 0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72, + 0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41, + 0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55, + 0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67, + 0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x2E,0x30,0x2C,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x25,0x56,0x61,0x6C,0x69,0x64,0x69,0x74,0x79,0x20,0x50,0x65,0x72,0x69, + 0x6F,0x64,0x20,0x4D,0x61,0x78,0x69,0x6D,0x75,0x6D,0x73,0x20,0x33,0x39,0x38,0x20, + 0x44,0x61,0x79,0x20,0x4C,0x65,0x61,0x66,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,0xA4,0xDD,0xA6,0x75,0x21,0xFC,0x44, + 0x4D,0xF9,0x5D,0x69,0x5D,0xCF,0xE7,0xD1,0x88,0x37,0xAA,0x9A,0x60,0x25,0x0C,0x2C, + 0x65,0xAA,0xF2,0x2A,0xDF,0x2F,0xA9,0x0C,0x61,0x40,0xCE,0xF1,0x87,0x81,0x74,0xA9, + 0xCE,0xAE,0x2E,0x6E,0x4D,0x9E,0x72,0x34,0x51,0x9B,0x0A,0xD2,0x6F,0x46,0xEE,0xB1, + 0x9B,0xAA,0xCF,0x2D,0xBA,0x32,0x4F,0x86,0x04,0x54,0x27,0x3C,0x95,0xEC,0xD2,0xC7, + 0x26,0xD1,0x9B,0x02,0x33,0x90,0x38,0x7F,0x92,0xF9,0x1B,0x15,0xA4,0x19,0x83,0xBB, + 0x51,0x38,0x2D,0x6C,0x4B,0x7A,0x68,0x54,0xCD,0x30,0x2F,0xC1,0x26,0x01,0xA0,0x60, + 0xBB,0x79,0x9F,0xAD,0x28,0x2F,0xA5,0x17,0x69,0xA7,0xCD,0xEE,0xE3,0x61,0x83,0xB5, + 0xBC,0xC2,0x6C,0xFA,0x85,0x75,0x7C,0x06,0x4D,0xEA,0xCB,0x39,0x42,0x21,0xB4,0x2F, + 0x9C,0x81,0xAA,0x39,0x3F,0xAA,0xEC,0xF8,0xA1,0x65,0xF5,0x64,0x0A,0xB2,0xA3,0x71, + 0x29,0xA2,0x74,0x12,0xE7,0x66,0xB5,0x1F,0xED,0xDF,0x2C,0xA8,0x0C,0xB7,0xD3,0x96, + 0x33,0x92,0x1D,0xF4,0xA8,0x94,0xD7,0x08,0x58,0x65,0xDD,0x6C,0x99,0x52,0x05,0x31, + 0xB6,0x0E,0x88,0xE2,0xE5,0xEB,0xCA,0x5A,0x30,0x9D,0x0C,0x68,0xC6,0x2B,0xB4,0x36, + 0xF2,0xA0,0xD1,0x97,0xDB,0x49,0x78,0xAB,0x79,0x90,0xE5,0x7B,0xA5,0xAD,0xE5,0xB0, + 0x13,0x85,0x74,0x75,0x15,0x82,0xC6,0x04,0x27,0x18,0x7C,0xE8,0x91,0x36,0x6E,0xF2, + 0x64,0xE3,0x37,0x2E,0x0B,0x8D,0x4D,0x8D,0x6B,0xC2,0x44,0x18,0x01,0x95,0xDE,0x08, + 0xAC,0x8D,0x00,0x5A,0xE9,0x09,0xEA,0xD1,0x0D,0x02,0x03,0x01,0x00,0x01,0xA3,0x81, + 0x98,0x30,0x81,0x95,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02, + 0x30,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02, + 0x07,0x80,0x30,0x1D,0x06,0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03, + 0x02,0x30,0x16,0x06,0x03,0x55,0x1D,0x11,0x04,0x0F,0x30,0x0D,0x82,0x0B,0x65,0x78, + 0x61,0x6D,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, + 0x04,0x16,0x04,0x14,0x81,0xE5,0x84,0xC1,0xB3,0x5E,0x70,0xD8,0x3A,0xF2,0x45,0x17, + 0x92,0x8B,0x24,0xD5,0x07,0xB1,0x5D,0x96,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04, + 0x18,0x30,0x16,0x80,0x14,0xDE,0xEB,0xFD,0x98,0xFD,0xCA,0x44,0xC1,0xFA,0xB7,0xF9, + 0x2B,0xF5,0x96,0x67,0x08,0x11,0x35,0x27,0x75,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x02,0x01,0x00,0x1B,0x19,0xDC, + 0x50,0x5C,0x92,0x48,0x4F,0x0B,0x3D,0xAF,0x1B,0x9C,0x22,0x36,0xB2,0x24,0x2F,0xBB, + 0xCB,0x05,0x5D,0xC8,0xA5,0x5F,0x43,0x47,0x0C,0x9A,0xCF,0xB5,0x1F,0x01,0x3F,0xE0, + 0x84,0xCE,0xA9,0xC7,0x05,0xFD,0x6E,0xE7,0xD2,0xF6,0x07,0x7B,0xDF,0x57,0xD6,0x0F, + 0x03,0x33,0xFE,0xB1,0xB6,0xBF,0x73,0xDF,0x69,0xEA,0x04,0xEA,0xFF,0x7C,0xBB,0x9E, + 0xC4,0x01,0x9A,0xE5,0x6A,0x10,0x45,0x42,0xB2,0xDB,0xA2,0xC3,0x85,0xF4,0x82,0x1A, + 0xE9,0x7B,0xDB,0xF4,0x53,0x3D,0x6B,0x2B,0xA0,0x1E,0x92,0x50,0x89,0x66,0xF3,0xF2, + 0x58,0x8E,0x61,0xBC,0x1D,0x33,0xE8,0x13,0xAA,0xBF,0x2B,0x17,0x36,0x95,0x51,0xA1, + 0x5C,0x9E,0x6B,0x3F,0xEF,0xBA,0x45,0x32,0x84,0xB1,0x81,0xEF,0x10,0xCA,0x05,0xB3, + 0xD7,0x31,0x79,0x76,0x28,0x38,0xB0,0x2E,0x30,0xAC,0x74,0xFF,0xF4,0xFB,0x8F,0x08, + 0x22,0x08,0x41,0x1B,0x67,0xB4,0x72,0x82,0x84,0x6E,0xC3,0x12,0x93,0x65,0xD4,0x9B, + 0xD4,0x2E,0x55,0x6C,0x22,0x6A,0x22,0x36,0x26,0x2C,0x9F,0x5C,0xFC,0x85,0xB2,0x71, + 0x0E,0x58,0x79,0x83,0x75,0x7E,0x65,0x50,0x18,0x05,0x95,0x2F,0xB6,0x05,0x6A,0xA8, + 0x9F,0x1C,0x66,0xFC,0x6F,0x30,0xBE,0xC6,0x20,0x7A,0xF8,0xFC,0xB4,0x24,0x5E,0x4A, + 0x26,0x4C,0xEC,0x48,0xF2,0x5A,0x7D,0x83,0xB1,0x86,0x69,0x48,0x69,0xC7,0xF3,0x2A, + 0xFA,0xB1,0x58,0x69,0x77,0x96,0x67,0xE5,0x7E,0xE6,0xE9,0x07,0xFC,0xA4,0x24,0xC6, + 0xC1,0x64,0x69,0xB4,0x36,0x59,0x81,0xA7,0xD4,0x14,0xEE,0xA5,0xDE,0x44,0x46,0x72, + 0x52,0xB6,0x28,0xF7,0x33,0x5B,0xFA,0x71,0x8F,0xC9,0x9F,0xBE,0xBB,0xEF,0xB4,0x4B, + 0x6A,0xA0,0x01,0xF1,0xA2,0x06,0x41,0xA4,0x8E,0x75,0xC8,0xAF,0x6C,0x31,0xCD,0xCB, + 0x6E,0xB3,0xD1,0x4F,0x46,0x39,0x74,0xD1,0x82,0x75,0x3D,0x71,0x8C,0xD8,0xDE,0xD6, + 0xDE,0x25,0x8A,0xD7,0x77,0xA7,0xD4,0xCA,0xCF,0x2A,0x35,0xA9,0xF4,0x19,0x81,0x98, + 0x81,0x64,0x16,0xBD,0x0C,0xE7,0xED,0xAA,0x05,0xEB,0xED,0x4B,0x1B,0xEE,0x78,0xC4, + 0x6C,0x93,0xDB,0x81,0xB2,0xD0,0x78,0x9D,0x66,0x41,0x91,0xF7,0xCD,0x82,0x45,0x8A, + 0x81,0x3D,0xC3,0x79,0x15,0x9E,0x1D,0xE8,0x25,0xB8,0x8D,0xA7,0xA7,0xA7,0x74,0x43, + 0xF7,0x43,0x80,0xF9,0x01,0xD3,0x81,0xDD,0xE4,0xFF,0x4A,0xC0,0x7C,0x44,0x30,0xB4, + 0xFA,0x9E,0xA3,0x5E,0xE2,0x2B,0x23,0xFB,0x68,0xE9,0x1C,0xA2,0xA9,0xF1,0xD0,0x45, + 0x50,0x3B,0xEC,0xEB,0x22,0xAC,0xBF,0x4E,0xE2,0x64,0xD7,0x0B,0xFE,0xB9,0xBE,0x28, + 0xC2,0xFB,0xA8,0xC5,0x93,0xD9,0x35,0x88,0x48,0x0A,0x24,0x22,0xAF,0x85,0x21,0xC3, + 0x9D,0x02,0x6E,0x9E,0x03,0xF6,0x78,0x66,0xCB,0x16,0x9E,0x74,0xF7,0xEB,0x85,0x63, + 0x9B,0xD8,0x11,0xAF,0x60,0x9E,0xF8,0x9E,0x4E,0x8E,0xEC,0xAD,0x99,0x65,0xEE,0x57, + 0x9C,0x59,0x53,0x7E,0xFE,0x1D,0xCA,0xED,0x17,0xAA,0x1C,0xF3,0xD9,0xC4,0x76,0xDF, + 0x9A,0x64,0x77,0xD6,0x41,0x2D,0x16,0xE7,0xAD,0x7E,0xBF,0x0B,0xF1,0x87,0x6A,0xCF, + 0x2A,0x7B,0x2B,0x8F,0x96,0xFF,0xA2,0xDC,0xE2,0x07,0xF0,0x0C,0x31, +}; + #endif /* _TRUSTTESTS_EVALUATION_VERIFY_DATE_TESTS_H_ */ diff --git a/tests/TrustTests/FrameworkTests/CertificateInterfaceTests.m b/tests/TrustTests/FrameworkTests/CertificateInterfaceTests.m index 2e5c8dea..5194d302 100644 --- a/tests/TrustTests/FrameworkTests/CertificateInterfaceTests.m +++ b/tests/TrustTests/FrameworkTests/CertificateInterfaceTests.m @@ -38,6 +38,7 @@ #include #include "../TestMacroConversions.h" #include "TrustFrameworkTestCase.h" +#include #include "CertificateInterfaceTests_data.h" @@ -501,4 +502,38 @@ errOut: CFRelease(result6); } +- (void)testCopyIPAddresses { + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, _IPAddressCert, sizeof(_IPAddressCert)); + NSArray *ipAddresses = CFBridgingRelease(SecCertificateCopyIPAddresses(cert)); + XCTAssertNotNil(ipAddresses); + XCTAssertEqual(ipAddresses.count, 1); + XCTAssertEqualObjects(ipAddresses[0], @"10.0.0.1"); + CFReleaseNull(cert); + + cert = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)); + ipAddresses = CFBridgingRelease(SecCertificateCopyIPAddresses(cert)); + XCTAssertNil(ipAddresses); + CFReleaseNull(cert); +} + +- (void)testCopySubjectAttributeValue { + // ATV not present + SecCertificateRef devCert = SecCertificateCreateWithBytes(NULL, _new_developer_cert, sizeof(_new_developer_cert)); + NSString *locality = CFBridgingRelease(SecCertificateCopySubjectAttributeValue(devCert, (DERItem *)&oidLocalityName)); + XCTAssertNil(locality); + + // ATV present + NSString *ou = CFBridgingRelease(SecCertificateCopySubjectAttributeValue(devCert, (DERItem *)&oidOrganizationalUnitName)); + XCTAssertNotNil(ou); + XCTAssert([ou isEqualToString:@"PV45XFU466"]); + CFReleaseNull(devCert); + + // pick the last value for multiple attributes + SecCertificateRef multipleValues = SecCertificateCreateWithBytes(NULL, two_common_names, sizeof(two_common_names)); + NSString *commonName = CFBridgingRelease(SecCertificateCopySubjectAttributeValue(multipleValues, (DERItem *)&oidCommonName)); + XCTAssertNotNil(commonName); + XCTAssert([commonName isEqualToString:@"certxauthsplit"]); + CFReleaseNull(multipleValues); +} + @end diff --git a/tests/TrustTests/FrameworkTests/CertificateInterfaceTests_data.h b/tests/TrustTests/FrameworkTests/CertificateInterfaceTests_data.h index 50f227e3..1a6bc4b1 100644 --- a/tests/TrustTests/FrameworkTests/CertificateInterfaceTests_data.h +++ b/tests/TrustTests/FrameworkTests/CertificateInterfaceTests_data.h @@ -994,4 +994,77 @@ const uint8_t _new_developer_cert[] = { 0xA4,0x85,0x74, }; +/* X509v3 Subject Alternative Name: + IP Address:10.0.0.1 */ +const uint8_t _IPAddressCert[] = { + 0x30,0x82,0x04,0x37,0x30,0x82,0x03,0x1F,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xC7,0x90,0xC5,0x69,0xCA,0xE3,0xB4,0x07,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27,0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53, + 0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63,0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A, + 0x20,0x49,0x50,0x20,0x41,0x64,0x64,0x72,0x65,0x73,0x73,0x20,0x53,0x41,0x4E,0x30, + 0x1E,0x17,0x0D,0x31,0x39,0x31,0x31,0x30,0x38,0x30,0x30,0x31,0x34,0x32,0x31,0x5A, + 0x17,0x0D,0x32,0x30,0x31,0x31,0x30,0x37,0x30,0x30,0x31,0x34,0x32,0x31,0x5A,0x30, + 0x81,0x95,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x29,0x30,0x27, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x53,0x53,0x4C,0x20,0x50,0x6F,0x6C,0x69,0x63, + 0x79,0x20,0x54,0x65,0x73,0x74,0x73,0x3A,0x20,0x49,0x50,0x20,0x41,0x64,0x64,0x72, + 0x65,0x73,0x73,0x20,0x53,0x41,0x4E,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,0xC1,0x80,0xDE,0x51,0x33,0xB8,0x28,0xA8, + 0x7D,0x94,0x12,0x73,0x6F,0x0E,0xFC,0xF5,0xF0,0xC6,0x18,0xD2,0x87,0xB8,0x37,0xEE, + 0xF9,0xB1,0x69,0x1D,0xF9,0xE1,0x65,0x8D,0x47,0x34,0x50,0xBD,0x72,0x41,0x32,0x7A, + 0x02,0x0F,0x72,0x85,0xB8,0xE1,0x3D,0x7C,0x78,0x90,0x0A,0x81,0x06,0x25,0x9B,0x13, + 0xCA,0xD6,0xAA,0x77,0xDC,0x4A,0x9B,0x32,0xB7,0x1D,0xF1,0xEF,0x52,0x33,0xE3,0x5D, + 0x80,0xE0,0xE1,0xBB,0xF2,0x5E,0x91,0x55,0xA1,0xF8,0xE4,0x25,0x62,0xAB,0xBA,0x3D, + 0x42,0xEB,0x9B,0xD7,0x95,0x92,0x18,0x26,0x5F,0xB1,0x28,0x9B,0x01,0xDB,0x52,0x18, + 0xFE,0xF4,0x4F,0xD6,0x3A,0x49,0x13,0xE2,0xB0,0x06,0xEF,0x28,0x6C,0x89,0xFD,0x23, + 0x19,0x56,0xF7,0x1A,0x51,0x89,0x5C,0x13,0xDD,0xD6,0x55,0x70,0x17,0xCA,0x05,0x59, + 0x77,0xEA,0x75,0xA4,0x44,0x05,0x49,0xD3,0xD6,0xE4,0x04,0x74,0xC8,0x5F,0xF9,0x19, + 0x75,0x27,0xB2,0x17,0x6B,0x2E,0x45,0xE5,0x07,0xBD,0x17,0x70,0xFD,0xA2,0x6A,0xF7, + 0xF1,0xD8,0x43,0xBC,0xF6,0xCD,0xD1,0x2D,0xE0,0xF0,0x55,0xE7,0x60,0xA5,0x09,0x42, + 0xE6,0x67,0xB6,0x40,0x56,0x4E,0x3E,0xDF,0x7B,0x89,0x44,0x36,0x78,0x83,0x30,0x25, + 0x12,0xFF,0x48,0x97,0xC1,0x04,0x87,0xC7,0xA3,0x06,0xCE,0x06,0xCE,0x2F,0xAE,0x01, + 0x42,0x57,0x62,0x3B,0xDA,0xEB,0xD8,0xDB,0x96,0x5E,0xFC,0x1E,0x30,0x4B,0xE4,0x80, + 0xE1,0xD9,0x34,0x03,0x9C,0xD4,0x92,0x39,0x17,0xA8,0xCD,0xCA,0x96,0x54,0xEB,0x2D, + 0x12,0x77,0xE3,0x96,0x09,0x6D,0xBB,0x93,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0x87, + 0x30,0x81,0x84,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, + 0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07, + 0x80,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x0F,0x06,0x03,0x55,0x1D,0x11,0x04,0x08,0x30, + 0x06,0x87,0x04,0x0A,0x00,0x00,0x01,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0xE0,0xA6,0x7D,0x62,0x28,0x6C,0xC0,0xCE,0x46,0xC8,0x04,0xB0,0xBA,0xB9, + 0x9B,0xF6,0x4A,0x60,0xBF,0xA9,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30, + 0x16,0x80,0x14,0xE0,0xA6,0x7D,0x62,0x28,0x6C,0xC0,0xCE,0x46,0xC8,0x04,0xB0,0xBA, + 0xB9,0x9B,0xF6,0x4A,0x60,0xBF,0xA9,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x55,0xBB,0x48,0x72,0x61, + 0x8F,0xAF,0x7F,0x18,0x2F,0x31,0xF9,0xAA,0xFF,0x4A,0xC1,0x5B,0xBF,0x45,0xFE,0x82, + 0x3C,0xBE,0xFC,0xBB,0x58,0xA7,0x4A,0xF3,0x84,0xF8,0x10,0xB4,0x51,0x33,0x91,0xA0, + 0x58,0x1C,0x5F,0x67,0x91,0x31,0xD8,0xEC,0xA0,0x6A,0x85,0x84,0x71,0xBE,0xB5,0x18, + 0xAC,0xB8,0x7E,0xC3,0xFC,0x1C,0x74,0x84,0x48,0x2C,0x99,0xE9,0x52,0xBB,0x36,0x00, + 0x35,0x8C,0x50,0xC8,0x13,0x2A,0xFA,0x1E,0xF8,0x15,0x72,0xEF,0xF0,0x20,0x28,0xA0, + 0xCD,0xC7,0x85,0xEF,0x48,0x8C,0x27,0xF9,0x0E,0x15,0x9F,0xB8,0x54,0xD1,0x44,0x08, + 0x31,0xB0,0xC8,0x24,0x53,0x4A,0x63,0x97,0xB5,0xB3,0x83,0x07,0xCD,0x6D,0xC5,0x10, + 0xDD,0xC0,0x90,0xA2,0xFF,0x8E,0xD5,0x2F,0xC4,0xBC,0x8A,0xE0,0x90,0xAA,0x79,0x09, + 0xB5,0x23,0x72,0x6A,0xFB,0x9B,0xE5,0x0E,0xD9,0x30,0x41,0x70,0xF1,0x17,0x9C,0x5F, + 0xD7,0x0A,0x10,0x8E,0x77,0xD9,0x2F,0x59,0xE4,0xB4,0xF6,0x8D,0x16,0x90,0x84,0xBB, + 0xB6,0xAF,0xEE,0x86,0x4D,0x21,0xAE,0x3E,0x7B,0x2F,0xAD,0xBD,0xC4,0x38,0x9C,0x9E, + 0xB5,0x7C,0x8D,0x36,0x72,0x2C,0x78,0xC7,0xD4,0x54,0xD9,0x93,0x18,0xC8,0x00,0x5E, + 0xFE,0x12,0xE4,0x50,0x90,0x88,0xFB,0x82,0xFE,0x94,0xA5,0x4C,0xEB,0x7F,0xB7,0x39, + 0x99,0x24,0x0B,0x23,0xF9,0xB4,0x92,0xA8,0x6F,0xA6,0x46,0xBB,0xFB,0xDA,0xCD,0x8F, + 0xB9,0x14,0xE8,0x9B,0xBB,0x1B,0x80,0x9E,0x9D,0x9A,0x16,0xFF,0xF1,0x55,0xFF,0xDF, + 0x3E,0x32,0x73,0x16,0x9D,0xEA,0xF0,0xB1,0x5A,0x12,0xAB, +}; + #endif /* _TRUSTTESTS_CERTIFICATE_INTERFACE_H_ */ diff --git a/tests/TrustTests/FrameworkTests/CertificateParseTests.m b/tests/TrustTests/FrameworkTests/CertificateParseTests.m index a1a30b67..d65c9113 100644 --- a/tests/TrustTests/FrameworkTests/CertificateParseTests.m +++ b/tests/TrustTests/FrameworkTests/CertificateParseTests.m @@ -38,6 +38,7 @@ const NSString *kSecTestParseSuccessResources = @"si-18-certificate-parse/ParseS const NSString *kSecTestKeyFailureResources = @"si-18-certificate-parse/KeyFailureCerts"; const NSString *kSecTestTODOFailureResources = @"si-18-certificate-parse/TODOFailureCerts"; const NSString *kSecTestExtensionFailureResources = @"si-18-certificate-parse/ExtensionFailureCerts"; +const NSString *kSecTestNameFailureResources = @"si-18-certificate-parse/NameFailureCerts"; @interface CertificateParseTests : TrustFrameworkTestCase @@ -129,4 +130,20 @@ const NSString *kSecTestExtensionFailureResources = @"si-18-certificate-parse/Ex } } +- (void)testUnparseableSubjectName { + /* A bunch of certificates with different parsing errors the subject name */ + NSArray * certURLs = [[NSBundle bundleForClass:[self class]]URLsForResourcesWithExtension:@".cer" subdirectory:(NSString *)kSecTestNameFailureResources]; + XCTAssertTrue([certURLs count] > 0, "Unable to find parse test name failure certs in bundle."); + + if ([certURLs count] > 0) { + [certURLs enumerateObjectsUsingBlock:^(NSURL *url, __unused NSUInteger idx, __unused BOOL *stop) { + NSData *certData = [NSData dataWithContentsOfURL:url]; + SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData); + isnt(cert, NULL, "Failed to parse bad cert with unparseable name: %@", url); + is(CFBridgingRelease(SecCertificateCopyCountry(cert)), nil, "Success parsing name for failure cert: %@", url); + CFReleaseNull(cert); + }]; + } +} + @end diff --git a/tests/TrustTests/FrameworkTests/TrustInterfaceTests.m b/tests/TrustTests/FrameworkTests/TrustInterfaceTests.m index e44c6c2d..9ab7c00b 100644 --- a/tests/TrustTests/FrameworkTests/TrustInterfaceTests.m +++ b/tests/TrustTests/FrameworkTests/TrustInterfaceTests.m @@ -145,7 +145,7 @@ is_status(trustResult, kSecTrustResultInvalid, "trustResult is kSecTrustResultInvalid"); is(SecTrustGetCertificateCount(trust), 1, "cert count is 1 without securityd running"); SecKeyRef pubKey = NULL; - ok(pubKey = SecTrustCopyPublicKey(trust), "copy public key without securityd running"); + ok(pubKey = SecTrustCopyKey(trust), "copy public key without securityd running"); CFReleaseNull(pubKey); SecServerSetTrustdMachServiceName("com.apple.trustd"); // End of Restore OS environment tests @@ -371,7 +371,8 @@ errOut: ok_status(SecTrustEvaluateAsync(trust, queue, ^(SecTrustRef _Nonnull trustRef, SecTrustResultType trustResult) { if ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified)) { // Evaluation succeeded! - SecKeyRef publicKey = SecTrustCopyPublicKey(trustRef); + SecKeyRef publicKey = SecTrustCopyKey(trustRef); + XCTAssert(publicKey != NULL); CFReleaseSafe(publicKey); } else if (trustResult == kSecTrustResultRecoverableTrustFailure) { // Evaluation failed, but may be able to recover . . . @@ -891,4 +892,37 @@ errOut: }]; } +- (void)testCopyKey +{ + SecTrustRef trust = NULL; + CFArrayRef certs = NULL; + SecCertificateRef cert0 = NULL, cert1 = NULL; + SecPolicyRef policy = NULL; + + isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), + NULL, "create cert0"); + isnt(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), + NULL, "create cert1"); + const void *v_certs[] = { cert0, cert1 }; + + certs = CFArrayCreate(NULL, v_certs, array_size(v_certs), &kCFTypeArrayCallBacks); + policy = SecPolicyCreateSSL(false, NULL); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); + + SecKeyRef trustPubKey = NULL, certPubKey = NULL; + ok(trustPubKey = SecTrustCopyKey(trust), "copy public key without securityd running"); + ok(certPubKey = SecCertificateCopyKey(cert0)); + XCTAssert(CFEqualSafe(trustPubKey, certPubKey)); + + + CFReleaseNull(trustPubKey); + CFReleaseNull(certPubKey); + CFReleaseNull(trust); + CFReleaseNull(cert0); + CFReleaseNull(cert1); + CFReleaseNull(certs); + CFReleaseNull(policy); +} + @end diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/any_eku.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/any_eku.cer new file mode 100644 index 0000000000000000000000000000000000000000..3e16b5ec791d76631b2c958b2e8f1c8eb4a3d9a0 GIT binary patch literal 910 zcmXqLV(v0%Vk%m|%*4pV#K>>J%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaSN^Q0xwcx&&;w zK@+1Aau6`GGB7tW@-qO%xtN+585#CTd-C|s7HGHqn!d~>edlt4h4D`Qa;oQN=*Rsx z{#2To+W+FC+_?y=FL~8fi&wPv`nW%ywOhV6@S4cNPn&jzmp}Zwp-@sPJ#|lP%YN@) z_dE6fR4P2K^Z!&oSLcgX(-8x?)Fkfz0cp<aS~OcdGI%f7>mPRQr5KN_~EvnNEDVB*RB0W=00a#m)wf27JKamgQ$;{LjL| z%*5VcAOzy8g7_Q;Y-}t*HUl^X$O^KE7zi~AlmOFQ0$Fm;fCfnN6s=@-&Q-7ohRuyF}iof&qq2g z6P-NIzAwC?_eN-MrezE-t4*Bg4v9Cnp1fhYQ?jhdIAk_=)WWYJJHwh{a^JJxxSg!6 zy!%J`BBu#YGD}RfS2rjA?d+ZNMOgS#YO%uFjcOkY|1w^Dz4LLL0)t2y<-3+Bz9G zZ%E9znj*1Uw{nB(!q9?{b@Q!O*GU>wi?}g7{jiA7uyVx_8wa&1++G6mCmIjd-}utw P`(pJ9FP0;3QoaHJg$PsI literal 0 HcmV?d00001 diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/common_name.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/common_name.cer new file mode 100644 index 0000000000000000000000000000000000000000..feb03000b26d6eca081135533b2adfd9c0578e18 GIT binary patch literal 831 zcmXqLVzxGDVp3kf%*4pV#K>&G%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaSI-#Ge9nPVWA0l+6 zP5j}`-ML?dJ1#xlUZM5jfcTBp2=V3FA9-I%xhHOW{_+QR(GC0kQ`Rb={N~ zE2DW7T+@Z7FbD+1gz`D`{!jmUWzNGl9X|4w5m{dw!r7-iRuJ9ha?CYlb9Q^)ORJ=t ze^+q1w58oBkvY1DZ~Co^<_iqB#qQPKcH5`uUwU%F?M% z_vY+3u?zb3?{#$FUUPZx@}-mih}C*lR`_e@=T9_#EAleFMtpOZ)CqCDPlc=I$%?a? zA7@h1UbF3JKU;sZeBhDJ@|jj^=CQ06DoFaIV_Q(h{OOfq#d?Q}KSBb#4){ppnu^1IKSMl3!@-M{KPnUbFbyr7H zEovQ`%W^4ajv0N?x*?1YrP+Sue$`a@b#FK4PRpQ+#S8X+X)j>5Q|X`fNJuB}$p27< zy#1#(tISr9HZ}L#^dz-3QL^nr3$xDG`+EY`Cp@1~z3t;(Da)gumnv=$JlR&2F!?_# Le@fO9m1`mZ>OeX} literal 0 HcmV?d00001 diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/data_encipher.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/data_encipher.cer new file mode 100644 index 0000000000000000000000000000000000000000..b00612aaedb3783db1b9e2356c0e1e742287d8fe GIT binary patch literal 897 zcmXqLVy-o4VoF`W%*4pV#K>vD%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaSTQE{#9 zR!$ACL;LLW<#(Up6R)(gQHqI4dv)HgF6*V^%EvL@RXce@j~0|Fn7l8nWHaB{H*ML> zqTDc5t~q7_2Aur&RqbWJoGCc<@9d8I%I9vk9l0N+yrFyfyTWefo319g9Rl;YETy$S zXsHD)UKY9Um6v_hy!Ce^3k~1@$Xk8*Tw!;|vyeB>7qaIniP+lmTVcN9;FHP;Hxl;c9Gd2Qd1KCH-en<16NHN{%fI`_Ugm6nf0=d6{QcoiBKW=v zc=_-A)Ee56a;ewKZ1w(6t1CAum}s0`oiJLpc_Zkr%=lx>>Lx25M* zKe8=+sIubTr?BOP3kxqOnJAyPtG&7ZzU$L+SsSJ+6OIHfyK{B2n&#(or+oSjaC(|b zSk1`%9J0S=t;OZ0jKe9f)cY5|^pa&X`zQEcVfzE4D;J)X+PI(DXkpt>y8E};l7*jg zkKgEWx-##@rl;AHZ0y&`g_?c1XMgmgwVG^NGm9Z3Q(kLM)$Q_n&g6ee3a{EX9=RQ6 IW$P#i0R4DUcK`qY literal 0 HcmV?d00001 diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/digital_signature.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/digital_signature.cer new file mode 100644 index 0000000000000000000000000000000000000000..4b03c9c82a9bd1ad41e427edea54835a13635e3e GIT binary patch literal 900 zcmXqLVs0>KV#-*+%*4pV#K>mA%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaSPY@%{y~Zee(0a#!b)fuf5KD!8fJx^aML;vjCmsi$^Q%x*zlZ zso>A7wf%ou@@lQWm(`*Ltx=O1uRq!J*!H*bPno|md(QSGFJJ#EFM@T)UX7M>!pHV! z__?aB(6d|k`UbiN ze87O0bVhUcs%*4pV#3*3E%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaSjcqni(iV2hez3Px!k(dkgoL+K%u0a!{5^_K>vNA9?G4eA2#krW87#SIE zPF$`WQ0?pfw{h8x%2n4UxgF_T;B4Z)zV3kc7UhWtlJ_Po^eqr*;(B)c#Qa?D>~jYe z2^lmgopW5XVc*jxhn;&`_8phoZMbRetqsesF^5Fk7eD%Xr9egYhpnb^aM|bma>1nm zjt8DT`eAdwW6nv#i?6S(zW09rEi;knEAMGciht(&XEaIn;HIJw0*3A#!ZP~iZ-Ik-BYsZxNQA%qXHyTdU zzVNzPJ7w4AbGKKmnDAp;Thg`Q{>OFe-NMh*zB~TYf%je59E%gi+e&x8^Kn#YDwWl- zo{$&Ea3fkzl6x`}Ga~~datHyF5-@}q8G1gy*?O*gn!u4$Zo9eOJleYHa-`RNJ1!?? z@d#swswRcVI9dI#mX7&8v$odsM}B`$H?=%3<94-u+iCX)580+3n)LIOOVP2fX)8Z& zkd?f@=XPYll+&l4uPA40oRc`uE&V`s#|u8^quqTRTY0{n*i~tCXwStDrOoeWoW5{f z_f|!3&$pypewzk9x!t^bitj{CyU-U|(mo;UbZD`h@b)P(8!a4}AHCQ+ZMo*^llvZ( zu)O@Epu4WEO!n)(WABZ&@h>)b>+=25jG5KS`vU8I$3cH?CzLMFR`Md^cQsDb>6@X470(0O2)Sp8x;= literal 0 HcmV?d00001 diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/email_protection.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/email_protection.cer new file mode 100644 index 0000000000000000000000000000000000000000..94b86416c9a51a37b1feb754ed545c643e2079dc GIT binary patch literal 924 zcmXqLVxD2p#MH2WnTe5!iILBMmyJ`a&7*j7rFX!N|(M+{DPw02Jq9YGPz$xPHI-&Rf~93nFfC%4HZz^~Z%4 z?9z>2cx%qze4*><&+MKif11_1;1ZY7*_8LT|Gxyh+_<;W@4C;vlaf5mjkog;7}^WH zo_3g{-uC#r1LA_Z=6y$=bn?#Lb3H#;YhmWgt>(og!Y6M%=&?6-yz~8u@O_2Ick);OxC%shgW^_iMfSL%!~|-i`@-e z4fucoFU!x!_@9M^nTfr@Kn%oJ1@UjiBLZHt!87Zz%ZDs_Kf>+S!@znjbG`l$`~ ztG4cCy3JJM*r?&$a%he)lfrqEX}Sx%H`V_xD?GH*Yu!!nx!2N^B|mJ~xrh7Axj!Wz zE~potEGv&>nlH*=-W&4w=}NY@*-O@+mza{aF!y17p@YRI4ua5lO;K~zxIiUZBliyjE8M2#ZN8DH4BYY^Bw>Kl7 z?cl8k)3-0XpyViTRD6Ef$&v#aot0wWGP>3(ub6n>KmNIjg#KA0y*pDh g+;opaH>;jTo^%qqJ9`aZXGXEfKb4r?J3BiJ0Bj9%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaS;{7-MkVBsU}R-rZerwT0E%-lH8Cpf1}?v>AExw4Yy*sH#?j#68)B5rFlt6l8RJ*;?t zkNE>J6Z^|ML)zx^%KUtJtU||O+uJ9SD`sc=XoY{#<4)e$(XqTJO{n9{{PO3D)~lb+ zE?KZ3*x$RimG5rNiY3)ei(a@%6eTRMJaQ`I)N02`KF_tkw&#_9{6C-drspwH(RZK3 zSrY8-M6X4@{0b&2eW>yRjBm(5Xg_|WNh`$i_O!W@2&s-mqu>pQlq9ay(3G0*MK zLf=f2(|7H5=WB1+JF!6Ca{q;hG)e1heqo#Z1m!UiB8te|=ee&rWW1j_>(v{claomx9&VCscn#2rjeO!#1Nk z%znMUn)B8TPoCbM%Q(X<%Y3QE3q~ukC;ZEj%Af4+iIMuV$@Pk@MAxjq7qQh!?O&&S Iy<2S!0DccqtpET3 literal 0 HcmV?d00001 diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_decipher_only.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_decipher_only.cer new file mode 100644 index 0000000000000000000000000000000000000000..083b21c57756fdfee8f555f14a57a14c4b54304d GIT binary patch literal 914 zcmXqLV(v3&Vk%p}%*4pV#K>d7%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaSRV<- z3Eg1+;O5e~P|JA7V{c>U=(4qnHzJqT*}md5QsY14{`>ev<+pzl6jyysE&VL=H8`!t zr~Jsib3cyHdFR>5Ch@`W|4W^cbAJoANjyBIC0QN2{1uP$xAYyU?@r$SIwz*_?2nR@ zDm$CoFL^%JU`|yCNt&A0a`ni$bj~%?PO&qJ>CIewYC$R)g$*P;d z8WqeeKJC?u$gMY5@^_tHrToz3!IDW$kq4(-S;IBShxgk`*|&_Y-_|G;%YP1!+46e% z4yo|A>rBjy42+8n4D<~6fw3UV&&c?ng_W6^oudJq3S^6?9wer$cgYODKsokCDZ zkN5nSuU=mBNnN>op~t-Y{yX|(kG>Z8{`LM%ukN{TwQ~#d&$?~Z?(zzEd(vq6+3%BY zzC%4DQ_^37oQ4%rIU0M*O6^YZ)Hgr8DJjt9>BC)B&at#`rNZ>2e!g3^EQfcNzDm&l zb@aMS!Tuj-N`IYsaZLDB>ug7cq-y cFJO-K^feFDIJ#e4#9M9KZ^fX0i(g3q0Qoatt^fc4 literal 0 HcmV?d00001 diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_encipher_decipher.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_agreement_encipher_decipher.cer new file mode 100644 index 0000000000000000000000000000000000000000..372ba0256ead2fe3716e3383d3cf07104e432be3 GIT binary patch literal 930 zcmXqLVxDKv#MHKcnTe5!iILZUmyJ`a&7Ik-hcmaNSi;%{GwUiW_uQ9{z$3Cg3;?rq)*!F)lGcr?QHB& z_Ir)*V+IYA!?Bu1e^*v>bluo>>*$=!S#=7WoNe{b=QJ(-w7l`z{*CpswBBi-eDGbw z>SfQS%c4DU^Ea&KVVbt?lKlTYtG1_~ODi(!T>bsUce6GVyZ4h8t*D;x@12OYYL|-G zf)LLDX(vE7}- zUU1Lh9=k8@Ow5c7jEfBn^bGicu_DXQ$oQXym6@5HvjLncWCdA741^j5N`Ps|A+;hg z7no}FlJj$s!xWhMfMLqWkjD})DVV?BmFONQd!B#yX zT;V}j-s=yiw;o=)h4)9xjU$U!uX^eheCg}AH!Lp$`|5TX@O3ZlxW<`mU;In%{WE7B zt?>I>MAVkr?g|guwpifV%B@=7Hf>jSy)^#zEa`dPwPnga>%Ly$@7TM$*H%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaSm?dTd#+KfkqPQZv8nql*odN|$aOdwxkVX6M#~_tjS(9r^O9?#&t# ziO0?o#?e8aT4Ynd`qZr2bR&?jwsiIS3~9dbmBt>6?uyII(Rs&wto-5LRG-KiKb`(p zMbIOvZ?_r`Io1cSZ;Ov}@k8@}DzWdNvCb-o1a%;i+mP7;Z!UhYD zp1%cqnr}Qf6*T9+D@>eIDgM#m_&Q;%#&zii{^}}w_ zPY>)_LOX=7nI4qN;!6&AYR-Cj`Ci@KW?Kx}E~UmM>djZnnf5GXWe7L_cP4+g;?r^m z_==x*?ozuyr=*rUU-f=p=2?MH?SfZ#_TLgM(OvZ^#;*Frw}~tVYQHS6A^ z^BRX6?tQ8KRq(b>r-Dgk>nbrD|Md^bFYYPo%{bWIS{-?7zu??+_qI4MTg)qVCimdw Xc)n>q>w2uYf7mA-ZJ8gpL3|znn1)!+ literal 0 HcmV?d00001 diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_encipher.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/key_encipher.cer new file mode 100644 index 0000000000000000000000000000000000000000..2170c42599e6b4c4bb62c8fc74b5a23bcdb3dc4e GIT binary patch literal 895 zcmXqLVy-r5VoF}X%*4pV#K>X5%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaSy>->=PBcHKe6?hRo%~yl{=pfo4JSY1J8uF zt(ucf-8w&MW|gj1)nEvII!Q@SbY1c(O}(`Vm;S2q%bzO>DhbuT9k=Fj_lX$?&(!YL z+Ig&I^L8$kOCIO7PCYVOEEPD<;^#|)m%o$J8rQV0-8yCNodc3}Z@N$IPrv+cbtk{$ zn(DQG?kN;^%C4zand0`$1OQgf7Tmc~WKCF&lVJuJ0ut1~e(GB7UIH_$cU1BSUQ zKO^IR78YhERt0dB%L=lH7zi~AlmHWmLuy50E-*>xCFkcN2PrUV0fUs0Vd{#UN5OU? zkAsBDFWCeoOnqt3ZnHRi=JWj)22UKOTvlc4zYug-@Xxwazda9z-s#Pc)Sf$EOm?+- zynpoTJO|yS@&Z3@ht=BEmq~hFk*df(Wy<_ya`D%PTjn<;e(}#gt+7~h-n{mS&Bvrn z1=`B8E$1ps+MbZLhadJ<7;5vcXub)q!ai8nOCXt2DlhWPIvN4~7oYHC*5;Od#aX^jO#io^KkHCg=FoDUIWs=1y8G;wpo*?0p**3>sSu6%6Fqm_u2ZdBlT#J$+pj z0`hY*lPeWMQj1H96@v2fOALh#1VJjec(@!33UX2vJoA$E3}p?ZL4w>oBEhN2rA3(~ zl?twT>6v+{sYRK2>4w|}oFHiq9wui;7>7-mDKywn$Up!j!_LF$Tw0J?RFavOZy+bm zYiMa`XkcbwWMpn=93{?cWB}xvLb(R+hROztAYIHnQkbr^Qt-?7OUzBh?og;pz?K^{ zF)ASk0V68|a}y&!15licsfm%1Vbi@AQd9See4I4P$j)XNi^sC%lHT`)pB2oS%Gcsp z`#kE`T@#zP%Kx_fUH|&_M921qoK1Q=nD}l=F8LL4!hhLCgR?*8Trk#DzW8eUffdXX ze|&5{n0&*c`dy8u53{;haFb^L1)0vw$$r(QR;Kg6EciUZ__3mHj^DXDKELy=hwO7c z9ShNUz9??xwTNT0|FrMZ>RZZTOUucS6n3lZly;fe|@`fQbYcLW~US*q!Ge zk!RYbbZF_~r7QU9JUtP$ ztDJw4`GW8^xvyHrYqZ=X<2B+vSM;4?_@j`1>Hq7MSBssST4u6;mhqY3V!ieHjc3tc z*V$})vG}dw(?>H6xzl$EaZh~uKjt#ayv5Cb)kEf2b*$c}QF%x@#C7iPxRNg>2ULJEz{c$U0;DctupVm zroB4xN!d!7A>N?sv3k%XX|BbeUvpPW9p;I%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaSyha8;@WSKf-fc~MXa^)cmDhL#LB6Pf9EY`QD863d*^pO zkHu@F>HnlZYFf*cJ}q!O=`LURa$dsLlGtnItCohOuH@GK9r@U)+v~LZBW+G^ak2ER zcaxYjuU5vEeCx7w?`T_XX3;4W6yJPU{HWpT=&9dBd3R-TH2jF0E~D0DnELv=%}3rv zYGSwbixa$;6^Wn!zxi$OWs_Wy4SzaUm9Bae5yhB$^r3f5&PR3L{QgI|B3agPynJ=0 z3#^as_|__EW%x)q#o|cOy^k@o8J4o2RJwF%>V1oH&3^AYoBkUzF*7nSF4i~DHQ)mV zyDUE=<9`+wW+pZVaIDJ;vWOT6H42mf(}+WAMPe>6Rp=$>=OPCwFm(Zgl##*3KVXmX zpUr(r%TA>|k6(Bvd5P=9{7-JF7yGwIZp%A%_V?!5Cljtb`Tv!PQA98$_J5Go8M|QH5+Trs)>a}yXDw#tP|}z{}!1~y7BX5%Ct0t5bL<_uKCA)9$6(-YOd8f^N8yAxcQ0ay&T_` z{<>bRx8cbD=O^Q*K4pEV)wA-;If-`+dlz5+*>3hh?9q`p_0)MQcn{0z-oCp^{+{ZI zyWOYPYx)15KX3QrIo0mxPJasJ{cyJXte}x&==ZMpwiWYMe)Rq@*-hnN@mt_f*vY literal 0 HcmV?d00001 diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/root.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/root.cer new file mode 100644 index 0000000000000000000000000000000000000000..579d3a45032e569329109acad68efbf049c00397 GIT binary patch literal 940 zcmXqLVqRg;#57?6GZP~d6Cw*eqY`oeGO{u-H!<=v7&I|*F*PwVGHeXn z^{wU8rrv_P)y8T^p7?Hhx`uJu!*g7sOC2Jrw1Q{-+t0KpHhPQpOuL=?r*x~coebLk zF2#5Cf31MCRkK$e*6x|1vH!uWrKcb6OiAO|Q2zJQhQQhX{>qdWKTY}3xa7zLsg?H^ z{Zn$;Ey2ESb|Po|jsGndpDbfPmvJ_s$Mu~(*YDRqyO!=fZ$7srO4X0?$uidiYdN=Y zGg%zeioV#^{SXmcMG$7X3RL9RCT>Xd2ckO`z^lp z)#rPOW_@&ClfS9p@y`2CN__seSyhLq)=pSf{zrepjT_3pWw(~}zlzkK!1*C8^#1GL zAKowgF)PJ2u=C6F3EI}P{npOa((pPvCCT`H)3^Dyjw-1(%blGweMRqFSreokTY3Fk z%pT*nYCUB#lb1c{*e~X*{KRJGcE=e>l?xs^{d`+q`bq0_=)tJdfxB!!g-mh2u5~_N QDC&r9ddaH4K}S@)0BY1^WB>pF literal 0 HcmV?d00001 diff --git a/tests/TrustTests/TestData/SMIMEPolicyTests-data/san_name.cer b/tests/TrustTests/TestData/SMIMEPolicyTests-data/san_name.cer new file mode 100644 index 0000000000000000000000000000000000000000..ea9d74daaee357ce56a3e7e1c7cb5dd880e80770 GIT binary patch literal 871 zcmXqLVoo+_V)9yE%f_kI=F#?@mywa1mBFB~#ZbXOj*U5#g_%b@*w@q7 zRUsfhCo{QHAtbf9q*x&+KflCK*gz1Zf{TaCv7jI)RlzeaSx@`CEs-jn1m9h*2uJgHCYm2hmOvT0#!k4mA)uHza@?noHfIo*``c4%jd z{O&mJcQdA_?df=8=(6{m$&C#P3ydeZxNDY7Ix}7E_37yQ_phtos=H!3o1=5txeJLd zn>KKG*ZwekI9u6!{@H_;r?*b5V?O*gz9hERe^%D)pJyeW?=(F6Xp5tM?6foit-bPG z^^7;9d%1n5C=?3H@zK^74Mp+SQ?c`* zRV(C5Hm(ZLeRA-WVMht49nMO@8;%oSW(g>6 bczrU&R#on;)#VtE@&nrn76i>|vpoy|ZKzY5 literal 0 HcmV?d00001 diff --git a/tests/TrustTests/TestData/TestCopyProperties_ios-data/TestCopyProperties_ios.plist b/tests/TrustTests/TestData/TestCopyProperties_ios-data/TestCopyProperties_ios.plist index d110b1ce..b51f2ae4 100644 --- a/tests/TrustTests/TestData/TestCopyProperties_ios-data/TestCopyProperties_ios.plist +++ b/tests/TrustTests/TestData/TestCopyProperties_ios-data/TestCopyProperties_ios.plist @@ -413,36 +413,6 @@ - - CertDirectory - si-20-sectrust-policies-data - BridgeOSDisable - - MajorTestName - AnchorSHA1 - MinorTestName - OnlyFailure - Policies - - PolicyIdentifier - 1.2.840.113635.100.1.51 - - Leaf - escrow_service_key_049F9D11 - Intermediates - EscrowServiceRootCA101 - Anchors - EscrowServiceRootCA101 - ExpectedProperties - - - type - error - value - Root certificate is not trusted. - - - CertDirectory si-20-sectrust-policies-data diff --git a/tests/TrustTests/TestRunners/Base.lproj/LaunchScreen.storyboard b/tests/TrustTests/TestRunners/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index bfa36129..00000000 --- a/tests/TrustTests/TestRunners/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/TrustTests/TestRunners/Base.lproj/Main.storyboard b/tests/TrustTests/TestRunners/Base.lproj/Main.storyboard deleted file mode 100644 index 942f0bc4..00000000 --- a/tests/TrustTests/TestRunners/Base.lproj/Main.storyboard +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/TrustTests/TestRunners/main.m b/tests/TrustTests/TestRunners/main.m index c34bf518..ab6c189b 100644 --- a/tests/TrustTests/TestRunners/main.m +++ b/tests/TrustTests/TestRunners/main.m @@ -23,8 +23,7 @@ @implementation TestRunner - (instancetype)initWithBundlePath:(NSString *)path andTestNames:(NSArray *)names { - self = [super init]; - if (self) { + if ((self = [super init])) { NSError *error = nil; _bundle = [NSBundle bundleWithPath:path]; @@ -112,8 +111,11 @@ [self testLogWithFormat:@"Test Suite '%@' started at %@\n", testSuite.name, [self.dateFormatter stringFromDate:testSuite.testRun.startDate]]; } -- (void)testSuite:(XCTestSuite *)testSuite didFailWithDescription:(NSString *)description inFile:(nullable NSString *)filePath atLine:(NSUInteger)lineNumber +- (void)testSuite:(XCTestSuite *)testSuite didRecordIssue:(XCTIssue *)issue { + NSString *filePath = [issue.sourceCodeContext.location.fileURL absoluteString]; + NSInteger lineNumber = issue.sourceCodeContext.location.lineNumber; + NSString *description = issue.description; [self testLogWithFormat:@"%@:%lu: error: %@ : %@\n", ((nil != filePath) ? filePath : @""), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testSuite.name, description]; } @@ -136,8 +138,11 @@ [self testLogWithFormat:@"Test Case '%@' started.\n", testCase.name]; } -- (void)testCase:(XCTestCase *)testCase didFailWithDescription:(NSString *)description inFile:(nullable NSString *)filePath atLine:(NSUInteger)lineNumber +- (void)testCase:(XCTestCase *)testCase didRecordIssue:(XCTIssue *)issue { + NSString *filePath = [issue.sourceCodeContext.location.fileURL absoluteString]; + NSInteger lineNumber = issue.sourceCodeContext.location.lineNumber; + NSString *description = issue.description; [self testLogWithFormat:@"%@:%lu: error: %@ : %@\n", ((nil != filePath) ? filePath : @""), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testCase.name, description]; } diff --git a/tests/TrustTests/TestRunners/trusttests_entitlements.plist b/tests/TrustTests/TestRunners/trusttests_entitlements.plist index 8df24b43..bac16a08 100644 --- a/tests/TrustTests/TestRunners/trusttests_entitlements.plist +++ b/tests/TrustTests/TestRunners/trusttests_entitlements.plist @@ -14,5 +14,15 @@ com.apple.MobileAsset.PKITrustSupplementals + com.apple.security.exception.files.absolute-path.read-only + + /System/Library/Caches/apticket.der + + com.apple.system.diagnostics.iokit-properties + + com.apple.private.AuthorizationServices + + com.apple.trust-settings.admin + diff --git a/tests/TrustTests/TrustEvaluationTestHelpers.m b/tests/TrustTests/TrustEvaluationTestHelpers.m index a7ee45d9..1a790099 100644 --- a/tests/TrustTests/TrustEvaluationTestHelpers.m +++ b/tests/TrustTests/TrustEvaluationTestHelpers.m @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -288,6 +289,50 @@ errOut: return false; } +- (bool)addThirdPartyPinningPolicyChecks:(CFDictionaryRef)properties + policy:(SecPolicyRef)policy +{ + if (!properties) { + return true; + } + + CFStringRef spkiSHA256Options[] = { + kSecPolicyCheckLeafSPKISHA256, + kSecPolicyCheckCAspkiSHA256, + }; + + for (size_t i = 0; i < sizeof(spkiSHA256Options)/sizeof(spkiSHA256Options[0]); i++) { + CFArrayRef spkiSHA256StringArray = CFDictionaryGetValue(properties, spkiSHA256Options[i]); + // Relevant property is not set. + if (!spkiSHA256StringArray) { + continue; + } + require_string(isArray(spkiSHA256StringArray), errOut, "SPKISHA256 property is not an array"); + + CFMutableArrayRef spkiSHA256DataArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + require_string(spkiSHA256DataArray, errOut, "failed to allocate memory for the SPKISHA256 data array"); + + for (CFIndex j = 0; j < CFArrayGetCount(spkiSHA256StringArray); j++) { + CFStringRef spkiSHA256String = CFArrayGetValueAtIndex(spkiSHA256StringArray, j); + require_string(isString(spkiSHA256String), errOut, "SPKISHA256 property array element is not a string"); + CFDataRef spkiSHA256Data = CreateCFDataFromBase64CFString(spkiSHA256String); + // 'spkiSHA256Data' is optional because we want to allow empty strings. + if (spkiSHA256Data) { + CFArrayAppendValue(spkiSHA256DataArray, spkiSHA256Data); + } + CFReleaseNull(spkiSHA256Data); + } + + SecPolicySetOptionsValue(policy, spkiSHA256Options[i], spkiSHA256DataArray); + CFReleaseNull(spkiSHA256DataArray); + } + + return true; + +errOut: + return false; +} + - (bool)addPolicy:(NSDictionary *)policyDict { SecPolicyRef policy = NULL; @@ -295,14 +340,17 @@ errOut: NSDictionary *policyProperties = [(NSDictionary *)policyDict objectForKey:kSecTrustTestPolicyProperties]; require_string(policyIdentifier, errOut, "failed to get policy OID"); + CFDictionaryRef properties = (__bridge CFDictionaryRef)policyProperties; policy = SecPolicyCreateWithProperties((__bridge CFStringRef)policyIdentifier, - (__bridge CFDictionaryRef)policyProperties); + properties); require_string(policy, errOut, "failed to create properties for policy OID"); + require_string([self addThirdPartyPinningPolicyChecks:properties policy:policy], errOut, "failed to parse properties for third-party-pinning policy checks"); [self.policies addObject:(__bridge id)policy]; CFReleaseNull(policy); return true; errOut: + CFReleaseNull(policy); return false; } diff --git a/tests/TrustTests/gen_test_plist.py b/tests/TrustTests/gen_test_plist.py index ee7c7307..c6a37679 100644 --- a/tests/TrustTests/gen_test_plist.py +++ b/tests/TrustTests/gen_test_plist.py @@ -32,8 +32,10 @@ for filename in test_files: test_command = Foundation.NSMutableArray.array() test_command.append('/AppleInternal/CoreOS/tests/Security/TrustTests') - test_command.append('-c ' + match.group(1)) - test_command.append('-t TrustTests') + test_command.append('-c') + test_command.append(match.group(1)) + test_command.append('-t') + test_command.append('TrustTests') test_dictionary['Command'] = test_command diff --git a/tests/secdmockaks/mockaks.h b/tests/secdmockaks/mockaks.h index 068c33fb..a27a51ce 100644 --- a/tests/secdmockaks/mockaks.h +++ b/tests/secdmockaks/mockaks.h @@ -80,6 +80,8 @@ int MKBForegroundUserSessionID( CFErrorRef _Nullable * _Nullable error); + (void)failNextDecryptRefKey:(NSError* _Nonnull) decryptRefKeyError; + (NSError * _Nullable)popDecryptRefKeyFailure; ++ (void)setOperationsUntilUnlock:(int)val; + @end #endif // OBJC2 diff --git a/tests/secdmockaks/mockaks.m b/tests/secdmockaks/mockaks.m index 4bf815b8..ca4f9a56 100644 --- a/tests/secdmockaks/mockaks.m +++ b/tests/secdmockaks/mockaks.m @@ -52,6 +52,8 @@ #import "tests/secdmockaks/generated_source/MockAKSRefKey.h" #import "tests/secdmockaks/generated_source/MockAKSOptionalParameters.h" +#include "utilities/simulatecrash_assert.h" + bool hwaes_key_available(void) { return false; @@ -70,6 +72,8 @@ static NSMutableDictionary* _lockedStates = nil; static dispatch_queue_t _mutabilityQueue = nil; static keybag_state_t _keybag_state = keybag_state_unlocked | keybag_state_been_unlocked; static NSMutableArray* _decryptRefKeyErrors = nil; +static int _operationsUntilUnlock = -1; // -1: don't care, 0: be unlocked, posnum: decrement and be locked + /* * Method that limit where this rather in-secure version of AKS can run */ @@ -222,6 +226,24 @@ static NSMutableArray* _decryptRefKeyErrors = nil; return error; } ++ (void)setOperationsUntilUnlock:(int)val { + _operationsUntilUnlock = val; +} + ++ (void)updateOperationsUntilUnlock { + if (_operationsUntilUnlock == -1) { + return; + } + + if (_operationsUntilUnlock == 0) { + _operationsUntilUnlock = -1; + [SecMockAKS unlockAllClasses]; + return; + } + + --_operationsUntilUnlock; +} + @end @@ -309,6 +331,8 @@ aks_wrap_key(const void * key, int key_size, keyclass_t key_class, keybag_handle return kAKSReturnBusy; } + [SecMockAKS updateOperationsUntilUnlock]; + // Assumes non-device keybags are asym if ([SecMockAKS isLocked:key_class] && handle == KEYBAG_DEVICE) { return kAKSReturnNoPermission; @@ -349,6 +373,8 @@ aks_unwrap_key(const void * wrapped_key, int wrapped_key_size, keyclass_t key_cl return kAKSReturnBusy; } + [SecMockAKS updateOperationsUntilUnlock]; + if ([SecMockAKS isLocked:key_class]) { return kAKSReturnNoPermission; } @@ -408,7 +434,7 @@ aks_unwrap_key(const void * wrapped_key, int wrapped_key_size, keyclass_t key_cl CFTypeRef cf = NULL; CFErrorRef cferror = NULL; uint8_t *der = (uint8_t *)params.externalData.bytes; - der_decode_plist(NULL, false, &cf, &cferror, der, der + params.externalData.length); + der_decode_plist(NULL, &cf, &cferror, der, der + params.externalData.length); if (cf == NULL) { *error = [NSError errorWithDomain:@"foo" code:kAKSReturnBadArgument userInfo:nil]; return NULL; @@ -610,6 +636,14 @@ aks_ref_key_delete(aks_ref_key_t handle, const uint8_t *der_params, size_t der_p return kAKSReturnSuccess; } +const uint8_t * +aks_ref_key_get_public_key(aks_ref_key_t handle, size_t *pub_key_len) +{ + static const uint8_t dummy_key[0x41] = { 0 }; + *pub_key_len = sizeof(dummy_key); + return dummy_key; +} + int aks_operation_optional_params(const uint8_t * access_groups, size_t access_groups_len, const uint8_t * external_data, size_t external_data_len, const void * acm_handle, int acm_handle_len, void ** out_der, size_t * out_der_len) { @@ -720,132 +754,176 @@ aks_generation(keybag_handle_t handle, return kAKSReturnSuccess; } -CFStringRef kMKBDeviceModeMultiUser = CFSTR("kMKBDeviceModeMultiUser"); -CFStringRef kMKBDeviceModeSingleUser = CFSTR("kMKBDeviceModeSingleUser"); -CFStringRef kMKBDeviceModeKey = CFSTR("kMKBDeviceModeKey"); +kern_return_t +aks_get_device_state(keybag_handle_t handle, aks_device_state_s *device_state) +{ + // Probably not legal + return kAKSReturnError; +} -static CFStringRef staticKeybagHandle = CFSTR("keybagHandle"); +int +aks_system_key_get_public(aks_system_key_type_t type, aks_system_key_generation_t generation, const uint8_t *der_params, size_t der_params_len, uint8_t **pub_out, size_t *pub_len_out) +{ + return kAKSReturnError; +} int -MKBKeyBagCreateWithData(CFDataRef keybagBlob, MKBKeyBagHandleRef* newHandle) +aks_system_key_operate(aks_system_key_type_t type, aks_system_key_operation_t operation, const uint8_t *der_params, size_t der_params_len) { - *newHandle = (MKBKeyBagHandleRef)staticKeybagHandle; - return kMobileKeyBagSuccess; + return kAKSReturnError; } int -MKBKeyBagUnlock(MKBKeyBagHandleRef keybag, CFDataRef passcode) +aks_system_key_collection(aks_system_key_type_t type, aks_system_key_generation_t generation, const uint8_t *der_params, size_t der_params_len, uint8_t **out_der, size_t *out_der_len) { - if (keybag == NULL || !CFEqual(keybag, staticKeybagHandle)) { - abort(); - } - return kMobileKeyBagSuccess; + return kAKSReturnError; } -int MKBKeyBagGetAKSHandle(MKBKeyBagHandleRef keybag, int32_t *handle) +int +aks_system_key_attest(aks_system_key_type_t type, aks_system_key_generation_t generation, aks_ref_key_t ref_key, const uint8_t *der_params, size_t der_params_len, uint8_t **out_der, size_t *out_der_len) { - if (keybag == NULL || !CFEqual(keybag, staticKeybagHandle)) { - abort(); - } - *handle = 17; - return kMobileKeyBagSuccess; + return kAKSReturnError; } -int MKBGetDeviceLockState(CFDictionaryRef options) +int +aks_gid_attest(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, void **out_der, size_t *out_der_len) { - if ([SecMockAKS isLocked:key_class_ak]) { - return kMobileKeyBagDeviceIsLocked; - } - return kMobileKeyBagDeviceIsUnlocked; + return kAKSReturnError; } -CF_RETURNS_RETAINED CFDictionaryRef -MKBUserTypeDeviceMode(CFDictionaryRef options, CFErrorRef * error) +int +aks_sik_attest(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, void **out_der, size_t *out_der_len) { - return CFBridgingRetain(@{ - (__bridge NSString *)kMKBDeviceModeKey : (__bridge NSString *)kMKBDeviceModeSingleUser, - }); + return kAKSReturnError; } -int MKBForegroundUserSessionID( CFErrorRef * error) +/* Unimplemented aks_ref_key functions */ + +int +aks_ref_key_compute_key(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, const uint8_t *pub_key, size_t pub_key_len, void **out_der, size_t *out_der_len) { - return kMobileKeyBagSuccess; + return kAKSReturnError; } -const CFTypeRef kAKSKeyAcl = (CFTypeRef)CFSTR("kAKSKeyAcl"); -const CFTypeRef kAKSKeyAclParamRequirePasscode = (CFTypeRef)CFSTR("kAKSKeyAclParamRequirePasscode"); +int +aks_ref_key_attest(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, aks_ref_key_t handle2, void **out_der, size_t *out_der_len) +{ + return kAKSReturnError; +} -const CFTypeRef kAKSKeyOpDefaultAcl = (CFTypeRef)CFSTR("kAKSKeyOpDefaultAcl"); -const CFTypeRef kAKSKeyOpEncrypt = (CFTypeRef)CFSTR("kAKSKeyOpEncrypt"); -const CFTypeRef kAKSKeyOpDecrypt = (CFTypeRef)CFSTR("kAKSKeyOpDecrypt"); -const CFTypeRef kAKSKeyOpSync = (CFTypeRef)CFSTR("kAKSKeyOpSync"); -const CFTypeRef kAKSKeyOpDelete = (CFTypeRef)CFSTR("kAKSKeyOpDelete"); -const CFTypeRef kAKSKeyOpCreate = (CFTypeRef)CFSTR("kAKSKeyOpCreate"); -const CFTypeRef kAKSKeyOpSign = (CFTypeRef)CFSTR("kAKSKeyOpSign"); -const CFTypeRef kAKSKeyOpSetKeyClass = (CFTypeRef)CFSTR("kAKSKeyOpSetKeyClass"); -const CFTypeRef kAKSKeyOpWrap = (CFTypeRef)CFSTR("kAKSKeyOpWrap"); -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"); +int +aks_ref_key_sign(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, const uint8_t *digest, size_t digest_len, void **out_der, size_t *out_der_len) +{ + return kAKSReturnError; +} +int +aks_ref_key_ecies_transcode(aks_ref_key_t handle, uint8_t *der_params, size_t der_params_len, const uint8_t *public_key, size_t public_key_len, const uint8_t *cipher_txt_in, size_t cipher_txt_in_len, uint8_t **cipher_txt_out, size_t *cipher_txt_out_len) +{ + return kAKSReturnError; +} -TKTokenRef TKTokenCreate(CFDictionaryRef attributes, CFErrorRef *error) +keyclass_t +aks_ref_key_get_key_class(aks_ref_key_t handle) { - return NULL; + return key_class_a; } -CFTypeRef TKTokenCopyObjectData(TKTokenRef token, CFDataRef objectID, CFErrorRef *error) +aks_key_type_t +aks_ref_key_get_type(aks_ref_key_t handle) { - return NULL; + return key_type_sym; } -CFDataRef TKTokenCreateOrUpdateObject(TKTokenRef token, CFDataRef objectID, CFMutableDictionaryRef attributes, CFErrorRef *error) +/* AKS Params (unimplemented) */ + +aks_params_t aks_params_create(const uint8_t *der_params, size_t der_params_len) { return NULL; } -CFDataRef TKTokenCopyObjectAccessControl(TKTokenRef token, CFDataRef objectID, CFErrorRef *error) +int aks_params_free(aks_params_t *params) { - return NULL; + return kAKSReturnSuccess; } -bool TKTokenDeleteObject(TKTokenRef token, CFDataRef objectID, CFErrorRef *error) + +int +aks_params_set_data(aks_params_t params, aks_params_key_t key, const void *value, size_t length) { - return false; + return kAKSReturnError; } -CFDataRef TKTokenCopyPublicKeyData(TKTokenRef token, CFDataRef objectID, CFErrorRef *error) +int +aks_params_get_der(aks_params_t params, uint8_t **out_der, size_t *out_der_len) { - return NULL; + return kAKSReturnError; } -CFTypeRef TKTokenCopyOperationResult(TKTokenRef token, CFDataRef objectID, CFIndex secKeyOperationType, CFArrayRef algorithm, - CFIndex secKeyOperationMode, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) +int +aks_params_set_number(aks_params_t params, aks_params_key_t key, int64_t *num) { - return NULL; + return kAKSReturnError; } -CF_RETURNS_RETAINED CFDictionaryRef TKTokenControl(TKTokenRef token, CFDictionaryRef attributes, CFErrorRef *error) +// This is in libaks_internal.h, which doesn't appear to be in the SDK. +int aks_ref_key_enable_test_keys(keybag_handle_t handle, const uint8_t *passcode, size_t passcode_len); +int +aks_ref_key_enable_test_keys(keybag_handle_t handle, const uint8_t *passcode, size_t passcode_len) { - return NULL; + abort(); + return kAKSReturnError; } -CFTypeRef LACreateNewContextWithACMContext(CFDataRef acmContext, CFErrorRef *error) +CFStringRef kMKBDeviceModeMultiUser = CFSTR("kMKBDeviceModeMultiUser"); +CFStringRef kMKBDeviceModeSingleUser = CFSTR("kMKBDeviceModeSingleUser"); +CFStringRef kMKBDeviceModeKey = CFSTR("kMKBDeviceModeKey"); + +static CFStringRef staticKeybagHandle = CFSTR("keybagHandle"); + +int +MKBKeyBagCreateWithData(CFDataRef keybagBlob, MKBKeyBagHandleRef* newHandle) { - return NULL; + *newHandle = (MKBKeyBagHandleRef)staticKeybagHandle; + return kMobileKeyBagSuccess; } -CFDataRef LACopyACMContext(CFTypeRef context, CFErrorRef *error) +int +MKBKeyBagUnlock(MKBKeyBagHandleRef keybag, CFDataRef passcode) { - return NULL; + if (keybag == NULL || !CFEqual(keybag, staticKeybagHandle)) { + abort(); + } + return kMobileKeyBagSuccess; } -bool LAEvaluateAndUpdateACL(CFTypeRef context, CFDataRef acl, CFTypeRef operation, CFDictionaryRef hints, CFDataRef *updatedACL, CFErrorRef *error) +int MKBKeyBagGetAKSHandle(MKBKeyBagHandleRef keybag, int32_t *handle) { - return false; + if (keybag == NULL || !CFEqual(keybag, staticKeybagHandle)) { + abort(); + } + *handle = 17; + return kMobileKeyBagSuccess; +} + +int MKBGetDeviceLockState(CFDictionaryRef options) +{ + if ([SecMockAKS isLocked:key_class_ak]) { + return kMobileKeyBagDeviceIsLocked; + } + return kMobileKeyBagDeviceIsUnlocked; +} + +CF_RETURNS_RETAINED CFDictionaryRef +MKBUserTypeDeviceMode(CFDictionaryRef options, CFErrorRef * error) +{ + return CFBridgingRetain(@{ + (__bridge NSString *)kMKBDeviceModeKey : (__bridge NSString *)kMKBDeviceModeSingleUser, + }); +} + +int MKBForegroundUserSessionID( CFErrorRef * error) +{ + return kMobileKeyBagSuccess; } ACMContextRef diff --git a/tests/secdmockaks/mockaksKeychain.m b/tests/secdmockaks/mockaksKeychain.m index 9a5280f3..e1941e0d 100644 --- a/tests/secdmockaks/mockaksKeychain.m +++ b/tests/secdmockaks/mockaksKeychain.m @@ -46,6 +46,10 @@ #import #import "mockaks.h" +#import + +#import + #import "secdmock_db_version_10_5.h" #import "secdmock_db_version_11_1.h" @@ -725,7 +729,7 @@ } #if !TARGET_OS_WATCH -/* this should be enabled for watch too, but that cause a crash in the mock aks layer */ +/* this should be enabled for watch too, but that causes a crash in the mock aks layer */ - (void)testUpgradeWithBadACLKey { @@ -843,21 +847,30 @@ NSMutableData *mutatedData = [data mutableCopy]; - if (counter < mutatedData.length) { + // This used to loop over all (~850!) bytes of the data but that's too slow. We now do first 50, last 50 and 20 random bytes + if (counter < 50) { mutatedDatabase = true; ((uint8_t *)[mutatedData mutableBytes])[counter] = 'X'; - counter++; + ++counter; + } else if (counter < 70) { + mutatedDatabase = true; + size_t idx = 50 + arc4random_uniform((uint32_t)(mutatedData.length - 100)); + ((uint8_t *)[mutatedData mutableBytes])[idx] = 'X'; + ++counter; + } else if (counter < 120) { + mutatedDatabase = true; + size_t idx = mutatedData.length - (counter - 70 - 1); + ((uint8_t *)[mutatedData mutableBytes])[idx] = 'X'; + ++counter; } else { counter = 0; } - NSString *mutateString = [NSString stringWithFormat:@"UPDATE genp SET data=x'%@'", [mutatedData hexString]]; ok &= SecDbPrepare(dbt, (__bridge CFStringRef)mutateString, &localError2, ^(sqlite3_stmt *stmt) { - ok = SecDbStep(dbt, stmt, NULL, ^(bool *stop) { - }); + ok = SecDbStep(dbt, stmt, NULL, NULL); }); XCTAssertTrue(ok, "corruption should be successful: %@", localError2); CFReleaseNull(localError2); @@ -915,7 +928,98 @@ XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess, "should successfully get item"); } +// This test fails before rdar://problem/60028419 because the keystore fails to check for errSecInteractionNotAllowed, +// tries to recreate the "broken" metadata key and if the keychain unlocks at the exact right moment succeeds and causes +// data loss. +- (void)testMetadataKeyRaceConditionFixed +{ + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"TestAccount-0", + (id)kSecAttrService : @"TestService", + (id)kSecValueData : [@"data" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecUseDataProtectionKeychain : @(YES), + (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlocked, + } mutableCopy]; + + // Create item 1 + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + // Drop metadata keys + SecKeychainDbReset(NULL); + [SecMockAKS setOperationsUntilUnlock:1]; // The first call is the metadata key unwrap to allow encrypting the item + [SecMockAKS lockClassA]; + + query[(id)kSecAttrAccount] = @"TestAcount-1"; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecInteractionNotAllowed); + + query[(id)kSecAttrAccount] = @"TestAccount-0"; + query[(id)kSecValueData] = nil; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecSuccess); + + [SecMockAKS setOperationsUntilUnlock:-1]; +} + +// A test for if LAContext can reasonably be used +// Note that this test can currently _only_ run on iOS in the simulator; on the actual platforms it tries to access +// real AKS/biometrics, which fails in automation environments. +#if TARGET_OS_OSX || TARGET_OS_SIMULATOR + - (void)testLAContext +{ + NSMutableDictionary* simplequery = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"TestAccount-0", + (id)kSecAttrService : @"TestService", + (id)kSecValueData : [@"data" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecUseDataProtectionKeychain : @(YES), + (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlocked, + } mutableCopy]; + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)simplequery, NULL), errSecSuccess, "Succeeded in adding simple item to keychain"); + + CFErrorRef cferror = NULL; + SecAccessControlRef access = SecAccessControlCreateWithFlags(nil, + kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, + kSecAccessControlUserPresence, + &cferror); + + XCTAssertNil((__bridge NSError*)cferror, "Should be no error creating an access control"); + + LAContext* context = [[LAContext alloc] init]; + +#if TARGET_OS_IPHONE || TARGET_OS_OSX + // This field is only usable on iPhone/macOS. It isn't stricly necessary for this test, though. + context.touchIDAuthenticationAllowableReuseDuration = 10; +#endif + + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"TestAccount-LAContext", + (id)kSecAttrService : @"TestService", + (id)kSecValueData : [@"data" dataUsingEncoding:NSUTF8StringEncoding], + (id)kSecUseDataProtectionKeychain : @(YES), + (id)kSecAttrAccessControl : (__bridge id)access, + (id)kSecUseAuthenticationContext : context, + } mutableCopy]; + + XCTAssertEqual(SecItemAdd((__bridge CFDictionaryRef)query, NULL), errSecSuccess, "Succeeded in adding LA-protected item to keychain"); + NSMutableDictionary* findquery = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"TestAccount-LAContext", + (id)kSecAttrService : @"TestService", + (id)kSecUseDataProtectionKeychain : @(YES), + (id)kSecUseAuthenticationContext : context, + (id)kSecReturnAttributes: @YES, + (id)kSecReturnData: @YES, + } mutableCopy]; + + CFTypeRef output = NULL; + XCTAssertEqual(SecItemCopyMatching((__bridge CFDictionaryRef)findquery, &output), errSecSuccess, "Found key in keychain"); + + XCTAssertNotNil((__bridge id)output, "Should have received something back from keychain"); + CFReleaseNull(output); +} +#endif // TARGET_OS_OSX || TARGET_OS_SIMULATOR #endif /* USE_KEYSTORE */ diff --git a/tests/stashtester/main.m b/tests/stashtester/main.m new file mode 100644 index 00000000..b75eb832 --- /dev/null +++ b/tests/stashtester/main.m @@ -0,0 +1,193 @@ +#import +#import +#include + +static void print(NSString* str) { + if (![str hasSuffix:@"\n"]) { + str = [str stringByAppendingString:@"\n"]; + } + [str writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:nil]; +} + +static void usage() { + print(@"Usage: stashtester [commands]"); + print(@""); + print(@"Commands:"); + print(@" -c Combine stash and load requests (equivalent to -s and -l)"); + print(@" -l Send stash login request to securityd (SecKeychainLogin)"); + print(@" -s Send stash request to securityd (SecKeychainStash)"); + print(@" -t Test the complete operation"); +} + +static bool performStash() { + NSLog(@"attempting stash"); + OSStatus result = SecKeychainStash(); + NSLog(@"result from stash: %ld", (long)result); + return result == errSecSuccess; +} + +static bool performLoad() { + NSLog(@"attempting load"); + OSStatus result = SecKeychainLogin(0, NULL, 0, NULL); + NSLog(@"result from load: %ld", (long)result); + return result == errSecSuccess; +} + +static NSMutableDictionary* makeQuery(bool includeData) { + NSMutableDictionary* query = [@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"stashtester", + (id)kSecUseDataProtectionKeychain : @NO, + } mutableCopy]; + if (includeData) { + query[(id)kSecValueData] = [@"sekrit" dataUsingEncoding:NSUTF8StringEncoding]; + } + return query; +} + +static bool performTest() { + NSLog(@"Begin test"); + NSLog(@"Adding item to keychain"); + NSMutableDictionary* addQ = makeQuery(true); + OSStatus result = SecItemAdd((__bridge CFDictionaryRef)addQ, NULL); + if (result != errSecSuccess) { + NSLog(@"Failed to add item pre-stash: %d; aborting test", (int)result); + return false; + } + + if (!performStash()) { + NSLog(@"Stash failed; aborting test"); + return false; + } + + NSLog(@"Locking legacy keychain"); + SecKeychainRef loginkc = NULL; + SecKeychainCopyLogin(&loginkc); + result = SecKeychainCopyLogin(&loginkc); + if (result != errSecSuccess) { + NSLog(@"Unable to obtain reference to login keychain; aborting test"); + return false; + } + result = SecKeychainLock(loginkc); + if (result != errSecSuccess) { + NSLog(@"Unable to lock login keychain; aborting test"); + return false; + } + + SecKeychainStatus status = 0; + result = SecKeychainGetStatus(loginkc, &status); + CFRelease(loginkc); + if (result != errSecSuccess) { + NSLog(@"Unable to get login keychain status; aborting test"); + return false; + } + + if (status & kSecUnlockStateStatus) { + NSLog(@"Login keychain not locked after locking; aborting test"); + return false; + } + + NSLog(@"Locking keybag"); + int rc = MKBLockDevice((__bridge CFDictionaryRef)@{(id)kKeyBagLockDeviceNow : @YES}); + if (rc != kIOReturnSuccess) { + NSLog(@"Failed to lock keybag (%d); aborting test", rc); + return false; + } + + // MKB asynchronously locks bag, make sure we don't race it + NSLog(@"Twiddling thumbs for 11 seconds"); + sleep(11); + + NSLog(@"Verifying keybag is locked"); + NSMutableDictionary* checkQ = makeQuery(false); + checkQ[(id)kSecUseDataProtectionKeychain] = @YES; + result = SecItemAdd((__bridge CFDictionaryRef)checkQ, NULL); + if (result != errSecInteractionNotAllowed) { + NSLog(@"Data protection keychain unexpectedly not locked; aborting test"); + return false; + } + + if (!performLoad()) { + NSLog(@"Failed to load stash (%d); aborting test", result); + return false; + } + + NSMutableDictionary* findQ = makeQuery(false); + findQ[(id)kSecReturnData] = @YES; + CFTypeRef object = NULL; + result = SecItemCopyMatching((__bridge CFDictionaryRef)findQ, &object); + NSData* password; + if (object) { + password = CFBridgingRelease(object); + } + if (result != errSecSuccess || !password || ![[@"sekrit" dataUsingEncoding:NSUTF8StringEncoding] isEqual:password]) { + NSLog(@"Unable to find item post-stashload (%d, %@); aborting test", result, password); + return false; + } + + NSLog(@"Test succeeded"); + return true; +} + +static bool cleanup() { + NSLog(@"Cleaning up"); + NSMutableDictionary* query = makeQuery(false); + OSStatus result = SecItemDelete((__bridge CFDictionaryRef)query); + if (result != errSecSuccess) { + NSLog(@"Cleanup: failed to delete item"); + return false; + } + return true; +} + +int main(int argc, const char * argv[]) { + @autoreleasepool { + bool stash = false; + bool load = false; + bool test = false; + int arg = 0; + char * const *gargv = (char * const *)argv; + while ((arg = getopt(argc, gargv, "clst")) != -1) { + switch (arg) { + case 'c': + stash = true; + load = true; + break; + case 'l': + load = true; + break; + case 's': + stash = true; + break; + case 't': + test = true; + break; + default: + usage(); + return 1; + } + } + + if ((!stash && !load && !test) || + (test && (stash || load))) + { + usage(); + return 1; + } + + if (test) { + bool testresult = performTest(); + bool cleanresult = cleanup(); + return (testresult && cleanresult) ? 0 : -1; + } + + if (stash && !performStash()) { + return -1; + } + + if (load && !performLoad()) { + return -1; + } + } + return 0; +} diff --git a/tests/stashtester/stashtester.entitlements b/tests/stashtester/stashtester.entitlements new file mode 100644 index 00000000..cac44722 --- /dev/null +++ b/tests/stashtester/stashtester.entitlements @@ -0,0 +1,12 @@ + + + + + application-identifier + com.apple.security.private.stashtester + com.apple.private.securityd.stash + + com.apple.keystore.device + + + diff --git a/trust/headers/SecCertificate.h b/trust/headers/SecCertificate.h index fcadd01d..bd29bac2 100644 --- a/trust/headers/SecCertificate.h +++ b/trust/headers/SecCertificate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -154,7 +154,13 @@ CFDataRef SecCertificateCopyNormalizedSubjectSequence(SecCertificateRef certific */ __nullable CF_RETURNS_RETAINED SecKeyRef SecCertificateCopyKey(SecCertificateRef certificate) - API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0)); + API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0), bridgeos(3.0)); + +#if TARGET_OS_OSX && TARGET_CPU_ARM64 +#define SEC_SUFFIX_LEGACYMAC(symbol) __asm("_" __STRING(symbol) "$LEGACYMAC") +#else +#define SEC_SUFFIX_LEGACYMAC(symbol) /**/ +#endif #if TARGET_OS_IPHONE /*! @@ -166,7 +172,7 @@ SecKeyRef SecCertificateCopyKey(SecCertificateRef certificate) */ __nullable SecKeyRef SecCertificateCopyPublicKey(SecCertificateRef certificate) - API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopyKey", ios(10.3, 12.0)) API_UNAVAILABLE(macos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopyKey", ios(10.3, 12.0)) API_UNAVAILABLE(macos, macCatalyst); #endif #if TARGET_OS_OSX @@ -179,7 +185,8 @@ SecKeyRef SecCertificateCopyPublicKey(SecCertificateRef certificate) @discussion NOTE: Deprecated in macOS 10.14; use SecCertificateCopyKey instead for cross-platform availability. */ OSStatus SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef * __nonnull CF_RETURNS_RETAINED key) - API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopyKey", macos(10.3, 10.14)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); + SEC_SUFFIX_LEGACYMAC(SecCertificateCopyPublicKey) + API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopyKey", macos(10.3, 10.14)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, macCatalyst); #endif /*! @@ -191,7 +198,7 @@ OSStatus SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef * */ __nullable CFDataRef SecCertificateCopySerialNumberData(SecCertificateRef certificate, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_13, __IPHONE_11_0); + API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0), bridgeos(3.0)); #if TARGET_OS_IPHONE /*! @@ -202,7 +209,7 @@ CFDataRef SecCertificateCopySerialNumberData(SecCertificateRef certificate, CFEr */ __nullable CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate) - API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopySerialNumberData", ios(10.3, 11.0)) API_UNAVAILABLE(macos, iosmac); + API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopySerialNumberData", ios(10.3, 11.0)) API_UNAVAILABLE(macos, macCatalyst); #endif #if TARGET_OS_OSX @@ -215,7 +222,8 @@ CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate) */ __nullable CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error) - API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopySerialNumberData", macos(10.7, 10.13)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); + SEC_SUFFIX_LEGACYMAC(SecCertificateCopySerialNumber) + API_DEPRECATED_WITH_REPLACEMENT("SecCertificateCopySerialNumberData", macos(10.7, 10.13)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, macCatalyst); #endif /* @@ -463,8 +471,8 @@ extern const CFStringRef kSecPropertyTypeData __OSX_AVAILABLE_STARTING(__MAC_10_ extern const CFStringRef kSecPropertyTypeString __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPropertyTypeURL __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPropertyTypeDate __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFStringRef kSecPropertyTypeArray API_AVAILABLE(macos(10.15)) SPI_AVAILABLE(ios(13.0), watchos(6.0), tvos(13.0), iosmac(13.0)); -extern const CFStringRef kSecPropertyTypeNumber API_AVAILABLE(macos(10.15)) SPI_AVAILABLE(ios(13.0), watchos(6.0), tvos(13.0), iosmac(13.0)); +extern const CFStringRef kSecPropertyTypeArray API_AVAILABLE(macos(10.15)) SPI_AVAILABLE(ios(13.0), watchos(6.0), tvos(13.0), macCatalyst(13.0)); +extern const CFStringRef kSecPropertyTypeNumber API_AVAILABLE(macos(10.15)) SPI_AVAILABLE(ios(13.0), watchos(6.0), tvos(13.0), macCatalyst(13.0)); /*! @function SecCertificateCopyValues diff --git a/trust/headers/SecCertificatePriv.h b/trust/headers/SecCertificatePriv.h index 086f48ac..417e8ecd 100644 --- a/trust/headers/SecCertificatePriv.h +++ b/trust/headers/SecCertificatePriv.h @@ -463,6 +463,15 @@ bool SecCertificateGetDeveloperIDDate(SecCertificateRef certificate, CFAbsoluteT CFAbsoluteTime SecAbsoluteTimeFromDateContentWithError(DERTag tag, const uint8_t *bytes, size_t length, CFErrorRef *error); +/* Return the (last) attribute value from the Subject DN with the indicated Attribute OID. + * This suits as a replacement for SecCertificateCopySubjectComponent */ +CFStringRef SecCertificateCopySubjectAttributeValue(SecCertificateRef cert, DERItem *attributeOID) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); + +/* Return the external roots (for use with SecTrustSetAnchorCertificates) */ +CFArrayRef SecCertificateCopyAppleExternalRoots(void) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); + /* * Legacy functions (OS X only) */ @@ -579,7 +588,7 @@ OSStatus SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, con */ OSStatus SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result) - __OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_10_0, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA, "SecCertificateCopySubjectComponent is deprecated. Use SecCertificateCopyCommonNames,SecCertificateCopyOrganization,SecCertificateCopyOrganizationalUnit, etc. instead."); + __OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_10_0, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA, "SecCertificateCopySubjectComponent is deprecated. Use SecCertificateCopySubjectAttributeValue instead."); /* Convenience functions for searching. */ diff --git a/trust/headers/SecPolicy.h b/trust/headers/SecPolicy.h index 59e95b54..a3c19456 100644 --- a/trust/headers/SecPolicy.h +++ b/trust/headers/SecPolicy.h @@ -73,9 +73,9 @@ extern const CFStringRef kSecPolicyAppleiChat __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); #endif extern const CFStringRef kSecPolicyApplePKINITClient - API_AVAILABLE(macos(10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); extern const CFStringRef kSecPolicyApplePKINITServer - API_AVAILABLE(macos(10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + API_AVAILABLE(macos(10.7)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst); extern const CFStringRef kSecPolicyAppleCodeSigning __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); extern const CFStringRef kSecPolicyMacAppStoreReceipt diff --git a/trust/headers/SecPolicyPriv.h b/trust/headers/SecPolicyPriv.h index 3927772e..85f6237f 100644 --- a/trust/headers/SecPolicyPriv.h +++ b/trust/headers/SecPolicyPriv.h @@ -59,12 +59,6 @@ extern const CFStringRef kSecPolicyAppleQAProfileSigner __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); extern const CFStringRef kSecPolicyAppleServerAuthentication __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); -extern const CFStringRef kSecPolicyAppleOTAPKISigner - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_12, __MAC_10_13_4, __IPHONE_7_0, __IPHONE_11_3); -extern const CFStringRef kSecPolicyAppleTestOTAPKISigner - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_12, __MAC_10_13_4, __IPHONE_7_0, __IPHONE_11_3); -extern const CFStringRef kSecPolicyAppleIDValidationRecordSigningPolicy - API_DEPRECATED_WITH_REPLACEMENT("kSecPolicyAppleIDValidationRecordSigning", ios(7.0,10.0), macos(10.9,10.12)); extern const CFStringRef kSecPolicyAppleIDValidationRecordSigning __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); extern const CFStringRef kSecPolicyAppleSMPEncryption @@ -191,10 +185,18 @@ extern const CFStringRef kSecPolicyAppleAlisha API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); extern const CFStringRef kSecPolicyAppleMeasuredBootPolicySigning API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); +extern const CFStringRef kSecPolicyApplePayQRCodeEncryption + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); +extern const CFStringRef kSecPolicyApplePayQRCodeSigning + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); +extern const CFStringRef kSecPolicyAppleAccessoryUpdateSigning + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); extern const CFStringRef kSecPolicyAppleEscrowServiceIdKeySigning API_AVAILABLE(macos(10.15.6), ios(13.5.5)); extern const CFStringRef kSecPolicyApplePCSEscrowServiceIdKeySigning API_AVAILABLE(macos(10.15.6), ios(13.5.5)); +extern const CFStringRef kSecPolicyAppleAggregateMetricTransparency + API_AVAILABLE(macos(10.15.6), ios(13.6), watchos(6.2), tvos(13.4)); /*! @@ -219,6 +221,7 @@ extern const CFStringRef kSecPolicyApplePCSEscrowServiceIdKeySigning @constant kSecPolicyNameAppleSiriService @constant kSecPolicyNameAppleHomeAppClipUploadService @constant kSecPolicyNameAppleUpdatesService + @constant kSecPolicyNameApplePushCertPortal */ extern const CFStringRef kSecPolicyNameAppleAST2Service __OSX_AVAILABLE(10.13) __IOS_AVAILABLE(11.0) __TVOS_AVAILABLE(11.0) __WATCHOS_AVAILABLE(4.0); @@ -256,6 +259,8 @@ extern const CFStringRef kSecPolicyNameAppleHomeAppClipUploadService API_AVAILABLE(macos(10.15.1), ios(13.2), watchos(6.1), tvos(13.1)); extern const CFStringRef kSecPolicyNameAppleUpdatesService API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); +extern const CFStringRef kSecPolicyNameApplePushCertPortal + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); /*! @enum Policy Value Constants @@ -335,10 +340,7 @@ CF_ENUM(CFOptionFlags) { in the leaf certificate. @discussion The resulting policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if the value true is set for the key - "ApplePinningAllowTestCerts%@" (where %@ is the policyName parameter) in the - com.apple.security preferences for the user of the calling application. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID matching the intermediateMarkerOID parameter. @@ -365,16 +367,12 @@ SecPolicyRef SecPolicyCreateApplePinned(CFStringRef policyName, in the leaf certificate. @discussion The resulting policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if the value true is set for the key - "ApplePinningAllowTestCerts%@" (where %@ is the policyName parameter) in the - com.apple.security preferences for the user of the calling application. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID matching the intermediateMarkerOID parameter, or 1.2.840.113635.100.6.2.12 if NULL is passed. * The leaf has a marker extension with OID matching the leafMarkerOID parameter. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. @@ -392,8 +390,7 @@ SecPolicyRef SecPolicyCreateAppleSSLPinned(CFStringRef policyName, CFStringRef h certificate chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "iPhone Activation". @@ -409,8 +406,7 @@ SecPolicyRef SecPolicyCreateiPhoneActivation(void); chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs * There are exactly 4 certs in chain. * The first intermediate has Common Name "Apple iPhone Device CA". @result A policy object. The caller is responsible for calling CFRelease @@ -502,8 +498,7 @@ SecPolicyRef SecPolicyCreateIPSec(Boolean server, CFStringRef __nullable hostna @abstract Returns a policy object for evaluating SW update signing certs. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate ExtendedKeyUsage Extension contains 1.2.840.113635.100.4.1. * The leaf ExtendedKeyUsage extension contains 1.2.840.113635.100.4.1. @@ -518,8 +513,7 @@ SecPolicyRef SecPolicyCreateAppleSWUpdateSigning(void); @abstract Returns a policy object for evaluating installer package signing certs. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The leaf KeyUsage extension has the digital signature bit set. * The leaf ExtendedKeyUsage extension has the CodeSigning OID. @@ -535,8 +529,7 @@ SecPolicyRef SecPolicyCreateApplePackageSigning(void); signatures. This is for apps signed directly by the app store. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "Apple iPhone OS Application Signing". @@ -556,8 +549,7 @@ SecPolicyRef SecPolicyCreateiPhoneApplicationSigning(void); signatures. This is for VPN plugins signed directly by the VPN team. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "Apple iPhone OS Application Signing". @@ -578,8 +570,7 @@ SecPolicyRef SecPolicyCreateiPhoneVPNApplicationSigning(void) profile. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID matching 1.2.840.113635.100.6.2.1 (WWDR CA). * The leaf has a marker extension with OID matching one of the following: @@ -602,8 +593,7 @@ SecPolicyRef SecPolicyCreateiPhoneProfileApplicationSigning(void); profile. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The leaf has a marker extension with OID matching one of the following: * 1.2.840.113635.100.6.1.7 ("3rd Party Mac Developer Application" leaf) @@ -624,8 +614,7 @@ SecPolicyRef SecPolicyCreateMacOSProfileApplicationSigning(void) @abstract Returns a policy object for evaluating provisioning profile signatures. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "Apple iPhone OS Provisioning Profile Signing". @@ -645,7 +634,7 @@ SecPolicyRef SecPolicyCreateiPhoneProvisioningProfileSigning(void); and allows for both the prod and the dev/test certs. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. Test roots are never permitted. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.1. @@ -693,8 +682,7 @@ enum { @discussion This policy uses the Basic X.509 policy with validity check and requires the leaf to have * a KeyUsage matching the smimeUsage, - * an ExtendedKeyUsage, if any, with the AnyExtendedKeyUsage OID or the - EmailProtection OID, and + * an ExtendedKeyUsage, if any, with the EmailProtection OID, and * if the email param is specified, the email address in the RFC822Name in the SubjectAlternativeName extension or in the Email Address field of the Subject Name. @@ -745,8 +733,7 @@ SecPolicyRef SecPolicyCreateURLBag(void); @abstract Returns a policy object for evaluating certificate chains for signing OTA Tasking. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "OTA Task Signing". @@ -761,8 +748,7 @@ SecPolicyRef SecPolicyCreateOTATasking(void); @abstract Returns a policy object for evaluating certificate chains for signing Mobile Assets. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple iPhone Certification Authority". * The leaf has Common Name "Asset Manifest Signing". @@ -778,8 +764,7 @@ SecPolicyRef SecPolicyCreateMobileAsset(void); Mobile Assets. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.18. * The leaf has a marker extension with OID 1.2.840.113635.100.6.55.1. @@ -795,8 +780,7 @@ SecPolicyRef SecPolicyCreateMobileAssetDevelopment(void) @abstract Returns a policy object for evaluating certificate chains for Apple ID Authority. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The intermediate(s) has(have) a marker extension with OID 1.2.840.113635.100.6.2.3 or OID 1.2.840.113635.100.6.2.7. * The leaf has a marker extension with OID 1.2.840.113635.100.4.7. @@ -813,8 +797,7 @@ SecPolicyRef SecPolicyCreateAppleIDAuthorityPolicy(void); Mac App Store Receipts. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.1. * The leaf has CertificatePolicy extension with OID 1.2.840.113635.100.5.6.1. @@ -834,8 +817,7 @@ SecPolicyRef SecPolicyCreateMacAppStoreReceipt(void); team ID to match the organizationalUnit field in the leaf certificate's subject. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The leaf has a marker extension with OID 1.2.840.113635.100.6.1.16 and containing the cardIssuer. * The leaf has ExtendedKeyUsage with OID 1.2.840.113635.100.4.14. @@ -852,8 +834,7 @@ SecPolicyRef SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, @abstract Returns a policy object for evaluating Mobile Store certificate chains. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple System Integration 2 Certification Authority". * The leaf has KeyUsage with the DigitalSignature bit set. @@ -869,8 +850,7 @@ SecPolicyRef SecPolicyCreateMobileStoreSigner(void); @abstract Returns a policy object for evaluating Test Mobile Store certificate chains. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple System Integration 2 Certification Authority". * The leaf has KeyUsage with the DigitalSignature bit set. @@ -886,7 +866,6 @@ SecPolicyRef SecPolicyCreateTestMobileStoreSigner(void); @abstract Returns a policy object for evaluating Escrow Service certificate chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to the current Escrow Roots in the OTAPKI asset. * There are exactly 2 certs in the chain. * The leaf has KeyUsage with the KeyEncipherment bit set. @result A policy object. The caller is responsible for calling CFRelease @@ -900,7 +879,6 @@ SecPolicyRef SecPolicyCreateEscrowServiceSigner(void); @abstract Returns a policy object for evaluating PCS Escrow Service certificate chains. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to the current PCS Escrow Roots in the OTAPKI asset. * There are exactly 2 certs in the chain. * The leaf has KeyUsage with the KeyEncipherment bit set. @result A policy object. The caller is responsible for calling CFRelease @@ -915,8 +893,7 @@ SecPolicyRef SecPolicyCreatePCSEscrowServiceSigner(void); Provisioning Profiles. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.1. * The leaf has KeyUsage with the DigitalSignature bit set. * The leaf has a marker extension with OID 1.2.840.113635.100.4.11. @@ -933,8 +910,7 @@ SecPolicyRef SecPolicyCreateOSXProvisioningProfileSigning(void); Configuration Profiles. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.3. * The leaf has ExtendedKeyUsage with OID 1.2.840.113635.100.4.16. @@ -951,8 +927,7 @@ SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void); policy as SecPolicyCreateConfigurationProfileSigner. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.3. * The leaf has ExtendedKeyUsage with OID 1.2.840.113635.100.4.17. @result A policy object. The caller is responsible for calling CFRelease @@ -961,42 +936,13 @@ SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void); __nullable CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void); -/*! - @function SecPolicyCreateOTAPKISigner - @abstract Returns a policy object for evaluating OTA PKI certificate chains. - @discussion This policy uses the Basic X.509 policy with validity check - and pinning options: - * The chain is anchored to Apple PKI Settings CA. - * There are exactly 2 certs in the chain. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -__nullable CF_RETURNS_RETAINED -SecPolicyRef SecPolicyCreateOTAPKISigner(void) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_12, __MAC_10_13_4, __IPHONE_7_0, __IPHONE_11_3); - -/*! - @function SecPolicyCreateTestOTAPKISigner - @abstract Returns a policy object for evaluating OTA PKI certificate chains. - @discussion This policy uses the Basic X.509 policy with validity check - and pinning options: - * The chain is anchored to Apple Test PKI Settings CA. - * There are exactly 2 certs in the chain. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -__nullable CF_RETURNS_RETAINED -SecPolicyRef SecPolicyCreateTestOTAPKISigner(void) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_12, __MAC_10_13_4, __IPHONE_7_0, __IPHONE_11_3); - /*! @function SecPolicyCreateAppleIDValidationRecordSigningPolicy @abstract Returns a policy object for evaluating certificate chains for signing Apple ID Validation Records. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The intermediate(s) has(have) a marker extension with OID 1.2.840.113635.100.6.2.3 or OID 1.2.840.113635.100.6.2.10. * The leaf has a marker extension with OID 1.2.840.113635.100.6.25. @@ -1012,8 +958,7 @@ SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void); @abstract Returns a policy object for evaluating SMP certificate chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.13. * The leaf has KeyUsage with the KeyEncipherment bit set. @@ -1046,8 +991,7 @@ SecPolicyRef SecPolicyCreateTestAppleSMPEncryption(void); @abstract Returns a policy object for verifying production PPQ Signing certificates. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple System Integration 2 Certification Authority". @@ -1066,8 +1010,7 @@ SecPolicyRef SecPolicyCreateApplePPQSigning(void); customer builds, this function returns the same policy as SecPolicyCreateApplePPQSigning. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple System Integration 2 Certification Authority". @@ -1083,7 +1026,16 @@ SecPolicyRef SecPolicyCreateTestApplePPQSigning(void); /*! @function SecPolicyCreateAppleIDSService @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) - @discussion This policy uses the SSL server policy. + @discussion This policy uses the Basic X.509 policy with validity check + and pinning options: + * The chain is anchored to any of the Apple Root CAs. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. + * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.4.2 or, + if Test Roots are allowed, OID 1.2.840.113635.100.6.27.4.1. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName + extension. + * The leaf has ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. */ @@ -1098,15 +1050,11 @@ SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef __nullable hostname); Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted only on internal releases either using the context dictionary or with - defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.4.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.4.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1123,15 +1071,11 @@ SecPolicyRef SecPolicyCreateAppleIDSServiceContext(CFStringRef hostname, CFDicti Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted only on internal releases either using the context dictionary or with - defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.5.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.5.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1147,9 +1091,7 @@ SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname, CFDictionaryR @discussion This policy uses the Basic X.509 policy with validity check and pinning options: * The chain is anchored to an Entrust Intermediate. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1166,12 +1108,11 @@ SecPolicyRef SecPolicyCreateApplePushServiceLegacy(CFStringRef hostname); Boolean true will allow Test Apple roots and test OIDs on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.11.2 or, if enabled, OID 1.2.840.113635.100.6.27.11.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1192,9 +1133,7 @@ SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname, CFDictionaryR * The chain length is 3. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.11.2 or OID 1.2.840.113635.100.6.27.11.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. @@ -1211,14 +1150,10 @@ SecPolicyRef SecPolicyCreateAppleCompatibilityMMCSService(CFStringRef hostname) Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted only on internal releases either using the context dictionary or with - defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.2. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1236,15 +1171,11 @@ SecPolicyRef SecPolicyCreateAppleGSService(CFStringRef hostname, CFDictionaryRef Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted only on internal releases either using the context dictionary or with - defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.3.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.3.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1262,14 +1193,11 @@ SecPolicyRef SecPolicyCreateApplePPQService(CFStringRef hostname, CFDictionaryRe Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted either using the context dictionary or with defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.8.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.8.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1287,15 +1215,11 @@ SecPolicyRef SecPolicyCreateAppleAST2Service(CFStringRef hostname, CFDictionaryR Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs via full certificate - comparison. Test Apple Root CAs are permitted only on internal releases either - using the context dictionary or with defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.7.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.7.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1318,9 +1242,7 @@ SecPolicyRef SecPolicyCreateAppleEscrowProxyService(CFStringRef hostname, CFDict * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.7.2 or, if UAT is enabled with a defaults write (internal devices only), OID 1.2.840.113635.100.6.27.7.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. @@ -1337,15 +1259,11 @@ __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); Boolean true will allow Test Apple roots on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs via full certificate - comparison. Test Apple Root CAs are permitted only on internal releases either - using the context dictionary or with defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.6.2 or, if Test Roots are allowed, OID 1.2.840.113635.100.6.27.6.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1361,13 +1279,10 @@ SecPolicyRef SecPolicyCreateAppleFMiPService(CFStringRef hostname, CFDictionaryR @param hostname Optional; hostname to verify the certificate name against. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.1 - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage, if any, with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1392,8 +1307,7 @@ SecPolicyRef SecPolicyCreateAppleTimeStamping(void); @abstract Returns a policy object for evaluating Apple Pay Issuer Encryption certificate chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has Common Name "Apple Worldwide Developer Relations CA - G2". * The leaf has KeyUsage with the KeyEncipherment bit set. @@ -1410,8 +1324,7 @@ SecPolicyRef SecPolicyCreateApplePayIssuerEncryption(void) @abstract Returns a policy object for evaluating Apple TV VPN Profile certificate chains. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Test Apple Root CAs - are permitted only on internal releases. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.10. * The leaf has a marker extension with OID 1.2.840.113635.100.6.43. @@ -1429,13 +1342,10 @@ SecPolicyRef SecPolicyCreateAppleATVVPNProfileSigning(void) @param hostname Required; hostname to verify the certificate name against. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs via full certificate - comparison. Test Apple Root CAs are permitted only on internal releases with defaults write. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.16 * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.9. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1451,8 +1361,7 @@ SecPolicyRef SecPolicyCreateAppleHomeKitServerAuth(CFStringRef hostname) certificates. @discussion The resulting policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID matching 1.2.840.113635.100.6.2.1 (WWDR CA) or 1.2.840.113635.100.6.2.6 (Developer ID CA). @@ -1484,8 +1393,7 @@ SecPolicyRef SecPolicyCreateAppleExternalDeveloper(void) @abstract Returns a policy object for verifying the Apple Software Signing certificate. @discussion The resulting policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has the Common Name "Apple Code Signing Certification Authority". * The leaf has a marker extension with OID matching 1.2.840.113635.100.6.22. @@ -1544,8 +1452,7 @@ SecPolicyRef SecPolicyCreateAppleUniqueDeviceCertificate(CFDataRef __nullable te @abstract Returns a policy object for verifying signed Warsaw assets. @discussion The resulting policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has an extension with OID matching 1.2.840.113635.100.6.2.14. * The leaf has a marker extension with OID matching 1.2.840.113635.100.6.29. @@ -1562,8 +1469,7 @@ SecPolicyRef SecPolicyCreateAppleWarsaw(void) @abstract Returns a policy object for verifying signed static assets for Secure IO. @discussion The resulting policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has an extension with OID matching 1.2.840.113635.100.6.2.10. * The leaf has a marker extension with OID matching 1.2.840.113635.100.6.50. @@ -1583,12 +1489,11 @@ SecPolicyRef SecPolicyCreateAppleSecureIOStaticAsset(void) Boolean true will allow Test Apple roots and test OIDs on internal releases. @discussion This policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.12. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.15.2 or, if enabled, OID 1.2.840.113635.100.6.27.15.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. * Revocation is checked via any available method. @result A policy object. The caller is responsible for calling CFRelease @@ -1610,9 +1515,7 @@ SecPolicyRef SecPolicyCreateAppleiCloudSetupService(CFStringRef hostname, CFDict * The chain length is 3. * The leaf has a marker extension with OID 1.2.840.113635.100.6.27.15.2 or OID 1.2.840.113635.100.6.27.15.1. - * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName - extension or Common Name. - * The leaf is checked against the Black and Gray lists. + * The leaf has the provided hostname in the DNSName of the SubjectAlternativeName extension. * The leaf has ExtendedKeyUsage with the ServerAuth OID. @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. @@ -1639,8 +1542,7 @@ SecPolicyRef SecPolicyCreateAppleAppTransportSecurity(void) @abstract Returns a policy object for evaluating certificate chains for signing Mobile Software Updates. @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.18. * The leaf has a marker extension with OID 1.2.840.113635.100.6.57.2, or on internal releases, @@ -1720,8 +1622,7 @@ SecPolicyRef SecPolicyCreateDemoDigitalCatalogSigning(void) @abstract Returns a policy object for evaluating certificate chains for signing Asset Receipts @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. Internal releases allow - the chain to be anchored to Test Apple Root CAs if a defaults write for the policy is set. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.10. * The leaf has a marker extension with OID 1.2.840.113635.100.6.61. @@ -1738,7 +1639,7 @@ SecPolicyRef SecPolicyCreateAppleAssetReceipt(void) @abstract Returns a policy object for evaluating certificate chains for signing Developer ID+ Tickets @discussion This policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.17. * The leaf has a marker extension with OID 1.2.840.113635.100.6.1.30. @@ -1800,7 +1701,7 @@ SecPolicyRef SecPolicyCreateAppleComponentCertificate(CFDataRef __nullable testR @param applicationId A string that identifies the applicationId. @discussion The resulting policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to any of the production Apple Root CAs. + * The chain is anchored to any of the Apple Root CAs. * There are exactly 3 certs in the chain. * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.3". * The leaf has a marker extension with OID 1.2.840.113635.100.6.69.1 and value @@ -1845,6 +1746,10 @@ SecPolicyRef SecPolicyCreateLegacySSL(Boolean server, CFStringRef __nullable hos __nullable CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateAlisha(void) API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); +extern const CFStringRef kSecPolicyAppleEscrowServiceIdKeySigning + API_AVAILABLE(macos(10.15.6), ios(13.5.5)); +extern const CFStringRef kSecPolicyApplePCSEscrowServiceIdKeySigning + API_AVAILABLE(macos(10.15.6), ios(13.5.5)); /*! @function SecPolicyCreateMeasuredBootPolicySigning @@ -1865,36 +1770,87 @@ SecPolicyRef SecPolicyCreateMeasuredBootPolicySigning(void) API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4)); /*! - @function SecPolicyCreateEscrowServiceIdKeySigning - @abstract Returns a policy object for verifying Escrow Service ID keys. - @discussion The resulting policy uses the Basic X.509 policy with no validity check and + @function SecPolicyCreateApplePayQRCodeEncryption + @abstract Returns a policy object for verifying ApplePay QRCode Encryption certificates + @discussion The resulting policy uses the Basic X.509 policy with validity check and pinning options: - * The chain is anchored to the current Escrow Roots in the OTAPKI asset. - * There are exactly 2 certs in the chain. - * The leaf has KeyUsage with the DigitalSignature bit set. - * CN matching the name generated by escrow service. + * The root matches the "Apple External EC Root", or on internal builds, "Test Apple External EC Root" + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.22. + * The leaf has a marker extension with OID 1.2.840.113635.100.13.3 + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + * Revocation is checked via any available method + Because the "Apple External" roots are not trusted by default, the caller must use + SecTrustSetAnchorCertificates with the expected roots. @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. */ __nullable CF_RETURNS_RETAINED -SecPolicyRef SecPolicyCreateEscrowServiceIdKeySigning(void) - API_AVAILABLE(macos(10.15.6), ios(13.6)); +SecPolicyRef SecPolicyCreateApplePayQRCodeEncryption(void) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); /*! - @function SecPolicyCreatePCSEscrowServiceIdKeySigning - @abstract Returns a policy object for verifying PCS Escrow Service ID keys. + @function SecPolicyCreateApplePayQRCodeSigning + @abstract Returns a policy object for verifying ApplePay QRCode Signing certificates + @discussion The resulting policy uses the Basic X.509 policy with validity check and + pinning options: + * The root matches the "Apple External EC Root", or on internal builds, "Test Apple External EC Root" + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.22. + * The leaf has a marker extension with OID 1.2.840.113635.100.12.12 + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + * Revocation is checked via any available method + Because the "Apple External" roots are not trusted by default, the caller must use + SecTrustSetAnchorCertificates with the expected roots. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateApplePayQRCodeSigning(void) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); + +/*! + @function SecPolicyCreateAppleAccessoryUpdateSigning + @abstract Returns a policy object for verifying Accessory Firmware Update Signing certificates @discussion The resulting policy uses the Basic X.509 policy with no validity check and pinning options: - * The chain is anchored to the current Escrow Roots in the OTAPKI asset. - * There are exactly 2 certs in the chain. - * The leaf has KeyUsage with the DigitalSignature bit set. - * CN matching the name generated by escrow service. + * The chain is anchored to any of the Apple Root CAs. + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.17. + * The leaf has a marker extension with OID 1.2.840.113635.100.12.9, or, if + "AllowAccessoryUpdateSigningBeta" is set to true in the com.apple.security + preference/defaults domain, OID 1.2.840.113635.100.12.10 + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + * Revocation is checked via any available method @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. */ __nullable CF_RETURNS_RETAINED -SecPolicyRef SecPolicyCreatePCSEscrowServiceIdKeySigning(void) - API_AVAILABLE(macos(10.15.6), ios(13.6)); +SecPolicyRef SecPolicyCreateAppleAccessoryUpdateSigning(void) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); + +/*! + @function SecPolicyCreateAggregateMetricTransparency + @abstract Returns a policy object for verifying Aggregate Metric Transparency certificates + @param facilitator A boolean to indicate whether the facilitator or partner transparency + certificate is being checked. + @discussion The resulting policy uses the Basic X.509 policy with validity check and + pinning options: + * The chain is anchored to any of the Apple Root CAs. + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.26. + * The leaf has a marker extension with OID 1.2.840.113635.100.12.17 if facilitator is true or + 1.2.840.113635.100.12.18 if facilitator is false. The contents of this marker extension + are not checked. + * Revocation is checked via any available method. + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + * Require a positive CT verification result. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAggregateMetricTransparency(bool facilitator) + API_AVAILABLE(macos(10.15.6), ios(13.6), watchos(6.2), tvos(13.4)); /* * Legacy functions (OS X only) @@ -1914,21 +1870,6 @@ SecPolicyRef SecPolicyCreatePCSEscrowServiceIdKeySigning(void) OSStatus SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef * __nonnull CF_RETURNS_RETAINED policy) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); -/*! - @function SecPolicyCopyAll - @abstract Returns an array of all known policies based on certificate type. - @param certificateType A certificate type. This is a optional parameter. Pass CSSM_CERT_UNKNOWN if the certificate type is unknown. - @param policies The returned array of policies. This is a required parameter. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later; - to obtain a policy reference, use one of the SecPolicyCreate* functions in SecPolicy.h. (Note: there is normally - no reason to iterate over multiple disjointed policies, except to provide a way to edit trust settings for each - policy, as is done in certain certificate UI views. In that specific case, your code should call SecPolicyCreateWithOID - for each desired policy from the list of supported OID constants in SecPolicy.h.) - */ -OSStatus SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef * __nonnull CF_RETURNS_RETAINED policies) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - /* Given a unified SecPolicyRef, return a copy with a legacy C++ ItemImpl-based Policy instance. Only for internal use; legacy references cannot be used by SecPolicy API functions. */ @@ -1964,7 +1905,6 @@ CFArrayRef SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef polic policy. Use outside of the Security project at your own peril. */ extern const CFStringRef kSecPolicyCheckAnchorApple; -extern const CFStringRef kSecPolicyCheckAnchorSHA1; extern const CFStringRef kSecPolicyCheckAnchorSHA256; extern const CFStringRef kSecPolicyCheckAnchorTrusted; extern const CFStringRef kSecPolicyCheckBasicCertificateProcessing; @@ -1983,6 +1923,7 @@ extern const CFStringRef kSecPolicyCheckExtendedKeyUsage; extern const CFStringRef kSecPolicyCheckExtendedValidation; extern const CFStringRef kSecPolicyCheckGrayListedKey; extern const CFStringRef kSecPolicyCheckGrayListedLeaf; +extern const CFStringRef kSecPolicyCheckLeafSPKISHA256; extern const CFStringRef kSecPolicyCheckIdLinkage; extern const CFStringRef kSecPolicyCheckIntermediateCountry; extern const CFStringRef kSecPolicyCheckIntermediateEKU; @@ -1990,6 +1931,7 @@ extern const CFStringRef kSecPolicyCheckIntermediateMarkerOid; extern const CFStringRef kSecPolicyCheckIntermediateMarkerOidWithoutValueCheck; extern const CFStringRef kSecPolicyCheckIntermediateOrganization; extern const CFStringRef kSecPolicyCheckIntermediateSPKISHA256; +extern const CFStringRef kSecPolicyCheckCAspkiSHA256; extern const CFStringRef kSecPolicyCheckIssuerCommonName; extern const CFStringRef kSecPolicyCheckIssuerPolicyConstraints; extern const CFStringRef kSecPolicyCheckIssuerNameConstraints; @@ -2002,6 +1944,7 @@ extern const CFStringRef kSecPolicyCheckMissingIntermediate; extern const CFStringRef kSecPolicyCheckNameConstraints; extern const CFStringRef kSecPolicyCheckNoNetworkAccess; extern const CFStringRef kSecPolicyCheckNonEmptySubject; +extern const CFStringRef kSecPolicyCheckNotCA; extern const CFStringRef kSecPolicyCheckNotValidBefore; extern const CFStringRef kSecPolicyCheckPinningRequired; extern const CFStringRef kSecPolicyCheckPolicyConstraints; @@ -2053,6 +1996,38 @@ extern const CFStringRef kSecPolicyNameCodeSigning; extern const CFStringRef kSecPolicyNameTimeStamping; extern const CFStringRef kSecPolicyNameOCSPSigner; +/*! + @function SecPolicyCreateEscrowServiceIdKeySigning + @abstract Returns a policy object for verifying Escrow Service ID keys. + @discussion The resulting policy uses the Basic X.509 policy with no validity check and + pinning options: + * The chain is anchored to the current Escrow Roots in the OTAPKI asset. + * There are exactly 2 certs in the chain. + * The leaf has KeyUsage with the DigitalSignature bit set. + * CN matching the name generated by escrow service. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateEscrowServiceIdKeySigning(void) + API_AVAILABLE(macos(10.15.6), ios(13.6)); + +/*! + @function SecPolicyCreatePCSEscrowServiceIdKeySigning + @abstract Returns a policy object for verifying PCS Escrow Service ID keys. + @discussion The resulting policy uses the Basic X.509 policy with no validity check and + pinning options: + * The chain is anchored to the current Escrow Roots in the OTAPKI asset. + * There are exactly 2 certs in the chain. + * The leaf has KeyUsage with the DigitalSignature bit set. + * CN matching the name generated by escrow service. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreatePCSEscrowServiceIdKeySigning(void) + API_AVAILABLE(macos(10.15.6), ios(13.6)); + /* * MARK: SecPolicyCheckCert functions */ @@ -2080,6 +2055,7 @@ bool SecPolicyCheckCertCertificatePolicy(SecCertificateRef cert, CFTypeRef pvcVa bool SecPolicyCheckCertCriticalExtensions(SecCertificateRef cert, CFTypeRef __nullable pvcValue); bool SecPolicyCheckCertSubjectCountry(SecCertificateRef cert, CFTypeRef pvcValue); bool SecPolicyCheckCertUnparseableExtension(SecCertificateRef cert, CFTypeRef pvcValue); +bool SecPolicyCheckCertNotCA(SecCertificateRef cert, CFTypeRef pvcValue); void SecPolicySetName(SecPolicyRef policy, CFStringRef policyName); __nullable CFArrayRef SecPolicyXPCArrayCopyArray(xpc_object_t xpc_policies, CFErrorRef *error); @@ -2088,6 +2064,10 @@ void SecPolicySetOptionsValue(SecPolicyRef policy, CFStringRef key, CFTypeRef va bool SecDNSIsTLD(CFStringRef reference); +CFDataRef CreateCFDataFromBase64CFString(CFStringRef base64string); +CFArrayRef parseNSPinnedDomains(CFDictionaryRef nsPinnedDomainsDict, CFStringRef hostName, CFStringRef nsPinnedIdentityType); +void SecPolicyReconcilePinningRequiredIfInfoSpecified(CFMutableDictionaryRef options); + CF_IMPLICIT_BRIDGING_DISABLED CF_ASSUME_NONNULL_END diff --git a/trust/headers/SecTrust.h b/trust/headers/SecTrust.h index a48083cd..a8c7f975 100644 --- a/trust/headers/SecTrust.h +++ b/trust/headers/SecTrust.h @@ -463,7 +463,22 @@ OSStatus SecTrustGetTrustResult(SecTrustRef trust, */ __nullable SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + API_DEPRECATED_WITH_REPLACEMENT("SecTrustCopyKey", macos(10.7, 10.16), ios(2.0, 14.0), watchos(1.0, 7.0), tvos(9.0, 14.0)); + +/*! + @function SecTrustCopyKey + @abstract Return the public key for a leaf certificate after it has + been evaluated. + @param trust A reference to the trust object which has been evaluated. + @result The certificate's public key, or NULL if it the public key could + not be extracted (this can happen if the public key algorithm is not + supported). The caller is responsible for calling CFRelease on the + returned key when it is no longer needed. + @discussion RSA and ECDSA public keys are supported. All other public key algorithms are unsupported. + */ +__nullable +SecKeyRef SecTrustCopyKey(SecTrustRef trust) + API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0)); /*! @function SecTrustGetCertificateCount diff --git a/trust/headers/SecTrustPriv.h b/trust/headers/SecTrustPriv.h index 5bf6e60b..f58f0c03 100644 --- a/trust/headers/SecTrustPriv.h +++ b/trust/headers/SecTrustPriv.h @@ -296,6 +296,14 @@ uint64_t SecTrustOTASecExperimentGetUpdatedAsset(CFErrorRef _Nullable * _Nullabl */ CFDictionaryRef SecTrustOTASecExperimentCopyAsset(CFErrorRef _Nullable * _Nullable CF_RETURNS_RETAINED error); +/* + @function SecTrustTriggerValidUpdate + @abstract Trigger trustd to fetch a valid update. + @param error A returned error if trustd failed to trigger the update. + @result True if the update was triggered, false if not. + */ +bool SecTrustTriggerValidUpdate(CFErrorRef _Nullable * _Nullable CF_RETURNS_RETAINED error); + /*! @function SecTrustFlushResponseCache @abstract Removes all OCSP responses from the per-user response cache. @@ -442,7 +450,7 @@ OSStatus SecTrustSetPinningException(SecTrustRef trust) @discussion Exceptions tagged with an older epoch are not trusted. */ uint64_t SecTrustGetExceptionResetCount(CFErrorRef *error) - API_UNAVAILABLE(macos, iosmac) API_AVAILABLE(ios(12.0), tvos(12.0), watchos(5.0)); + API_UNAVAILABLE(macos, macCatalyst) API_AVAILABLE(ios(12.0), tvos(12.0), watchos(5.0)); /*! @function SecTrustIncrementExceptionResetCount @@ -452,7 +460,7 @@ uint64_t SecTrustGetExceptionResetCount(CFErrorRef *error) @discussion By increasing the current epoch any existing exceptions, tagged with the old epoch, become distrusted. */ OSStatus SecTrustIncrementExceptionResetCount(CFErrorRef *error) - __API_UNAVAILABLE(macos, iosmac) __API_AVAILABLE(ios(12.0), tvos(12.0), watchos(5.0)); + __API_UNAVAILABLE(macos, macCatalyst) __API_AVAILABLE(ios(12.0), tvos(12.0), watchos(5.0)); #endif #ifdef __BLOCKS__ diff --git a/trust/headers/SecTrustSettingsPriv.h b/trust/headers/SecTrustSettingsPriv.h index 62b1c9b4..21046ff2 100644 --- a/trust/headers/SecTrustSettingsPriv.h +++ b/trust/headers/SecTrustSettingsPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -58,15 +58,15 @@ extern const CFStringRef kSecCTExceptionsSPKIHashKey; /* @function SecTrustStoreSetCTExceptions @abstract Set the certificate transparency enforcement exceptions - @param applicationIdentifier Identifier for the caller. If null, the application-identifier will be read from the callers entitlements. + @param applicationIdentifier Identifier for the caller. If null, the application-identifier will be read from the caller's entitlements. @param exceptions Dictionary of exceptions to set for this application. These exceptions replace existing exceptions for the keys in the dictionary. Exceptions for omitted keys are not affected. Null removes all exceptions for this application. See the discussion sections below for a complete overview of options. - @param error Upon failure describes cause of the failure. + @param error On failure, describes the cause of the failure; otherwise, null. @result boolean indicating success of the operation. If false, error will be filled in with a description of the error. @discussions An exceptions dictionary has two optional keys: kSecCTExceptionsDomainsKey takes an array of strings. These strings are the domains that are excluded from enforcing CT. A leading "." is supported to signify subdomains. Wildcard domains are not supported. kSecCTExceptionsCAsKey takes an array of dictionaries. Each dictionary has two required keys: - kSecCTExceptionsHashAlgorithmKey takes a string indicating the hash algorithm. Currenlty only "sha256" is supported. - kSecCTExceptionsSPKIHashKey takes a data containing hash of a certificates SubjectPublicKeyInfo. + kSecCTExceptionsHashAlgorithmKey takes a string indicating the hash algorithm. Currently only "sha256" is supported. + kSecCTExceptionsSPKIHashKey takes a data containing hash of a certificate's SubjectPublicKeyInfo. */ bool SecTrustStoreSetCTExceptions(CFStringRef applicationIdentifier, CFDictionaryRef exceptions, CFErrorRef *error); @@ -74,12 +74,41 @@ bool SecTrustStoreSetCTExceptions(CFStringRef applicationIdentifier, CFDictionar @function SecTrustStoreCopyCTExceptions @abstract Return the certificate transparency enforcement exceptions @param applicationIdentifier Identifier for the caller's exceptions to fetch. If null, all set exceptions will be returned (regardless of which caller set them). - @param error Upon failure describes cause of the failure. + @param error On failure, describes the cause of the failure; otherwise, null. @result The dictionary of currently set exceptions. Null if none exist or upon failure. @discussion The returned exceptions dictionary has the same options as input exceptions. See the discussion of SecTrustStoreSetCTExceptions. */ CF_RETURNS_RETAINED CFDictionaryRef SecTrustStoreCopyCTExceptions(CFStringRef applicationIdentifier, CFErrorRef *error); + +extern const CFStringRef kSecCARevocationAdditionsKey; +extern const CFStringRef kSecCARevocationHashAlgorithmKey; +extern const CFStringRef kSecCARevocationSPKIHashKey; + +/* + @function SecTrustStoreSetCARevocationAdditions + @abstract Set a list of certificate authorities (specified by subject public key info hash) for which revocation should be explicitly checked. + @param applicationIdentifier Identifier for the caller. If null, the application-identifier will be read from the caller's entitlements. + @param additions Dictionary of SPKI hashes for which revocation should be explicitly checked. Existing entries for the keys in the dictionary will be replaced. Null removes all CA revocation additions for this application. See the discussion sections below for a complete overview of options. + @param error On failure, describes the cause of the failure; otherwise, null. + @result boolean indicating success of the operation. If false, error will be filled in with a description of the error. + @discussions An additions dictionary currently has one defined key: + kSecCARevocationAdditionsKey takes an array of dictionaries. Each dictionary has two required keys: + kSecCARevocationHashAlgorithmKey takes a string indicating the hash algorithm. Currently only "sha256" is supported. + kSecCARevocationSPKIHashKey takes a data containing hash of a certificate's SubjectPublicKeyInfo. + */ +bool SecTrustStoreSetCARevocationAdditions(CFStringRef applicationIdentifier, CFDictionaryRef additions, CFErrorRef *error); + +/* + @function SecTrustStoreCopyCARevocationAdditions + @abstract Return the certificate authority SPKI hashes for which revocation should be explicitly checked. + @param applicationIdentifier Identifier for the caller's additions to fetch. If null, all set exceptions will be returned (regardless of which caller set them). + @param error On failure, describes cause of the failure; otherwise, null. + @result The dictionary of currently set CA revocation additions. Null if none exist or upon failure. + @discussion The returned additions dictionary has the same options as input additions. See the discussion of SecTrustStoreSetCARevocationAdditions. + */ +CF_RETURNS_RETAINED CFDictionaryRef SecTrustStoreCopyCARevocationAdditions(CFStringRef applicationIdentifier, CFErrorRef *error); + #if SEC_OS_OSX /* @@ -211,6 +240,19 @@ void SecTrustSettingsPurgeUserAdminCertsCache(void); */ OSStatus SecTrustSettingsCopyCertificatesForUserAdminDomains( CFArrayRef CF_RETURNS_RETAINED *certArray); + +/* Just like the API version (SecTrustSettingsCopyTrustSettings) but + * uses the cached version of trust settings to avoid disk reads. */ +OSStatus SecTrustSettingsCopyTrustSettings_Cached( + SecCertificateRef certRef, + SecTrustSettingsDomain domain, + CFArrayRef CF_RETURNS_RETAINED *trustSettings); + +/* Purge the trust settings cache (used by the above) */ +void SecTrustSettingsPurgeCache(void); + +/* Determines if the given cert has any trust settings in the admin or user domains */ +bool SecTrustSettingsUserAdminDomainsContain(SecCertificateRef certRef); #endif /* SEC_OS_OSX_INCLUDES */ __END_DECLS diff --git a/trust/headers/oids.h b/trust/headers/oids.h index 4a1d490d..d524d573 100644 --- a/trust/headers/oids.h +++ b/trust/headers/oids.h @@ -27,6 +27,14 @@ * */ +/* We need to guard against the other copy of libDER. + * This is outside this header's guards because DERItem.h currently guards + * the DERItem type against this header (legacy from when this header also + * defined the type). */ +#ifndef _LIB_DER_H_ +#include +#endif /* _LIB_DER_H_ */ + #ifndef _SECURITY_OIDS_H_ #define _SECURITY_OIDS_H_ @@ -35,24 +43,6 @@ __BEGIN_DECLS -/* This is a subset of libDER's oids.h. If the types header has - * already been included, we should skip these typedef declarations. */ -#ifndef _LIB_DER_H_ -/* - * Basic data types - */ -typedef uint8_t DERByte; -typedef size_t DERSize; - -/* - * Primary representation of a block of memory. - */ -typedef struct { - DERByte *data; - DERSize length; -} DERItem; -#endif /* _LIB_DER_H_ */ - /* Algorithm oids. */ extern const DERItem oidRsa, /* PKCS1 RSA encryption, used to identify RSA keys */ diff --git a/trust/trustd/OTATrustUtilities.m b/trust/trustd/OTATrustUtilities.m index f3e59709..4ac7be77 100644 --- a/trust/trustd/OTATrustUtilities.m +++ b/trust/trustd/OTATrustUtilities.m @@ -272,9 +272,9 @@ static void LogRemotelyWithAttributes(OTATrustLogLevel level, NSError **error, N #if ENABLE_TRUSTD_ANALYTICS /* only report errors and notices */ if (error && level == OTATrustLogLevelError) { - [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:YES result:*error withAttributes:attributes]; + [[TrustAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:YES result:*error withAttributes:attributes]; } else if (error && level == OTATrustLogLevelNotice) { - [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:NO result:*error withAttributes:attributes]; + [[TrustAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventOTAPKIEvent hardFailure:NO result:*error withAttributes:attributes]; } #endif // ENABLE_TRUSTD_ANALYTICS } @@ -536,7 +536,7 @@ static NSNumber *PKIUpdateAndPurgeAsset(MAAsset *asset, NSNumber *asset_version, UpdateFromAsset([asset getLocalFileUrl], asset_version, error)) { secnotice("OTATrust", "finished update to version %@ from installed asset. purging asset.", asset_version); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logSuccessForEventNamed:TrustdHealthAnalyticsEventOTAPKIEvent]; + [[TrustAnalytics logger] logSuccessForEventNamed:TrustdHealthAnalyticsEventOTAPKIEvent]; #endif // ENABLE_TRUSTD_ANALYTICS [asset purge:^(MAPurgeResult purge_result) { if (purge_result != MAPurgeSucceeded) { diff --git a/trust/trustd/SecCertificateServer.c b/trust/trustd/SecCertificateServer.c index ebd9350f..71233beb 100644 --- a/trust/trustd/SecCertificateServer.c +++ b/trust/trustd/SecCertificateServer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2017-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,7 @@ #include "trust/trustd/SecPolicyServer.h" #include "trust/trustd/SecCertificateServer.h" #include "trust/trustd/SecRevocationServer.h" +#include "trust/trustd/SecTrustStoreServer.h" // MARK: - // MARK: SecCertificateVC @@ -254,6 +256,11 @@ struct SecCertificatePathVC { bool is_allowlisted; bool hasStrongHashes; + /* revocationCAIndex contains the index of the last CA with a SPKI-based + * revocation match, or -1 (kCFNotFound) if no CA match was found. + * A value of 0 means the path has not yet been checked for a match. */ + CFIndex revocationCAIndex; + void * rvcs; CFIndex rvcCount; @@ -757,7 +764,7 @@ bool SecCertificatePathVCHasWeakKeySize(SecCertificatePathVCRef certificatePath) *stop = true; } }); - + errOut: CFReleaseSafe(keySizes); CFReleaseSafe(rsaSize); @@ -768,19 +775,19 @@ errOut: /* Return a score for this certificate chain. */ CFIndex SecCertificatePathVCScore(SecCertificatePathVCRef certificatePath, CFAbsoluteTime verifyTime) { CFIndex score = 0; - + /* Paths that don't verify score terribly.c */ if (certificatePath->lastVerifiedSigner != certificatePath->count - 1) { secdebug("trust", "lvs: %" PRIdCFIndex " count: %" PRIdCFIndex, certificatePath->lastVerifiedSigner, certificatePath->count); score -= 100000; } - + if (certificatePath->isAnchored) { /* Anchored paths for the win! */ score += 10000; } - + if (certificatePath->isSelfSigned && (certificatePath->selfIssued == certificatePath->count - 1)) { /* Chains that terminate in a self-signed certificate are preferred, even if they don't end in an anchor. */ @@ -791,19 +798,19 @@ CFIndex SecCertificatePathVCScore(SecCertificatePathVCRef certificatePath, CFAbs /* Longer chains are preferred when the chain doesn't end in a self-signed cert. */ score += 1 * certificatePath->count; } - + if (SecCertificatePathVCIsValid(certificatePath, verifyTime)) { score += 100; } - + if (!SecCertificatePathVCHasWeakHash(certificatePath)) { score += 10; } - + if (!SecCertificatePathVCHasWeakKeySize(certificatePath)) { score += 10; } - + return score; } @@ -1001,6 +1008,63 @@ void SecCertificatePathVCSetRequiresCT(SecCertificatePathVCRef certificatePath, certificatePath->requiresCT = requiresCT; } +static bool has_ca_additions_key(SecCertificatePathVCRef path, CFDictionaryRef ca_entry) { + bool result = false; + CFDataRef hash = CFDictionaryGetValue(ca_entry, kSecCARevocationSPKIHashKey); + if (!hash) { + return false; + } + /* only check issuing CAs and not the leaf */ + for (CFIndex certIX = 1; certIX < SecCertificatePathVCGetCount(path); certIX++) { + SecCertificateRef ca = SecCertificatePathVCGetCertificateAtIndex(path, certIX); + CFDataRef spkiHash = SecCertificateCopySubjectPublicKeyInfoSHA256Digest(ca); + bool matched = CFEqualSafe(hash, spkiHash); + CFReleaseNull(spkiHash); + if (!matched) { + continue; + } + /* this SPKI is a match; remember highest index */ + if (certIX > path->revocationCAIndex) { + path->revocationCAIndex = certIX; + } + result = true; + } + return result; +} + +static void SecCertificatePathVCCheckCARevocationAdditions(SecCertificatePathVCRef path) { + CFDictionaryRef additions = _SecTrustStoreCopyCARevocationAdditions(NULL, NULL); + path->revocationCAIndex = kCFNotFound; + if (!additions) { + return; + } + + __block bool result = false; + CFArrayRef ca_list = CFDictionaryGetValue(additions, kSecCARevocationAdditionsKey); + if (ca_list) { + CFArrayForEach(ca_list, ^(const void *value) { + result = result || has_ca_additions_key(path, value); + }); + } + + if (result) { + secinfo("ocsp", "key-based CA revocation applies at index %lld", + (long long)path->revocationCAIndex); + } + + CFReleaseNull(additions); + return; +} + +CFIndex SecCertificatePathVCIndexOfCAWithRevocationAdditions(SecCertificatePathVCRef certificatePath) { + if (!certificatePath) { return kCFNotFound; } + if (0 == certificatePath->revocationCAIndex) { + /* we haven't checked this path yet, do it now */ + SecCertificatePathVCCheckCARevocationAdditions(certificatePath); + } + return certificatePath->revocationCAIndex; +} + CFAbsoluteTime SecCertificatePathVCIssuanceTime(SecCertificatePathVCRef certificatePath) { if (!certificatePath) { return 0; } return certificatePath->issuanceTime; diff --git a/trust/trustd/SecCertificateServer.h b/trust/trustd/SecCertificateServer.h index 8a144340..e3b69495 100644 --- a/trust/trustd/SecCertificateServer.h +++ b/trust/trustd/SecCertificateServer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * Copyright (c) 2017-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -166,6 +166,12 @@ void SecCertificatePathVCSetRequiresCT(SecCertificatePathVCRef certificatePath, CFAbsoluteTime SecCertificatePathVCIssuanceTime(SecCertificatePathVCRef certificatePath); void SecCertificatePathVCSetIssuanceTime(SecCertificatePathVCRef certificatePath, CFAbsoluteTime issuanceTime); +/* CA Revocation Additions */ +/* Returns the index of the highest issuing CA which has matching key-based + * revocation additions in the given path, or kCFNotFound if none is found. + */ +CFIndex SecCertificatePathVCIndexOfCAWithRevocationAdditions(SecCertificatePathVCRef certificatePath); + /* Allowlist */ bool SecCertificatePathVCIsAllowlisted(SecCertificatePathVCRef certificatePath); void SecCertificatePathVCSetIsAllowlisted(SecCertificatePathVCRef certificatePath, bool isAllowlisted); diff --git a/trust/trustd/SecCertificateSource.c b/trust/trustd/SecCertificateSource.c index 1c7932e7..63924442 100644 --- a/trust/trustd/SecCertificateSource.c +++ b/trust/trustd/SecCertificateSource.c @@ -416,8 +416,6 @@ struct SecCertificateSource _kSecSystemAnchorSource = { const SecCertificateSourceRef kSecSystemAnchorSource = &_kSecSystemAnchorSource; - -#if TARGET_OS_IPHONE // MARK: - // MARK: SecUserAnchorSource /******************************************************** @@ -461,7 +459,6 @@ struct SecCertificateSource _kSecUserAnchorSource = { }; const SecCertificateSourceRef kSecUserAnchorSource = &_kSecUserAnchorSource; -#endif // MARK: - // MARK: SecMemoryCertificateSource @@ -629,30 +626,33 @@ const SecCertificateSourceRef kSecLegacyCertificateSource = &_kSecLegacyCertific static bool SecLegacyAnchorSourceCopyParents(SecCertificateSourceRef source, SecCertificateRef certificate, void *context, SecCertificateSourceParents callback) { CFMutableArrayRef anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFArrayRef parents = SecItemCopyParentCertificates_osx(certificate, NULL); CFArrayRef trusted = NULL; - if (parents == NULL) { + CFDataRef normalizedIssuer = SecCertificateCopyNormalizedIssuerSequence(certificate); + if (!normalizedIssuer) { goto finish; } + /* Get the custom anchors which have been trusted in the user and admin domains. * We don't need system domain roots here, since SecSystemAnchorSource provides those. */ OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted); if (status == errSecSuccess && trusted) { - CFIndex index, count = CFArrayGetCount(parents); + CFIndex index, count = CFArrayGetCount(trusted); for (index = 0; index < count; index++) { - SecCertificateRef parent = (SecCertificateRef)CFArrayGetValueAtIndex(parents, index); - if (parent && CFArrayContainsValue(trusted, CFRangeMake(0, CFArrayGetCount(trusted)), parent)) { - CFArrayAppendValue(anchors, parent); + SecCertificateRef potentialParent = (SecCertificateRef)CFArrayGetValueAtIndex(trusted, index); + CFDataRef normalizedSubject = SecCertificateCopyNormalizedSubjectSequence(potentialParent); + if (CFEqualSafe(normalizedIssuer, normalizedSubject)) { + CFArrayAppendValue(anchors, potentialParent); } + CFReleaseSafe(normalizedSubject); } } finish: callback(context, anchors); CFReleaseSafe(anchors); - CFReleaseSafe(parents); CFReleaseSafe(trusted); + CFReleaseSafe(normalizedIssuer); return true; } @@ -661,19 +661,19 @@ static CFArrayRef SecLegacyAnchorSourceCopyUsageConstraints(SecCertificateSource CFArrayRef result = NULL; CFArrayRef userTrustSettings = NULL, adminTrustSettings = NULL; - OSStatus status = SecTrustSettingsCopyTrustSettings(certificate, - kSecTrustSettingsDomainUser, - &userTrustSettings); - if ((status == errSecSuccess) && (userTrustSettings != NULL)) { - result = CFRetain(userTrustSettings); + OSStatus status = SecTrustSettingsCopyTrustSettings_Cached(certificate, + kSecTrustSettingsDomainAdmin, + &adminTrustSettings); + if ((status == errSecSuccess) && (adminTrustSettings != NULL)) { + /* admin trust settings overrule user trust settings (rdar://37052515) */ + return adminTrustSettings; } - status = SecTrustSettingsCopyTrustSettings(certificate, - kSecTrustSettingsDomainAdmin, - &adminTrustSettings); - /* user trust settings overrule admin trust settings */ - if ((status == errSecSuccess) && (adminTrustSettings != NULL) && (result == NULL)) { - result = CFRetain(adminTrustSettings); + status = SecTrustSettingsCopyTrustSettings_Cached(certificate, + kSecTrustSettingsDomainUser, + &userTrustSettings); + if (status == errSecSuccess) { + result = CFRetainSafe(userTrustSettings); } CFReleaseNull(userTrustSettings); @@ -686,31 +686,39 @@ static bool SecLegacyAnchorSourceContains(SecCertificateSourceRef source, if (certificate == NULL) { return false; } - CFArrayRef trusted = NULL; - bool result = false; - OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted); - if ((status == errSecSuccess) && (trusted != NULL)) { - CFIndex index, count = CFArrayGetCount(trusted); - for (index = 0; index < count; index++) { - SecCertificateRef anchor = (SecCertificateRef)CFRetainSafe(CFArrayGetValueAtIndex(trusted, index)); - if (anchor && (CFGetTypeID(anchor) != CFGetTypeID(certificate))) { - /* This should only happen if trustd and the Security framework are using different SecCertificate TypeIDs. + + if (SecTrustSettingsUserAdminDomainsContain(certificate)) { + return true; + } else { + CFArrayRef trusted = NULL; + bool result = false; + OSStatus status = SecTrustSettingsCopyCertificatesForUserAdminDomains(&trusted); + if ((status == errSecSuccess) && (trusted != NULL)) { + if ((CFArrayGetCount(trusted) > 0) && CFGetTypeID(CFArrayGetValueAtIndex(trusted, 0)) != CFGetTypeID(certificate)) { + /* This fallback should only happen if trustd and the Security framework are using different SecCertificate TypeIDs. * This occurs in TrustTests where we rebuild SecCertificate.c for code coverage purposes, so we end up with * two registered SecCertificate types. So we'll make a SecCertificate of our type. */ - SecCertificateRef temp = SecCertificateCreateWithBytes(NULL, SecCertificateGetBytePtr(anchor), SecCertificateGetLength(anchor)); - CFAssignRetained(anchor, temp); - } - if (anchor && CFEqual(anchor, certificate)) { - result = true; - } - CFReleaseNull(anchor); - if (result) { - break; + CFIndex index, count = CFArrayGetCount(trusted); + for (index = 0; index < count; index++) { + SecCertificateRef anchor = (SecCertificateRef)CFRetainSafe(CFArrayGetValueAtIndex(trusted, index)); + if (anchor && (CFGetTypeID(anchor) != CFGetTypeID(certificate))) { + SecCertificateRef temp = SecCertificateCreateWithBytes(NULL, SecCertificateGetBytePtr(anchor), SecCertificateGetLength(anchor)); + CFAssignRetained(anchor, temp); + } + if (anchor && CFEqual(anchor, certificate)) { + result = true; + } + CFReleaseNull(anchor); + if (result) { + break; + } + } } + CFReleaseSafe(trusted); + return result; } } - CFReleaseSafe(trusted); - return result; + return false; } struct SecCertificateSource _kSecLegacyAnchorSource = { diff --git a/trust/trustd/SecCertificateSource.h b/trust/trustd/SecCertificateSource.h index c2c99907..b99b822a 100644 --- a/trust/trustd/SecCertificateSource.h +++ b/trust/trustd/SecCertificateSource.h @@ -78,10 +78,8 @@ void SecMemoryCertificateSourceDestroy(SecCertificateSourceRef source); /* SecSystemAnchorSource */ extern const SecCertificateSourceRef kSecSystemAnchorSource; -#if TARGET_OS_IPHONE /* SecUserAnchorSource */ extern const SecCertificateSourceRef kSecUserAnchorSource; -#endif /* SecCAIssuerCertificateSource */ extern const SecCertificateSourceRef kSecCAIssuerSource; diff --git a/trust/trustd/SecOCSPResponse.c b/trust/trustd/SecOCSPResponse.c index 0d1995a6..2b422449 100644 --- a/trust/trustd/SecOCSPResponse.c +++ b/trust/trustd/SecOCSPResponse.c @@ -692,3 +692,20 @@ SecCertificateRef SecOCSPResponseCopySigner(SecOCSPResponseRef this, SecCertific /* We couldn't find who signed this ocspResponse, give up. */ return NULL; } + +bool SecOCSPResponseIsWeakHash(SecOCSPResponseRef response) { + SecAsn1AlgId algId = response->basicResponse.algId; + const DERItem algOid = { + .data = algId.algorithm.Data, + .length = algId.algorithm.Length, + }; + SecSignatureHashAlgorithm algorithm = SecSignatureHashAlgorithmForAlgorithmOid(&algOid); + if (algorithm == kSecSignatureHashAlgorithmUnknown || + algorithm == kSecSignatureHashAlgorithmMD2 || + algorithm == kSecSignatureHashAlgorithmMD4 || + algorithm == kSecSignatureHashAlgorithmMD5 || + algorithm == kSecSignatureHashAlgorithmSHA1) { + return true; + } + return false; +} diff --git a/trust/trustd/SecOCSPResponse.h b/trust/trustd/SecOCSPResponse.h index 91eec797..2bbaf3fc 100644 --- a/trust/trustd/SecOCSPResponse.h +++ b/trust/trustd/SecOCSPResponse.h @@ -160,6 +160,8 @@ void SecOCSPSingleResponseDestroy(SecOCSPSingleResponseRef this); SecCertificateRef SecOCSPResponseCopySigner(SecOCSPResponseRef this, SecCertificateRef issuerPath); +bool SecOCSPResponseIsWeakHash(SecOCSPResponseRef response); + __END_DECLS #endif /* !_SECURITY_SECOCSPRESPONSE_H_ */ diff --git a/trust/trustd/SecPinningDb.m b/trust/trustd/SecPinningDb.m index a62b9256..55fc3193 100644 --- a/trust/trustd/SecPinningDb.m +++ b/trust/trustd/SecPinningDb.m @@ -341,7 +341,7 @@ static inline bool isNSDictionary(id nsType) { if (!ok || error) { secerror("SecPinningDb: error installing updated pinning list version %@: %@", [pinningList objectAtIndex:0], error); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logHardError:(__bridge NSError *)error + [[TrustAnalytics logger] logHardError:(__bridge NSError *)error withEventName:TrustdHealthAnalyticsEventDatabaseEvent withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : @(TAOperationWrite) }]; @@ -471,7 +471,7 @@ static inline bool isNSDictionary(id nsType) { if (!ok) { secerror("SecPinningDb: %s failed: %@", didCreate ? "Create" : "Open", error ? *error : NULL); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logHardError:(error ? (__bridge NSError *)*error : nil) + [[TrustAnalytics logger] logHardError:(error ? (__bridge NSError *)*error : nil) withEventName:TrustdHealthAnalyticsEventDatabaseEvent withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : didCreate ? @(TAOperationCreate) : @(TAOperationOpen)}]; @@ -699,7 +699,7 @@ static void verify_create_path(const char *path) if (!ok || error) { secerror("SecPinningDb: error querying DB for hostname: %@", error); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logHardError:(__bridge NSError *)error + [[TrustAnalytics logger] logHardError:(__bridge NSError *)error withEventName:TrustdHealthAnalyticsEventDatabaseEvent withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : @(TAOperationRead)}]; @@ -774,7 +774,7 @@ static void verify_create_path(const char *path) if (!ok || error) { secerror("SecPinningDb: error querying DB for policyName: %@", error); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logHardError:(__bridge NSError *)error + [[TrustAnalytics logger] logHardError:(__bridge NSError *)error withEventName:TrustdHealthAnalyticsEventDatabaseEvent withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : @(TAOperationRead)}]; @@ -809,7 +809,7 @@ void SecPinningDbInitialize(void) { if (!ok || error) { secerror("SecPinningDb: unable to initialize db: %@", error); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logHardError:(__bridge NSError *)error + [[TrustAnalytics logger] logHardError:(__bridge NSError *)error withEventName:TrustdHealthAnalyticsEventDatabaseEvent withAttributes:@{TrustdHealthAnalyticsAttributeAffectedDatabase : @(TAPinningDb), TrustdHealthAnalyticsAttributeDatabaseOperation : @(TAOperationRead)}]; @@ -823,15 +823,18 @@ void SecPinningDbInitialize(void) { CFDictionaryRef _Nullable SecPinningDbCopyMatching(CFDictionaryRef query) { @autoreleasepool { SecPinningDbInitialize(); - NSDictionary *nsQuery = (__bridge NSDictionary*)query; - NSString *hostname = [nsQuery objectForKey:(__bridge NSString*)kSecPinningDbKeyHostname]; - NSDictionary *results = [pinningDb queryForDomain:hostname]; - if (results) { return CFBridgingRetain(results); } + /* prefer rules queried by policy name */ NSString *policyName = [nsQuery objectForKey:(__bridge NSString*)kSecPinningDbKeyPolicyName]; - results = [pinningDb queryForPolicyName:policyName]; - if (!results) { return nil; } + NSDictionary *results = [pinningDb queryForPolicyName:policyName]; + if (results) { + return CFBridgingRetain(results); + } + + /* then rules queried by hostname */ + NSString *hostname = [nsQuery objectForKey:(__bridge NSString*)kSecPinningDbKeyHostname]; + results = [pinningDb queryForDomain:hostname]; return CFBridgingRetain(results); } } diff --git a/trust/trustd/SecPolicyServer.c b/trust/trustd/SecPolicyServer.c index e826197b..e0abcb94 100644 --- a/trust/trustd/SecPolicyServer.c +++ b/trust/trustd/SecPolicyServer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -308,9 +308,26 @@ static void SecPolicyCheckExtendedKeyUsage(SecPVCRef pvc, CFStringRef key) { SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0); SecPolicyRef policy = SecPVCGetPolicy(pvc); CFTypeRef xeku = CFDictionaryGetValue(policy->_options, key); + /* leaf check enforced */ if (!SecPolicyCheckCertExtendedKeyUsage(leaf, xeku)){ SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); } + + /* subCA check produces metrics */ + TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(pvc->builder); + CFIndex ix, count = SecPVCGetCertificateCount(pvc); + if (count > 2 && analytics) { + for (ix = 1; ix < count - 1 ; ++ix) { + SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix); + CFArrayRef ekus = SecCertificateCopyExtendedKeyUsage(cert); + if (ekus && CFArrayGetCount(ekus) && // subCA has ekus + !SecPolicyCheckCertExtendedKeyUsage(cert, CFSTR("2.5.29.37.0")) && // but not the anyEKU + !SecPolicyCheckCertExtendedKeyUsage(cert, xeku)) { // and not the EKUs specified by the policy + analytics->ca_fail_eku_check = true; + } + CFReleaseNull(ekus); + } + } } static void SecPolicyCheckBasicConstraints(SecPVCRef pvc, @@ -557,26 +574,8 @@ static void SecPolicyCheckAnchorSHA256(SecPVCRef pvc, CFStringRef key) { return; } - -/* AUDIT[securityd](done): - policy->_options is a caller provided dictionary, only its cf type has - been checked. - */ -static void SecPolicyCheckAnchorSHA1(SecPVCRef pvc, - CFStringRef key) { - CFIndex count = SecPVCGetCertificateCount(pvc); - SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, count - 1); - CFDataRef anchorSHA1 = SecCertificateGetSHA1Digest(cert); - - if (!isDigestInPolicy(pvc, key, anchorSHA1)) - if (!SecPVCSetResult(pvc, kSecPolicyCheckAnchorSHA1, count-1, kCFBooleanFalse)) - return; - - return; -} - /* - Check the SHA256 of SPKI of the first intermediate CA certificate in the path + Check the SHA256 of SPKI of the first intermediate CA certificate in the path. policy->_options is a caller provided dictionary, only its cf type has been checked. */ @@ -599,6 +598,73 @@ static void SecPolicyCheckIntermediateSPKISHA256(SecPVCRef pvc, CFReleaseNull(digest); } +/* + Check the SPKI SHA256 of CA certificates in the path + policy->_options is a caller provided dictionary, only its cf type has + been checked. + */ +static void SecPolicyCheckCAspkiSHA256(SecPVCRef pvc, + CFStringRef key) { + SecCertificateRef cert = NULL; + CFDataRef digest = NULL; + + if (SecPVCGetCertificateCount(pvc) < 2) { + SecPVCSetResult(pvc, kSecPolicyCheckCAspkiSHA256, 0, kCFBooleanFalse); + return; + } + + bool spkiSHA256match = false; + CFIndex count = SecPVCGetCertificateCount(pvc); + for (CFIndex i = 1; i < count && spkiSHA256match == false; i++) { + cert = SecPVCGetCertificateAtIndex(pvc, i); + digest = SecCertificateCopySubjectPublicKeyInfoSHA256Digest(cert); + + if (isDigestInPolicy(pvc, key, digest)) { + spkiSHA256match = true; + } + + CFReleaseNull(digest); + } + + if (spkiSHA256match == true) { + return; + } + + for (CFIndex i = 1; i < count; i++) { + SecPVCSetResult(pvc, kSecPolicyCheckCAspkiSHA256, i, kCFBooleanFalse); + } +} + +/* + Check the SPKI SHA256 of the leaf certificate. + policy->_options is a caller provided dictionary, only its cf type has + been checked. +*/ +static void SecPolicyCheckLeafSPKISHA256(SecPVCRef pvc, + CFStringRef key) { + SecPolicyRef policy = SecPVCGetPolicy(pvc); + + CFArrayRef leafSPKISHA256 = CFDictionaryGetValue(policy->_options, key); + if (isArray(leafSPKISHA256) == false) { + /* @@@ We can't return an error here and making the evaluation fail + won't help much either. */ + return; + } + + SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0); + CFDataRef digest = SecCertificateCopySubjectPublicKeyInfoSHA256Digest(leaf); + if (!digest) { + SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); + return; + } + + if (!CFArrayContainsValue(leafSPKISHA256, CFRangeMake(0, CFArrayGetCount(leafSPKISHA256)), digest)) { + SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); + } + + CFReleaseNull(digest); +} + /* policy->_options is a caller provided dictionary, only its cf type has been checked. @@ -1984,14 +2050,14 @@ static void SecPolicyCheckKeySize(SecPVCRef pvc, CFStringRef key) { SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0); /* Don't check key size for user-anchored leafs */ -#if TARGET_OS_IPHONE - SecCertificateSourceRef userSource = kSecUserAnchorSource; -#else - SecCertificateSourceRef userSource = kSecLegacyAnchorSource; -#endif - if (SecPVCIsAnchorPerConstraints(pvc, userSource, leaf)) { + if (SecPVCIsAnchorPerConstraints(pvc, kSecUserAnchorSource, leaf)) { + return; + } +#if TARGET_OS_OSX + if (SecPVCIsAnchorPerConstraints(pvc, kSecLegacyAnchorSource, leaf)) { return; } +#endif for (ix = 0; ix < count; ++ix) { SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix); @@ -2020,10 +2086,10 @@ static void SecPolicyCheckSignatureHashAlgorithms(SecPVCRef pvc, CFIndex ix = 0, count = SecPVCGetCertificateCount(pvc); /* Ignore (a non-self-signed) anchor if it's trusted by the user */ -#if TARGET_OS_IPHONE bool userAnchored = SecPVCIsAnchorPerConstraints(pvc, kSecUserAnchorSource, SecPVCGetCertificateAtIndex(pvc, count - 1)); -#else - bool userAnchored = SecPVCIsAnchorPerConstraints(pvc, kSecLegacyAnchorSource, SecPVCGetCertificateAtIndex(pvc, count - 1)); +#if TARGET_OS_OSX + userAnchored = userAnchored || SecPVCIsAnchorPerConstraints(pvc, kSecLegacyAnchorSource, + SecPVCGetCertificateAtIndex(pvc, count - 1)); #endif if (SecPathBuilderIsAnchored(pvc->builder) && userAnchored) { count--; @@ -2178,7 +2244,7 @@ static bool is_configured_test_system_root(SecCertificateRef root, CFStringRef p CFDataRef rootHash = SecCertificateCopySHA256Digest(root); CFTypeRef value = CFPreferencesCopyAppValue(preference, CFSTR("com.apple.security")); require_quiet(isData(value), out); - require_quiet(kCFCompareEqualTo == CFDataCompare(rootHash, value), out); + require_quiet(CFEqual(rootHash, value), out); result = true; out: @@ -2408,6 +2474,7 @@ out: static bool SecPolicyCheckSystemTrustValidityPeriodMaximums(CFAbsoluteTime notBefore, CFAbsoluteTime notAfter) { CFAbsoluteTime jul2016 = 489024000.0; // 1 July 2016 00:00:00 UTC CFAbsoluteTime mar2018 = 541555200.0; // 1 March 2018 00:00:00 UTC + CFAbsoluteTime sep2020 = 620611200.0; // 1 September 2020 00:00:00 UTC if (notBefore < jul2016) { /* Validity Period no greater than 60 months. 60 months is no more than 5 years and 2 leap days (and 1 hour slip). */ @@ -2425,13 +2492,20 @@ static bool SecPolicyCheckSystemTrustValidityPeriodMaximums(CFAbsoluteTime notBe secnotice("policy", "System-trusted leaf validity period longer than 39 months and issued after 30 June 2016"); return false; } - } else { + } else if (notBefore < sep2020) { /* Validity Period no greater than 825 days (and 1 hour slip). */ CFAbsoluteTime maxPeriod = 60*60*24*825 + 3600; if (notAfter - notBefore > maxPeriod) { secnotice("policy", "System-trusted leaf validity period longer than 825 days and issued on or after 1 March 2018"); return false; } + } else { + /* Validity Period no greater than 398 days (and no slip). HT211025 */ + CFAbsoluteTime maxPeriod = 60*60*24*398; + if (notAfter - notBefore > maxPeriod) { + secnotice("policy", "System-trusted leaf validity period longer than 398 days and issued on or after 1 September 2020"); + return false; + } } return true; } @@ -2471,14 +2545,14 @@ static void SecPolicyCheckValidityPeriodMaximums(SecPVCRef pvc, CFStringRef key) } /* Don't check validity periods against maximums for user-anchored leafs */ -#if TARGET_OS_IPHONE - SecCertificateSourceRef userSource = kSecUserAnchorSource; -#else - SecCertificateSourceRef userSource = kSecLegacyAnchorSource; -#endif - if (SecPVCIsAnchorPerConstraints(pvc, userSource, leaf)) { + if (SecPVCIsAnchorPerConstraints(pvc, kSecUserAnchorSource, leaf)) { return; } +#if TARGET_OS_OSX + if (SecPVCIsAnchorPerConstraints(pvc, kSecLegacyAnchorSource, leaf)) { + return; + } +#endif /* all other trust */ if (!SecPolicyCheckOtherTrustValidityPeriodMaximums(notBefore, notAfter)) { @@ -2498,18 +2572,33 @@ static void SecPolicyCheckServerAuthEKU(SecPVCRef pvc, CFStringRef key) { if (!SecPolicyCheckCertExtendedKeyUsage(leaf, CFSTR("1.3.6.1.5.5.7.3.1"))) { // server auth EKU SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); } + /* if any subCA cert has an EKU, it must have the server auth EKU */ + if (count > 2) { // chain has subCAs + for (int ix = 1; ix < count - 1; ix++) { // iterate through subCAs + SecCertificateRef subCA = SecPVCGetCertificateAtIndex(pvc, ix); + CFArrayRef eku = NULL; + if ((eku = SecCertificateCopyExtendedKeyUsage(subCA)) && CFArrayGetCount(eku)) { // subCA has EKU set + if (!SecPolicyCheckCertExtendedKeyUsage(subCA, CFSTR("1.3.6.1.5.5.7.3.1")) && // check server auth EKU + !SecPolicyCheckCertExtendedKeyUsage(subCA, CFSTR("2.5.29.37.0"))) { // check anyEKU + SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); + } + } + CFReleaseNull(eku); + } + } return; } /* skip user/admin-anchored chains */ -#if TARGET_OS_IPHONE - SecCertificateSourceRef userSource = kSecUserAnchorSource; -#else - SecCertificateSourceRef userSource = kSecLegacyAnchorSource; -#endif - if (SecPVCIsAnchorPerConstraints(pvc, userSource, root)) { + if (SecPVCIsAnchorPerConstraints(pvc, kSecUserAnchorSource, root)) { return; } +#if TARGET_OS_OSX + if (SecPVCIsAnchorPerConstraints(pvc, kSecLegacyAnchorSource, root)) { + return; + } +#endif + /* All other anchor types must be compliant if issued on or after 1 July 2019 */ CFAbsoluteTime notBefore = SecCertificateNotValidBefore(leaf); @@ -2521,6 +2610,18 @@ static void SecPolicyCheckServerAuthEKU(SecPVCRef pvc, CFStringRef key) { } } +static void SecPolicyCheckCTRequired(SecPVCRef pvc, CFStringRef key) { + SecCertificatePathVCRef path = SecPathBuilderGetPath(pvc->builder); + SecCertificatePathVCSetRequiresCT(path, kSecPathCTRequiredOverridable); +} + +static void SecPolicyCheckNotCA(SecPVCRef pvc, CFStringRef key) { + SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0); + if (SecCertificateIsCA(leaf)) { + SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); + } +} + void SecPolicyServerInitialize(void) { gSecPolicyLeafCallbacks = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); @@ -2635,6 +2736,9 @@ static bool SecPVCIsExceptedError(SecPVCRef pvc, CFIndex ix, CFStringRef key, CF */ #if TARGET_OS_OSX CFDictionaryRef options = CFArrayGetValueAtIndex(exceptions, 0); + if (!isDictionary(options)) { + return false; + } /* Type 2 */ if (exceptionsCount == 1 && (ix > 0 || !CFDictionaryContainsKey(options, kSecCertificateDetailSHA1Digest))) { /* SHA1Digest not allowed */ @@ -2665,6 +2769,9 @@ static bool SecPVCIsExceptedError(SecPVCRef pvc, CFIndex ix, CFStringRef key, CF /* Type 1 */ if (ix >= exceptionsCount) { return false; } CFDictionaryRef exception = CFArrayGetValueAtIndex(exceptions, ix); + if (!isDictionary(exception)) { + return false; + } /* Compare the cert hash */ if (!CFDictionaryContainsKey(exception, kSecCertificateDetailSHA1Digest)) { return false; } @@ -3296,7 +3403,7 @@ static bool SecPVCCallerIsApplication(CFDataRef clientAuditToken, CFTypeRef appR SecRequirementRef requirement = NULL; CFStringRef stringRequirement = NULL; - require(appRef && clientAuditToken, out); + require_quiet(appRef && clientAuditToken, out); require(CFGetTypeID(appRef) == SecTrustedApplicationGetTypeID(), out); require_noerr(SecTrustedApplicationCopyRequirement((SecTrustedApplicationRef)appRef, &requirement), out); require(requirement, out); @@ -3484,16 +3591,16 @@ static void SecPVCCheckUsageConstraints(SecPVCRef pvc) { /* If we already think the PVC is ok and this cert is from one of the user/ * admin anchor sources, trustRoot, trustAsRoot, and Invalid (no constraints), * all mean we should use the special "Proceed" trust result. */ -#if TARGET_OS_IPHONE if (SecPathBuilderIsAnchorSource(pvc->builder, kSecUserAnchorSource) && - SecCertificateSourceContains(kSecUserAnchorSource, cert)) -#else + SecCertificateSourceContains(kSecUserAnchorSource, cert)) { + pvc->result = kSecTrustResultProceed; + } +#if TARGET_OS_OSX if (SecPathBuilderIsAnchorSource(pvc->builder, kSecLegacyAnchorSource) && - SecCertificateSourceContains(kSecLegacyAnchorSource, cert)) -#endif - { + SecCertificateSourceContains(kSecLegacyAnchorSource, cert)) { pvc->result = kSecTrustResultProceed; } +#endif } } } @@ -3574,7 +3681,10 @@ static void SecPVCCheckIssuerDateConstraints(SecPVCRef pvc) { } } -static bool SecPVCIsSSLServerAuthenticationPolicy(SecPVCRef pvc) { +static bool SecPVCPolicyPermitsCTRequired(SecPVCRef pvc) { +#if TARGET_OS_BRIDGE + return false; +#else // !TARGET_OS_BRIDGE if (!pvc || !pvc->policies) { return false; } @@ -3582,15 +3692,22 @@ static bool SecPVCIsSSLServerAuthenticationPolicy(SecPVCRef pvc) { if (!policy) { return false; } + // SSL policy CFStringRef policyName = SecPolicyGetName(policy); if (CFEqualSafe(policyName, kSecPolicyNameSSLServer)) { return true; } + // SSL policy by another name CFDictionaryRef options = policy->_options; if (options && CFDictionaryGetValue(options, kSecPolicyCheckSSLHostname)) { return true; } + // Policy explicitly requires CT + if (options && CFDictionaryGetValue(options, kSecPolicyCheckCTRequired)) { + return true; + } return false; +#endif // !TARGET_OS_BRIDGE } /* ASSUMPTIONS: @@ -3609,7 +3726,7 @@ static void SecPVCCheckRequireCTConstraints(SecPVCRef pvc) { Note that CT will already be required if there is a not-after date constraint present (set in SecRVCProcessValidDateConstraints). */ - if (SecPVCIsSSLServerAuthenticationPolicy(pvc)) { + if (SecPVCPolicyPermitsCTRequired(pvc)) { CFIndex ix, certCount = SecCertificatePathVCGetCount(path); SecCertificateRef certificate = SecPathBuilderGetCertificateAtIndex(pvc->builder, 0); CFAbsoluteTime earliestNotAfter = 31556908800.0; /* default: 3001-01-01 00:00:00-0000 */ @@ -3644,15 +3761,16 @@ static void SecPVCCheckRequireCTConstraints(SecPVCRef pvc) { /* Path is not CT validated, so check if CT was required. */ SecPathCTPolicy ctp = SecCertificatePathVCRequiresCT(path); - if (ctp <= kSecPathCTNotRequired || !SecPVCIsSSLServerAuthenticationPolicy(pvc)) { + if (ctp <= kSecPathCTNotRequired || !SecPVCPolicyPermitsCTRequired(pvc)) { return; } /* We need to have a recent log list or the CT check may have failed due to the list being out of date. * Also, honor the CT kill switch. */ SecOTAPKIRef otaref = SecOTAPKICopyCurrentOTAPKIRef(); + CFDictionaryRef trustedLogs = SecPathBuilderCopyTrustedLogs(pvc->builder); if (!SecOTAPKIKillSwitchEnabled(otaref, kOTAPKIKillSwitchCT) && - SecOTAPKIAssetStalenessLessThanSeconds(otaref, kSecOTAPKIAssetStalenessDisable)) { + (SecOTAPKIAssetStalenessLessThanSeconds(otaref, kSecOTAPKIAssetStalenessDisable) || trustedLogs)) { /* CT was required. Error is always set on leaf certificate. */ if (ctp != kSecPathCTRequiredOverridable) { /* Normally kSecPolicyCheckCTRequired is recoverable */ @@ -3663,6 +3781,7 @@ static void SecPVCCheckRequireCTConstraints(SecPVCRef pvc) { } } CFReleaseNull(otaref); + CFReleaseNull(trustedLogs); } /* "Deep" copy the details array */ diff --git a/trust/trustd/SecRevocationDb.c b/trust/trustd/SecRevocationDb.c index 5672e48f..4fdb34b9 100644 --- a/trust/trustd/SecRevocationDb.c +++ b/trust/trustd/SecRevocationDb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 Apple Inc. All Rights Reserved. + * Copyright (c) 2016-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -203,6 +203,14 @@ static double htond(double h) { return n; } +/* Obtain swapped value of the 32-bit integer referenced by the given pointer. + Since a generic void or char pointer may not be aligned on a 4-byte boundary, + the UB sanitizer does not let us directly dereference it as *(uint32_t*). +*/ +static uint32_t SecSwapInt32Ptr(const void* P) { + uint32_t _i=0; memcpy(&_i,P,sizeof(_i)); return OSSwapInt32(_i); +} + // MARK: - // MARK: Valid definitions @@ -250,7 +258,7 @@ typedef CF_OPTIONS(CFOptionFlags, SecValidInfoFlags) { /* maximum allowed interval */ #define kSecMaxUpdateInterval (60.0 * 60 * 24 * 7) -#define kSecRevocationBasePath "/Library/Keychains/crls" +/* filenames we use, relative to revocation info directory */ #define kSecRevocationCurUpdateFile "update-current" #define kSecRevocationDbFileName "valid.sqlite3" #define kSecRevocationDbReplaceFile ".valid_replace" @@ -319,7 +327,7 @@ bool SecRevocationDbUpdateSchema(SecRevocationDbRef rdb); CFIndex SecRevocationDbGetUpdateFormat(void); bool _SecRevocationDbSetUpdateSource(SecRevocationDbConnectionRef dbc, CFStringRef source, CFErrorRef *error); bool SecRevocationDbSetUpdateSource(SecRevocationDbRef rdb, CFStringRef source); -CFStringRef SecRevocationDbCopyUpdateSource(void); +CF_RETURNS_RETAINED CFStringRef SecRevocationDbCopyUpdateSource(void); bool SecRevocationDbSetNextUpdateTime(CFAbsoluteTime nextUpdate, CFErrorRef *error); CFAbsoluteTime SecRevocationDbGetNextUpdateTime(void); dispatch_queue_t SecRevocationDbGetUpdateQueue(void); @@ -623,8 +631,7 @@ static bool SecValidUpdateProcessData(SecRevocationDbConnectionRef dbc, CFIndex SecError(errSecParam, error, CFSTR("SecValidUpdateProcessData: data length is too short")); return result; } - /* get length of signed data */ - uint32_t dataLength = OSSwapInt32(*((uint32_t *)p)); + uint32_t dataLength = SecSwapInt32Ptr(p); bytesRemaining -= sizeof(uint32_t); p += sizeof(uint32_t); @@ -632,7 +639,7 @@ static bool SecValidUpdateProcessData(SecRevocationDbConnectionRef dbc, CFIndex uint32_t plistCount = 1; uint32_t plistTotal = 1; if (format > kSecValidUpdateFormatG2) { - plistCount = OSSwapInt32(*((uint32_t *)p)); + plistCount = SecSwapInt32Ptr(p); plistTotal = plistCount; bytesRemaining -= sizeof(uint32_t); p += sizeof(uint32_t); @@ -652,7 +659,7 @@ static bool SecValidUpdateProcessData(SecRevocationDbConnectionRef dbc, CFIndex CFPropertyListRef propertyList = NULL; uint32_t plistLength = dataLength; if (format > kSecValidUpdateFormatG2) { - plistLength = OSSwapInt32(*((uint32_t *)p)); + plistLength = SecSwapInt32Ptr(p); bytesRemaining -= sizeof(uint32_t); p += sizeof(uint32_t); } @@ -942,9 +949,15 @@ static CF_RETURNS_RETAINED CFStringRef SecRevocationDbCopyServer(void) { /* Prefer a in-process setting for the update server, as used in testing */ CFTypeRef value = CFPreferencesCopyAppValue(kUpdateServerKey, kSecPrefsDomain); if (!value) { - value = (CFStringRef)CFPreferencesCopyValue(kUpdateServerKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + value = CFPreferencesCopyValue(kUpdateServerKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + } + CFStringRef server = NULL; + if (isString(value)) { + server = (CFStringRef)value; + } else { + CFReleaseNull(value); + server = CFRetainSafe(SecRevocationDbGetDefaultServer()); } - CFStringRef server = (isString(value)) ? (CFStringRef)value : CFRetainSafe(SecRevocationDbGetDefaultServer()); return server; } @@ -1125,6 +1138,56 @@ static CFStringRef SecValidInfoCopyFormatDescription(CFTypeRef cf, CFDictionaryR ============================================================================== */ +static CFIndex _SecRevocationDbGetUpdateVersion(CFStringRef server) { + // determine version of our current database + CFIndex version = SecRevocationDbGetVersion(); + secdebug("validupdate", "got version %ld from db", (long)version); + if (version <= 0) { + if (gLastVersion > 0) { + secdebug("validupdate", "error getting version; using last good version: %ld", (long)gLastVersion); + } + version = gLastVersion; + } + + // determine source of our current database + // (if this ever changes, we will need to reload the db) + CFStringRef db_source = SecRevocationDbCopyUpdateSource(); + if (!db_source) { + db_source = (CFStringRef) CFRetain(kValidUpdateProdServer); + } + + // determine whether we need to recreate the database + CFIndex db_version = SecRevocationDbGetSchemaVersion(); + CFIndex db_format = SecRevocationDbGetUpdateFormat(); + if (db_version < kSecRevocationDbSchemaVersion || + db_format < kSecRevocationDbUpdateFormat || + kCFCompareEqualTo != CFStringCompare(server, db_source, kCFCompareCaseInsensitive)) { + // we need to fully rebuild the db contents, so we set our version to 0. + version = gLastVersion = 0; + } + CFReleaseNull(db_source); + return version; +} + +static bool _SecRevocationDbIsUpdateEnabled(void) { + CFTypeRef value = NULL; + // determine whether update fetching is enabled +#if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE + // Valid update fetching was initially enabled on macOS 10.13 and iOS 11.0. + // This conditional has been changed to include every platform and version + // except for those where the db should not be updated over the air. + bool updateEnabled = true; +#else + bool updateEnabled = false; +#endif + value = (CFBooleanRef)CFPreferencesCopyValue(kUpdateEnabledKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + if (isBoolean(value)) { + updateEnabled = CFBooleanGetValue((CFBooleanRef)value); + } + CFReleaseNull(value); + return updateEnabled; +} + /* SecRevocationDbCheckNextUpdate returns true if we dispatched an update request, otherwise false. */ @@ -1183,52 +1246,15 @@ static bool _SecRevocationDbCheckNextUpdate(void) { // determine which server to query CFStringRef server = SecRevocationDbCopyServer(); - // determine version of our current database - CFIndex version = SecRevocationDbGetVersion(); - secdebug("validupdate", "got version %ld from db", (long)version); - if (version <= 0) { - if (gLastVersion > 0) { - secdebug("validupdate", "error getting version; using last good version: %ld", (long)gLastVersion); - } - version = gLastVersion; - } + // determine version to update from + CFIndex version = _SecRevocationDbGetUpdateVersion(server); - // determine source of our current database - // (if this ever changes, we will need to reload the db) - CFStringRef db_source = SecRevocationDbCopyUpdateSource(); - if (!db_source) { - db_source = (CFStringRef) CFRetain(kValidUpdateProdServer); - } - - // determine whether we need to recreate the database - CFIndex db_version = SecRevocationDbGetSchemaVersion(); - CFIndex db_format = SecRevocationDbGetUpdateFormat(); - if (db_version < kSecRevocationDbSchemaVersion || - db_format < kSecRevocationDbUpdateFormat || - kCFCompareEqualTo != CFStringCompare(server, db_source, kCFCompareCaseInsensitive)) { - // we need to fully rebuild the db contents, so we set our version to 0. - version = gLastVersion = 0; - } - - // determine whether update fetching is enabled -#if !TARGET_OS_WATCH && !TARGET_OS_BRIDGE - // Valid update fetching was initially enabled on macOS 10.13 and iOS 11.0. - // This conditional has been changed to include every platform and version - // except for those where the db should not be updated over the air. - bool updateEnabled = true; -#else - bool updateEnabled = false; -#endif - value = (CFBooleanRef)CFPreferencesCopyValue(kUpdateEnabledKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - if (isBoolean(value)) { - updateEnabled = CFBooleanGetValue((CFBooleanRef)value); - } - CFReleaseNull(value); + // determine if update is enabled for this device + bool updateEnabled = _SecRevocationDbIsUpdateEnabled(); // Schedule maintenance work bool result = SecValidUpdateSchedule(updateEnabled, server, version); CFReleaseNull(server); - CFReleaseNull(db_source); return result; } @@ -1248,6 +1274,26 @@ void SecRevocationDbCheckNextUpdate(void) { sec_action_perform(action); } +bool SecRevocationDbUpdate(CFErrorRef *error) +{ + // are we the db owner instance? + if (!isDbOwner()) { + return SecError(errSecWrPerm, error, CFSTR("Unable to update Valid DB from user agent")); + } + + if (!_SecRevocationDbIsUpdateEnabled()) { + return SecError(errSecWrPerm, error, CFSTR("Valid updates not enabled on this device")); + } + + CFStringRef server = SecRevocationDbCopyServer(); + CFIndex version = _SecRevocationDbGetUpdateVersion(server); + + secdebug("validupdate", "will fetch v%lu from \"%@\" now", (unsigned long)version, server); + bool result = SecValidUpdateUpdateNow(SecRevocationDbGetUpdateQueue(), server, version); + CFReleaseNull(server); + return result; +} + /* This function verifies an update, in this format: 1) unsigned 32-bit network-byte-order length of binary plist 2) binary plist data @@ -1260,7 +1306,7 @@ bool SecRevocationDbVerifyUpdate(void *update, CFIndex length) { if (!update || length <= (CFIndex)sizeof(uint32_t)) { return false; } - uint32_t plistLength = OSSwapInt32(*((uint32_t *)update)); + uint32_t plistLength = SecSwapInt32Ptr(update); if ((plistLength + (CFIndex)(sizeof(uint32_t)*2)) > (uint64_t) length) { secdebug("validupdate", "ERROR: reported plist length (%lu)+%lu exceeds total length (%lu)\n", (unsigned long)plistLength, (unsigned long)sizeof(uint32_t)*2, (unsigned long)length); @@ -1268,7 +1314,7 @@ bool SecRevocationDbVerifyUpdate(void *update, CFIndex length) { } uint8_t *plistData = (uint8_t *)update + sizeof(uint32_t); uint8_t *sigData = (uint8_t *)plistData + plistLength; - uint32_t sigLength = OSSwapInt32(*((uint32_t *)sigData)); + uint32_t sigLength = SecSwapInt32Ptr(sigData); sigData += sizeof(uint32_t); if ((plistLength + sigLength + (CFIndex)(sizeof(uint32_t) * 2)) != (uint64_t) length) { secdebug("validupdate", "ERROR: reported lengths do not add up to total length\n"); @@ -2389,10 +2435,10 @@ static bool _SecRevocationDbUpdateIssuers(SecRevocationDbConnectionRef dbc, int6 } static SecValidInfoFormat _SecRevocationDbGetGroupFormatForData(SecRevocationDbConnectionRef dbc, int64_t groupId, CFDataRef data) { - /* determine existing format if groupId is supplied and this is a partial update, + /* determine existing format if groupId is supplied, otherwise return the expected format for the given data. */ SecValidInfoFormat format = kSecValidInfoFormatUnknown; - if (groupId >= 0 && !dbc->fullUpdate) { + if (groupId >= 0) { format = _SecRevocationDbGetGroupFormat(dbc, groupId, NULL, NULL, NULL, NULL); } if (format == kSecValidInfoFormatUnknown && data != NULL) { @@ -2587,7 +2633,7 @@ static bool _SecRevocationDbUpdateDateConstraints(SecRevocationDbConnectionRef d return ok; /* no dates supplied, so we have nothing to update for this issuer */ } - if (!(notBeforeDate && notAfterDate) && !dbc->fullUpdate) { + if (!(notBeforeDate && notAfterDate)) { /* only one date was supplied, so check for existing date constraints */ CFDateRef curNotBeforeDate = NULL; CFDateRef curNotAfterDate = NULL; @@ -3170,8 +3216,8 @@ static bool _SecRevocationDbApplyGroupUpdate(SecRevocationDbConnectionRef dbc, C __block CFErrorRef localError = NULL; CFArrayRef issuers = (dict) ? (CFArrayRef)CFDictionaryGetValue(dict, CFSTR("issuer-hash")) : NULL; - /* if this is not a full update, then look for existing group id */ - if (ok && isArray(issuers) && !dbc->fullUpdate) { + /* look for existing group id */ + if (ok && isArray(issuers)) { CFIndex issuerIX, issuerCount = CFArrayGetCount(issuers); /* while we have issuers and haven't found a matching group id */ for (issuerIX=0; issuerIX #include #include +#include #include #include @@ -105,6 +106,12 @@ void SecValidInfoSetAnchor(SecValidInfoRef validInfo, SecCertificateRef anchor); */ void SecRevocationDbCheckNextUpdate(void); +/*! + @function SecRevocationDbUpdate + @abstract Trigger update now. For use in testing and tools. + */ +bool SecRevocationDbUpdate(CFErrorRef *error); + /*! @function SecRevocationDbCopyMatching @abstract Returns a SecValidInfo reference if matching revocation (or allow list) info was found. @@ -177,7 +184,7 @@ extern const CFStringRef kValidUpdateCarryServer; @abstract Returns the server source for updates of the revocation database. @result The base string of the server URI. */ -CFStringRef SecRevocationDbCopyUpdateSource(void); +CF_RETURNS_RETAINED CFStringRef SecRevocationDbCopyUpdateSource(void); __END_DECLS diff --git a/trust/trustd/SecRevocationNetworking.h b/trust/trustd/SecRevocationNetworking.h index e642f193..e87f9eb9 100644 --- a/trust/trustd/SecRevocationNetworking.h +++ b/trust/trustd/SecRevocationNetworking.h @@ -29,6 +29,7 @@ #import "trust/trustd/SecRevocationServer.h" bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex version); +bool SecValidUpdateUpdateNow(dispatch_queue_t queue, CFStringRef server, CFIndex version); bool SecORVCBeginFetches(SecORVCRef orvc, SecCertificateRef cert); #endif /* _SECURITY_SECREVOCATIONNETWORKING_H_ */ diff --git a/trust/trustd/SecRevocationNetworking.m b/trust/trustd/SecRevocationNetworking.m index c1852066..acbcd118 100644 --- a/trust/trustd/SecRevocationNetworking.m +++ b/trust/trustd/SecRevocationNetworking.m @@ -197,9 +197,8 @@ didReceiveResponse:(NSURLResponse *)response (void)remove(updateFilePath); int fd; - off_t off; fd = open(updateFilePath, O_RDWR | O_CREAT | O_TRUNC, 0644); - if (fd < 0 || (off = lseek(fd, 0, SEEK_SET)) < 0) { + if (fd < 0) { secnotice("validupdate","unable to open %@ (errno %d)", self->_currentUpdateFileURL, errno); } if (fd >= 0) { @@ -218,7 +217,7 @@ didReceiveResponse:(NSURLResponse *)response if (!self->_currentUpdateFile) { secnotice("validupdate", "failed to open %@: %@. canceling task %@", self->_currentUpdateFileURL, error, dataTask); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventValidUpdate hardFailure:NO result:error]; + [[TrustAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventValidUpdate hardFailure:NO result:error]; #endif // ENABLE_TRUSTD_ANALYTICS completionHandler(NSURLSessionResponseCancel); [self reschedule]; @@ -259,7 +258,7 @@ didCompleteWithError:(NSError *)error { if (error) { secnotice("validupdate", "Session %@ task %@ failed with error %@", session, task, error); #if ENABLE_TRUSTD_ANALYTICS - [[TrustdHealthAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventValidUpdate hardFailure:NO result:error]; + [[TrustAnalytics logger] logResultForEvent:TrustdHealthAnalyticsEventValidUpdate hardFailure:NO result:error]; #endif // ENABLE_TRUSTD_ANALYTICS [self reschedule]; /* close file before we leave */ @@ -288,30 +287,25 @@ didCompleteWithError:(NSError *)error { @interface ValidUpdateRequest : NSObject @property NSTimeInterval updateScheduled; @property NSURLSession *backgroundSession; +@property NSURLSession *ephemeralSession; @end static ValidUpdateRequest *request = nil; @implementation ValidUpdateRequest -- (NSURLSessionConfiguration *)validUpdateConfiguration { - /* preferences to override defaults */ - CFTypeRef value = NULL; - bool updateOnWiFiOnly = true; - value = CFPreferencesCopyValue(kUpdateWiFiOnlyKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - if (isBoolean(value)) { - updateOnWiFiOnly = CFBooleanGetValue((CFBooleanRef)value); - } - CFReleaseNull(value); - bool updateInBackground = true; - value = CFPreferencesCopyValue(kUpdateBackgroundKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - if (isBoolean(value)) { - updateInBackground = CFBooleanGetValue((CFBooleanRef)value); - } - CFReleaseNull(value); - +- (NSURLSessionConfiguration *)validUpdateConfiguration:(BOOL)background { NSURLSessionConfiguration *config = nil; - if (updateInBackground) { + if (background) { + /* preferences to override defaults */ + CFTypeRef value = NULL; + bool updateOnWiFiOnly = true; + value = CFPreferencesCopyValue(kUpdateWiFiOnlyKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + if (isBoolean(value)) { + updateOnWiFiOnly = CFBooleanGetValue((CFBooleanRef)value); + } + CFReleaseNull(value); + config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier: @"com.apple.trustd.networking.background"]; config.networkServiceType = NSURLNetworkServiceTypeBackground; config.discretionary = YES; @@ -332,8 +326,9 @@ static ValidUpdateRequest *request = nil; return config; } -- (void) createSession:(dispatch_queue_t)updateQueue forServer:(NSString *)updateServer { - NSURLSessionConfiguration *config = [self validUpdateConfiguration]; +- (NSURLSession *)createSession:(BOOL)background queue:(dispatch_queue_t)updateQueue forServer:(NSString *)updateServer +{ + NSURLSessionConfiguration *config = [self validUpdateConfiguration:background]; ValidDelegate *delegate = [[ValidDelegate alloc] init]; delegate.handler = ^(void) { request.updateScheduled = 0.0; @@ -348,7 +343,23 @@ static ValidUpdateRequest *request = nil; We'll then dispatch the work on updateQueue and return from the callback. */ NSOperationQueue *queue = [[NSOperationQueue alloc] init]; queue.maxConcurrentOperationCount = 1; - _backgroundSession = [NSURLSession sessionWithConfiguration:config delegate:delegate delegateQueue:queue]; + return [NSURLSession sessionWithConfiguration:config delegate:delegate delegateQueue:queue]; +} + +- (void) createSessions:(dispatch_queue_t)updateQueue forServer:(NSString *)updateServer { + self.ephemeralSession = [self createSession:NO queue:updateQueue forServer:updateServer]; + + bool updateInBackground = true; + CFTypeRef value = CFPreferencesCopyValue(kUpdateBackgroundKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + if (isBoolean(value)) { + updateInBackground = CFBooleanGetValue((CFBooleanRef)value); + } + CFReleaseNull(value); + if (updateInBackground) { + self.backgroundSession = [self createSession:YES queue:updateQueue forServer:updateServer]; + } else { + self.backgroundSession = self.ephemeralSession; + } } - (BOOL) scheduleUpdateFromServer:(NSString *)server forVersion:(NSUInteger)version withQueue:(dispatch_queue_t)updateQueue { @@ -399,7 +410,7 @@ static ValidUpdateRequest *request = nil; }); if (!self.backgroundSession) { - [self createSession:updateQueue forServer:server]; + [self createSessions:updateQueue forServer:server]; } else { ValidDelegate *delegate = (ValidDelegate *)[self.backgroundSession delegate]; delegate.currentUpdateServer = [server copy]; @@ -424,20 +435,68 @@ static ValidUpdateRequest *request = nil; return YES; } + +- (BOOL)updateNowFromServer:(NSString *)server version:(NSUInteger)version queue:(dispatch_queue_t)updateQueue +{ + if (!server) { + secnotice("validupdate", "invalid update request"); + return NO; + } + + if (!updateQueue) { + secnotice("validupdate", "missing update queue, skipping update"); + return NO; + } + + if (!self.ephemeralSession) { + [self createSessions:updateQueue forServer:server]; + } else { + ValidDelegate *delegate = (ValidDelegate *)[self.ephemeralSession delegate]; + delegate.currentUpdateServer = [server copy]; + } + + /* POWER LOG EVENT: scheduling our background download session now */ + SecPLLogRegisteredEvent(@"ValidUpdateEvent", @{ + @"timestamp" : @([[NSDate date] timeIntervalSince1970]), + @"event" : @"downloadScheduled", + @"version" : @(version) + }); + + NSURL *validUrl = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@/g3/v%ld", + server, (unsigned long)version]]; + NSURLSessionDataTask *dataTask = [self.ephemeralSession dataTaskWithURL:validUrl]; + dataTask.taskDescription = [NSString stringWithFormat:@"%lu",(unsigned long)version]; + [dataTask resume]; + secnotice("validupdate", "running foreground data task %@ at %f", dataTask, CFAbsoluteTimeGetCurrent()); + return YES; +} + @end +static void SecValidUpdateCreateValidUpdateRequest() +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + @autoreleasepool { + request = [[ValidUpdateRequest alloc] init]; + } + }); +} + bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex version) { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - @autoreleasepool { - request = [[ValidUpdateRequest alloc] init]; - } - }); + SecValidUpdateCreateValidUpdateRequest(); @autoreleasepool { return [request scheduleUpdateFromServer:(__bridge NSString*)server forVersion:version withQueue:queue]; } } +bool SecValidUpdateUpdateNow(dispatch_queue_t queue, CFStringRef server, CFIndex version) { + SecValidUpdateCreateValidUpdateRequest(); + @autoreleasepool { + return [request updateNowFromServer:(__bridge NSString*)server version:version queue:queue]; + } +} + /* MARK: - */ /* MARK: OCSP Fetch Networking */ #define OCSP_REQUEST_THRESHOLD 10 @@ -490,7 +549,7 @@ bool SecValidUpdateRequest(dispatch_queue_t queue, CFStringRef server, CFIndex v SecORVCConsumeOCSPResponse(orvc, ocspResponse, self.expiration, true, false); if (analytics && !orvc->done) { /* We got an OCSP response that didn't pass validation */ - analytics-> ocsp_validation_failed = true; + analytics->ocsp_validation_failed = true; } } else if (analytics) { /* We got something that wasn't an OCSP response (e.g. captive portal) -- diff --git a/trust/trustd/SecRevocationServer.c b/trust/trustd/SecRevocationServer.c index b0b5ac86..abf32ece 100644 --- a/trust/trustd/SecRevocationServer.c +++ b/trust/trustd/SecRevocationServer.c @@ -285,6 +285,11 @@ void SecORVCConsumeOCSPResponse(SecORVCRef rvc, SecOCSPResponseRef ocspResponse sr->certStatus == CS_Revoked ? SecOCSPResponseProducedAt(ocspResponse) : verifyTime), errOut); #endif + TrustAnalyticsBuilder *analytics = SecPathBuilderGetAnalyticsData(rvc->builder); + if (analytics && SecOCSPResponseIsWeakHash(ocspResponse)) { + analytics->ocsp_weak_hash = true; + } + // If we get here, we have a properly signed ocsp response // but we haven't checked dates yet. @@ -1017,12 +1022,16 @@ bool SecPathBuilderCheckRevocation(SecPathBuilderRef builder) { * This check resolves unrevocation events after the nextUpdate time. */ bool old_cached_response = (!rvc->done && rvc->orvc->ocspResponse); + /* Check whether CA revocation additions match an issuer above us in this path. + * If so, we will attempt revocation checking below. */ + bool has_ca_revocation = (certIX < SecCertificatePathVCIndexOfCAWithRevocationAdditions(path)); + /* If the cert is EV or if revocation checking was explicitly enabled, attempt to fire off an async http request for this cert's revocation status, unless we already successfully checked the revocation status of this cert based on the cache or stapled responses. */ bool allow_fetch = SecRevocationCanAccessNetwork(builder, first_check_done) && (SecCertificatePathVCIsEV(path) || SecCertificatePathVCIsOptionallyEV(path) || - SecPathBuilderGetRevocationMethod(builder) || old_cached_response); + SecPathBuilderGetRevocationMethod(builder) || old_cached_response || has_ca_revocation); if (rvc->done || !allow_fetch) { /* We got a cache hit or we aren't allowed to access the network */ SecRVCUpdatePVC(rvc); diff --git a/trust/trustd/SecTrustExceptionResetCount.m b/trust/trustd/SecTrustExceptionResetCount.m index 4552f3ce..401c22b8 100644 --- a/trust/trustd/SecTrustExceptionResetCount.m +++ b/trust/trustd/SecTrustExceptionResetCount.m @@ -119,6 +119,8 @@ static bool SecWritePlistToFileInKeychainDirectory(uint64_t exceptionResetCount, if (localError) { if (error) { *error = localError; + } else { + CFReleaseNull(localError); } secerror("Permanent storage for the exceptions epoch is unavailable."); return status; @@ -164,11 +166,14 @@ uint64_t SecTrustServerGetExceptionResetCount(CFErrorRef *error) { * That's expected when epoch is still 0 and there is nothing to store in permanent storage. (and later read) */ if (localError && CFEqualSafe(CFErrorGetDomain(localError), kCFErrorDomainPOSIX) && CFErrorGetCode(localError) == ENXIO) { - CFRelease(localError); - localError = NULL; + CFReleaseNull(localError); } - if (error && localError) { - *error = localError; + if (localError) { + if (error) { + *error = localError; + } else { + CFReleaseNull(localError); + } } secinfo("trust", "exceptionResetCount: %llu (%s)", exceptionResetCount, error ? (*error ? "Error" : "OK") : "N/A"); return exceptionResetCount; diff --git a/trust/trustd/SecTrustServer.c b/trust/trustd/SecTrustServer.c index 8e1eeee0..42d1a4d0 100644 --- a/trust/trustd/SecTrustServer.c +++ b/trust/trustd/SecTrustServer.c @@ -242,9 +242,7 @@ static void SecPathBuilderInit(SecPathBuilderRef builder, dispatch_queue_t build if we don't explicitly trust them. */ CFArrayAppendValue(builder->parentSources, builder->appleAnchorSource); CFArrayAppendValue(builder->parentSources, kSecSystemAnchorSource); - #if TARGET_OS_IPHONE CFArrayAppendValue(builder->parentSources, kSecUserAnchorSource); - #endif } if (keychainsAllowed && builder->canAccessNetwork) { CFArrayAppendValue(builder->parentSources, kSecCAIssuerSource); @@ -273,13 +271,12 @@ static void SecPathBuilderInit(SecPathBuilderRef builder, dispatch_queue_t build anchorSources if we are supposed to trust them. */ CFArrayAppendValue(builder->anchorSources, builder->appleAnchorSource); if (keychainsAllowed) { -#if TARGET_OS_IPHONE - CFArrayAppendValue(builder->anchorSources, kSecUserAnchorSource); -#else /* TARGET_OS_OSX */ +#if TARGET_OS_OSX if (kSecLegacyAnchorSource->contains && kSecLegacyAnchorSource->copyParents) { CFArrayAppendValue(builder->anchorSources, kSecLegacyAnchorSource); } #endif + CFArrayAppendValue(builder->anchorSources, kSecUserAnchorSource); } CFArrayAppendValue(builder->anchorSources, kSecSystemAnchorSource); } @@ -466,6 +463,9 @@ CFSetRef SecPathBuilderGetAllPaths(SecPathBuilderRef builder) TrustAnalyticsBuilder *SecPathBuilderGetAnalyticsData(SecPathBuilderRef builder) { + if (!builder) { + return NULL; + } return builder->analyticsData; } @@ -1364,6 +1364,20 @@ SecTrustServerEvaluateBlock(dispatch_queue_t builderQueue, CFDataRef clientAudit SecPathBuilderStep(builder); } +static CFDataRef SecTrustServerCopySelfAuditToken(void) +{ + audit_token_t token; + kern_return_t kr; + mach_msg_type_number_t token_size = TASK_AUDIT_TOKEN_COUNT; + kr = task_info(mach_task_self(), TASK_AUDIT_TOKEN, (task_info_t)&token, &token_size); + if (kr != KERN_SUCCESS) { + secwarning("failed to get audit token for ourselves"); + return NULL; + } + + return CFDataCreate(NULL, (uint8_t *)&token, sizeof(token)); +} + // NO_SERVER Shim code only, xpc interface should call SecTrustServerEvaluateBlock() directly SecTrustResultType SecTrustServerEvaluate(CFArrayRef certificates, CFArrayRef anchors, bool anchorsOnly, bool keychainsAllowed, CFArrayRef policies, CFArrayRef responses, CFArrayRef SCTs, CFArrayRef trustedLogs, CFAbsoluteTime verifyTime, __unused CFArrayRef accessGroups, CFArrayRef exceptions, CFArrayRef *pdetails, CFDictionaryRef *pinfo, CFArrayRef *pchain, CFErrorRef *perror) { @@ -1371,13 +1385,16 @@ SecTrustResultType SecTrustServerEvaluate(CFArrayRef certificates, CFArrayRef an __block SecTrustResultType result = kSecTrustResultInvalid; __block dispatch_queue_t queue = dispatch_queue_create("com.apple.trustd.evaluation.recursive", DISPATCH_QUEUE_SERIAL); + /* make an audit token for ourselves */ + CFDataRef audit_token = SecTrustServerCopySelfAuditToken(); + /* We need to use the async call with the semaphore here instead of a synchronous call because we may return from * SecPathBuilderStep while waiting for an asynchronous network call in order to complete the evaluation. That return * is necessary in the XPC interface in order to free up the workloop for other trust evaluations while we wait for * the networking to complete, but here, we need to make sure we wait for the network call (which will async back * onto our queue) to complete and signal us before we return to the "inline" caller. */ dispatch_async(queue, ^{ - SecTrustServerEvaluateBlock(queue, NULL, certificates, anchors, anchorsOnly, keychainsAllowed, policies, responses, SCTs, trustedLogs, verifyTime, accessGroups, exceptions, ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, CFArrayRef chain, CFErrorRef error) { + SecTrustServerEvaluateBlock(queue, audit_token, certificates, anchors, anchorsOnly, keychainsAllowed, policies, responses, SCTs, trustedLogs, verifyTime, accessGroups, exceptions, ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, CFArrayRef chain, CFErrorRef error) { result = tr; if (tr == kSecTrustResultInvalid) { if (perror) { @@ -1404,6 +1421,7 @@ SecTrustResultType SecTrustServerEvaluate(CFArrayRef certificates, CFArrayRef an dispatch_semaphore_wait(done, DISPATCH_TIME_FOREVER); dispatch_release(done); dispatch_release_null(queue); + CFReleaseNull(audit_token); return result; } diff --git a/trust/trustd/SecTrustServer.h b/trust/trustd/SecTrustServer.h index 898e71f3..50233ad5 100644 --- a/trust/trustd/SecTrustServer.h +++ b/trust/trustd/SecTrustServer.h @@ -180,6 +180,7 @@ typedef CF_OPTIONS(uint8_t, TAValidStatus) { typedef struct { uint64_t start_time; bool suspected_mitm; + bool ca_fail_eku_check; // Certificate Transparency TA_SCTSource sct_sources; uint32_t number_scts; @@ -202,6 +203,7 @@ typedef struct { uint64_t ocsp_fetch_time; uint32_t ocsp_fetch_failed; bool ocsp_validation_failed; + bool ocsp_weak_hash; // Valid TAValidStatus valid_status; bool valid_trigger_ocsp; diff --git a/trust/trustd/SecTrustStoreServer.c b/trust/trustd/SecTrustStoreServer.c index 88de9d23..04bc212c 100644 --- a/trust/trustd/SecTrustStoreServer.c +++ b/trust/trustd/SecTrustStoreServer.c @@ -64,6 +64,7 @@ static dispatch_once_t kSecTrustStoreUserOnce; static SecTrustStoreRef kSecTrustStoreUser = NULL; +#if TARGET_OS_IPHONE static const char copyParentsSQL[] = "SELECT data FROM tsettings WHERE subj=?"; static const char containsSQL[] = "SELECT tset FROM tsettings WHERE sha1=?"; static const char insertSQL[] = "INSERT OR REPLACE INTO tsettings(sha1,subj,tset,data)VALUES(?,?,?,?)"; @@ -71,6 +72,7 @@ static const char deleteSQL[] = "DELETE FROM tsettings WHERE sha1=?"; static const char deleteAllSQL[] = "BEGIN EXCLUSIVE TRANSACTION; DELETE from tsettings; COMMIT TRANSACTION; VACUUM;"; static const char copyAllSQL[] = "SELECT data,tset FROM tsettings ORDER BY sha1"; static const char countAllSQL[] = "SELECT COUNT(*) FROM tsettings"; +#endif #define kSecTrustStoreName CFSTR("TrustStore") #define kSecTrustStoreDbExtension CFSTR("sqlite3") @@ -92,7 +94,7 @@ struct __SecTrustStore { // MARK: - // MARK: Trust store functions - +#if TARGET_OS_IPHONE static int sec_create_path(const char *path) { char pathbuf[PATH_MAX]; @@ -594,3 +596,62 @@ bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, errOutNotLocked: return ok; } + +#else // !TARGET_OS_IPHONE +/* On macOS the trust store has nothing in it by default */ +static void SecTrustStoreInitUser(void) { + SecTrustStoreRef ts = (SecTrustStoreRef)malloc(sizeof(struct __SecTrustStore)); + memset(ts, 0, sizeof(struct __SecTrustStore)); + ts->readOnly = true; + kSecTrustStoreUser = ts; +} + +SecTrustStoreRef SecTrustStoreForDomainName(CFStringRef domainName, CFErrorRef *error) { + if (CFEqual(CFSTR("user"), domainName)) { + dispatch_once(&kSecTrustStoreUserOnce, ^{ SecTrustStoreInitUser(); }); + return kSecTrustStoreUser; + } else { + SecError(errSecParam, error, CFSTR("unknown domain: %@"), domainName); + return NULL; + } +} + +bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts, + SecCertificateRef certificate, + CFTypeRef trustSettingsDictOrArray, CFErrorRef *error) { + return SecError(errSecUnimplemented, error, CFSTR("trust store is not modifiable on this platform")); +} + +bool SecTrustStoreRemoveCertificateWithDigest(SecTrustStoreRef ts, CFDataRef digest, CFErrorRef *error) { + return SecError(errSecUnimplemented, error, CFSTR("trust store is not modifiable on this platform")); +} + +bool _SecTrustStoreRemoveAll(SecTrustStoreRef ts, CFErrorRef *error) { + return SecError(errSecUnimplemented, error, CFSTR("trust store is not modifiable on this platform")); +} + +CFArrayRef SecTrustStoreCopyParents(SecTrustStoreRef ts, + SecCertificateRef certificate, CFErrorRef *error) { + CFArrayRef parents = NULL; + return parents; +} + +bool SecTrustStoreContainsCertificateWithDigest(SecTrustStoreRef ts, CFDataRef digest, bool *contains, CFErrorRef *error) { + if (contains) { + *contains = false; + } + return true; +} + +bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, CFDataRef digest, CFArrayRef *usageConstraints, CFErrorRef *error) { + return true; +} + +bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, CFErrorRef *error) { + CFMutableArrayRef CertsAndSettings = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + if (CertsAndSettings) { + *trustStoreContents = CertsAndSettings; + } + return true; +} +#endif diff --git a/trust/trustd/SecTrustStoreServer.h b/trust/trustd/SecTrustStoreServer.h index 41444de1..64e0baf4 100644 --- a/trust/trustd/SecTrustStoreServer.h +++ b/trust/trustd/SecTrustStoreServer.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2007-2009,2012-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,2012-2020 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, @@ -17,7 +17,7 @@ * 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@ */ @@ -57,6 +57,9 @@ bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, bool _SecTrustStoreSetCTExceptions(CFStringRef appID, CFDictionaryRef exceptions, CFErrorRef *error); CF_RETURNS_RETAINED CFDictionaryRef _SecTrustStoreCopyCTExceptions(CFStringRef appID, CFErrorRef *error); +bool _SecTrustStoreSetCARevocationAdditions(CFStringRef appID, CFDictionaryRef additions, CFErrorRef *error); +CF_RETURNS_RETAINED CFDictionaryRef _SecTrustStoreCopyCARevocationAdditions(CFStringRef appID, CFErrorRef *error); + __END_DECLS #endif /* !_SECURITY_SECTRUSTSTORESERVER_H_ */ diff --git a/trust/trustd/SecTrustStoreServer.m b/trust/trustd/SecTrustStoreServer.m index acb0fb48..8c88c19c 100644 --- a/trust/trustd/SecTrustStoreServer.m +++ b/trust/trustd/SecTrustStoreServer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2018-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -33,6 +33,9 @@ #import "OTATrustUtilities.h" #include "SecTrustStoreServer.h" +// +// MARK : CT Exceptions +// typedef bool(*exceptionsArrayValueChecker)(id _Nonnull obj); static bool checkDomainsValuesCompliance(id _Nonnull obj) { @@ -184,7 +187,7 @@ CFDictionaryRef _SecTrustStoreCopyCTExceptions(CFStringRef appID, CFErrorRef *er int check = 0; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - /* initialize gHashCTExceptions cache */ + /* initialize gHasCTExceptions cache */ NSError *read_error = nil; NSDictionary *allExceptions = readExceptionsFromDisk(&read_error); if (!allExceptions || [allExceptions count] == 0) { @@ -202,7 +205,7 @@ CFDictionaryRef _SecTrustStoreCopyCTExceptions(CFStringRef appID, CFErrorRef *er status = notify_check(notify_token, NULL); } if (status != NOTIFY_STATUS_OK) { - secerror("failed to establish notification for CT exceptions: %ud", status); + secerror("failed to establish notification for CT exceptions: %u", status); notify_cancel(notify_token); notify_token = 0; } @@ -266,3 +269,216 @@ CFDictionaryRef _SecTrustStoreCopyCTExceptions(CFStringRef appID, CFErrorRef *er return NULL; } } + +// +// MARK: CA Revocation Additions +// +typedef bool(*additionsArrayValueChecker)(id _Nonnull obj); + +static bool checkCARevocationValuesCompliance(id _Nonnull obj) { + if (![obj isKindOfClass:[NSDictionary class]]) { + return false; + } + if (2 != [(NSDictionary*)obj count]) { + return false; + } + if (nil == ((NSDictionary*)obj)[(__bridge NSString*)kSecCARevocationHashAlgorithmKey] || + nil == ((NSDictionary*)obj)[(__bridge NSString*)kSecCARevocationSPKIHashKey]) { + return false; + } + if (![((NSDictionary*)obj)[(__bridge NSString*)kSecCARevocationHashAlgorithmKey] isKindOfClass:[NSString class]] || + ![((NSDictionary*)obj)[(__bridge NSString*)kSecCARevocationSPKIHashKey] isKindOfClass:[NSData class]]) { + return false; + } + if (![((NSDictionary*)obj)[(__bridge NSString*)kSecCARevocationHashAlgorithmKey] isEqualToString:@"sha256"]) { + return false; + } + return true; +} + +static bool checkCARevocationValues(NSString *key, id value, additionsArrayValueChecker checker, CFErrorRef *error) { + if (![value isKindOfClass:[NSArray class]]) { + return SecError(errSecParam, error, CFSTR("value for %@ is not an array in revocation additions dictionary"), key); + } + + __block bool result = true; + [(NSArray*)value enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (!checker(obj)) { + result = SecError(errSecParam, error, CFSTR("value %lu for %@ is not the expected type"), (unsigned long)idx, key); + *stop = true; + } + }]; + return result; +} + +static bool checkInputAdditionsAndSetAppAdditions(NSDictionary *inAdditions, NSMutableDictionary *appAdditions, CFErrorRef *error) { + __block bool result = true; + [inAdditions enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + if ([key isEqualToString:(__bridge NSString*)kSecCARevocationAdditionsKey]) { + if (!checkCARevocationValues(key, obj, checkCARevocationValuesCompliance, error)) { + *stop = YES; + result = false; + return; + } + } else { + result = SecError(errSecParam, error, CFSTR("unknown key (%@) in additions dictionary"), key); + *stop = YES; + result = false; + return; + } + if ([(NSArray*)obj count] == 0) { + [appAdditions removeObjectForKey:key]; + } else { + appAdditions[key] = obj; + } + }]; + return result; +} + +static _Atomic bool gHasCARevocationAdditions = false; +#define kSecCARevocationChanged "com.apple.trustd.ca.revocation-changed" + +static NSURL *CARevocationFileURL() { + return CFBridgingRelease(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("CARevocation.plist"))); +} + +static NSDictionary *readRevocationAdditionsFromDisk(NSError **error) { + secdebug("ocsp", "reading CA revocation additions from disk"); + NSDictionary *allAdditions = [NSDictionary dictionaryWithContentsOfURL:CARevocationFileURL() + error:error]; + return allAdditions; +} + +bool _SecTrustStoreSetCARevocationAdditions(CFStringRef appID, CFDictionaryRef additions, CFErrorRef *error) { + if (!SecOTAPKIIsSystemTrustd()) { + secerror("Unable to write CA revocation additions from user agent"); + return SecError(errSecWrPerm, error, CFSTR("Unable to write CA revocation additions from user agent")); + } + + if (!appID) { + secerror("application-identifier required to set CA revocation additions"); + return SecError(errSecParam, error, CFSTR("application-identifier required to set CA revocation additions")); + } + + @autoreleasepool { + NSError *nserror = nil; + NSMutableDictionary *allAdditions = [readRevocationAdditionsFromDisk(&nserror) mutableCopy]; + NSMutableDictionary *appAdditions = NULL; + if (allAdditions && allAdditions[(__bridge NSString*)appID]) { + appAdditions = [allAdditions[(__bridge NSString*)appID] mutableCopy]; + } else { + appAdditions = [NSMutableDictionary dictionary]; + if (!allAdditions) { + allAdditions = [NSMutableDictionary dictionary]; + } + } + + if (additions && (CFDictionaryGetCount(additions) > 0)) { + NSDictionary *inAdditions = (__bridge NSDictionary*)additions; + if (!checkInputAdditionsAndSetAppAdditions(inAdditions, appAdditions, error)) { + secerror("input additions have error: %@", error ? *error : nil); + return false; + } + } + + if (!additions || [appAdditions count] == 0) { + [allAdditions removeObjectForKey:(__bridge NSString*)appID]; + } else { + allAdditions[(__bridge NSString*)appID] = appAdditions; + } + + if (![allAdditions writeToURL:CARevocationFileURL() error:&nserror]) { + secerror("failed to write CA revocation additions: %@", nserror); + if (error) { + *error = CFRetainSafe((__bridge CFErrorRef)nserror); + } + return false; + } + secnotice("ocsp", "wrote %lu CA revocation additions", (unsigned long)[allAdditions count]); + atomic_store(&gHasCARevocationAdditions, [allAdditions count] != 0); + notify_post(kSecCARevocationChanged); + return true; + } +} + +CFDictionaryRef _SecTrustStoreCopyCARevocationAdditions(CFStringRef appID, CFErrorRef *error) { + @autoreleasepool { + /* Set us up for not reading the disk when there are never exceptions */ + static int notify_token = 0; + int check = 0; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + /* initialize gHasCARevocation cache */ + NSError *read_error = nil; + NSDictionary *allAdditions = readRevocationAdditionsFromDisk(&read_error); + if (!allAdditions || [allAdditions count] == 0) { + secnotice("ocsp", "skipping further reads. no CA revocation additions found: %@", read_error); + atomic_store(&gHasCARevocationAdditions, false); + } else { + secnotice("ocsp", "have CA revocation additions. will need to read."); + atomic_store(&gHasCARevocationAdditions, true); + } + + /* read-only trustds register for notfications from the read-write trustd */ + if (!SecOTAPKIIsSystemTrustd()) { + uint32_t status = notify_register_check(kSecCARevocationChanged, ¬ify_token); + if (status == NOTIFY_STATUS_OK) { + status = notify_check(notify_token, NULL); + } + if (status != NOTIFY_STATUS_OK) { + secerror("failed to establish notification for CA revocation additions: %u", status); + notify_cancel(notify_token); + notify_token = 0; + } + } + }); + + /* Read the negative cached value as to whether there are any revocation additions to read */ + if (!SecOTAPKIIsSystemTrustd()) { + /* Check whether we got a notification. If we didn't, and there are no additions set, return NULL. + * Otherwise, we need to read from disk */ + uint32_t check_status = notify_check(notify_token, &check); + if (check_status == NOTIFY_STATUS_OK && check == 0 && !atomic_load(&gHasCARevocationAdditions)) { + return NULL; + } + } else if (!atomic_load(&gHasCARevocationAdditions)) { + return NULL; + } + + /* We need to read the exceptions from disk */ + NSError *read_error = nil; + NSDictionary *allAdditions = readRevocationAdditionsFromDisk(&read_error); + if (!allAdditions || [allAdditions count] == 0) { + secnotice("ocsp", "skipping further reads. no CA revocation additions found: %@", read_error); + atomic_store(&gHasCARevocationAdditions, false); + return NULL; + } + + /* If the caller specified an appID, return only the exceptions for that appID */ + if (appID) { + return CFBridgingRetain(allAdditions[(__bridge NSString*)appID]); + } + + /* Otherwise, combine all the revocation additions into one array */ + NSMutableArray *caAdditions = [NSMutableArray array]; + [allAdditions enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull __unused key, NSDictionary * _Nonnull appAdditions, + BOOL * _Nonnull __unused stop) { + if (appAdditions[(__bridge NSString*)kSecCARevocationAdditionsKey] && + checkCARevocationValues((__bridge NSString*)kSecCARevocationAdditionsKey, + appAdditions[(__bridge NSString*)kSecCARevocationAdditionsKey], + checkCARevocationValuesCompliance, error)) { + [caAdditions addObjectsFromArray:appAdditions[(__bridge NSString*)kSecCARevocationAdditionsKey]]; + } + }]; + NSMutableDictionary *additions = [NSMutableDictionary dictionaryWithCapacity:2]; + if ([caAdditions count] > 0) { + additions[(__bridge NSString*)kSecCARevocationAdditionsKey] = caAdditions; + } + if ([additions count] > 0) { + secdebug("ocsp", "found %lu CA revocation additions on disk", (unsigned long)[additions count]); + atomic_store(&gHasCARevocationAdditions, true); + return CFBridgingRetain(additions); + } + return NULL; + } +} diff --git a/trust/trustd/iOS/entitlements.plist b/trust/trustd/iOS/entitlements.plist index dc6f6d2e..1709fd9c 100644 --- a/trust/trustd/iOS/entitlements.plist +++ b/trust/trustd/iOS/entitlements.plist @@ -19,6 +19,12 @@ com.apple.MobileAsset.PKITrustSupplementals com.apple.MobileAsset.SecExperimentAssets + com.apple.private.security.storage.trustd + + com.apple.private.security.storage.trustd-private + + com.apple.private.security.storage.SFAnalytics + seatbelt-profiles trustd diff --git a/trust/trustd/macOS/com.apple.trustd.sb b/trust/trustd/macOS/com.apple.trustd.sb index f13684b1..e7f0a6a7 100644 --- a/trust/trustd/macOS/com.apple.trustd.sb +++ b/trust/trustd/macOS/com.apple.trustd.sb @@ -38,6 +38,7 @@ (allow file-read* file-write* (subpath "/private/var/db/mds/") (subpath "/private/var/db/crls/") + (subpath "/private/var/protected/") (subpath "/System/Library/Security/") (subpath "/Library/Keychains/") (subpath "/private/var/root/Library/Caches/com.apple.nsurlsessiond/")) @@ -62,11 +63,26 @@ (global-name "com.apple.securityd.xpc") (global-name "com.apple.cfnetwork.cfnetworkagent") (global-name "com.apple.nsurlsessiond") + (global-name "com.apple.dnssd.service") (xpc-service-name "com.apple.powerlog.plxpclogger.xpc") (global-name "com.apple.nesessionmanager.content-filter")) (allow ipc-posix-shm (ipc-posix-name "com.apple.AppleDatabaseChanged")) + ;; Read IOKit properties for personalization + (allow iokit-get-properties + (iokit-property "image4-supported") + (iokit-property "Content") + (iokit-property "boot-uuid") + (iokit-property "IORegistryEntryPropertyKeys") + (iokit-property "IOClassNameOverride") + (iokit-property "Protocol Characteristics") + (iokit-property "board-id") + (iokit-property "chip-id") + (iokit-property "unique-chip-id") + (iokit-property "boot-manifest-hash") + (iokit-property "crypto-hash-method")) + (allow network-outbound) (allow system-socket) diff --git a/trust/trustd/macOS/entitlements.plist b/trust/trustd/macOS/entitlements.plist index efa5ea47..c880b49a 100644 --- a/trust/trustd/macOS/entitlements.plist +++ b/trust/trustd/macOS/entitlements.plist @@ -19,5 +19,11 @@ com.apple.MobileAsset.PKITrustSupplementals com.apple.MobileAsset.SecExperimentAssets + com.apple.private.security.storage.trustd + + com.apple.private.security.storage.trustd-private + + com.apple.private.security.storage.SFAnalytics + diff --git a/trust/trustd/trustd.c b/trust/trustd/trustd.c index 02e9808a..fc51d32d 100644 --- a/trust/trustd/trustd.c +++ b/trust/trustd/trustd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2017-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -305,7 +305,7 @@ static bool SecXPC_OTASecExperiment_GetAsset(SecurityClient * __unused client, x return result; } -static bool SecXPC_OTAPKI_CopyTrustedCTLogs(SecurityClient * __unused client, xpc_object_t event, +static bool SecXPC_OTAPKI_CopyTrustedCTLogs(SecurityClient * __unused client, xpc_object_t __unused event, xpc_object_t reply, CFErrorRef *error) { bool result = false; CFDictionaryRef trustedLogs = SecOTAPKICopyCurrentTrustedCTLogs(error); @@ -381,6 +381,33 @@ static bool SecXPCTrustStoreCopyCTExceptions(SecurityClient * __unused client, x return false; } +static bool SecXPCTrustStoreSetCARevocationAdditions(SecurityClient *client, xpc_object_t event, + xpc_object_t reply, CFErrorRef *error) { + CFStringRef appID = NULL; + CFDictionaryRef additions = NULL; + if (!SecXPCDictionaryCopyStringOptional(event, kSecTrustEventApplicationID, &appID, error) || !appID) { + /* We always want to set the app ID with the additions */ + appID = SecTaskCopyApplicationIdentifier(client->task); + } + (void)SecXPCDictionaryCopyDictionaryOptional(event, kSecTrustRevocationAdditionsKey, &additions, error); + bool result = _SecTrustStoreSetCARevocationAdditions(appID, additions, error); + xpc_dictionary_set_bool(reply, kSecXPCKeyResult, result); + CFReleaseNull(additions); + CFReleaseNull(appID); + return false; +} + +static bool SecXPCTrustStoreCopyCARevocationAdditions(SecurityClient * __unused client, xpc_object_t event, + xpc_object_t reply, CFErrorRef *error) { + CFStringRef appID = NULL; + (void)SecXPCDictionaryCopyStringOptional(event, kSecTrustEventApplicationID, &appID, error); + CFDictionaryRef additions = _SecTrustStoreCopyCARevocationAdditions(appID, error); + SecXPCDictionarySetPListOptional(reply, kSecTrustRevocationAdditionsKey, additions, error); + CFReleaseNull(additions); + CFReleaseNull(appID); + return false; +} + #if TARGET_OS_IPHONE static bool SecXPCTrustGetExceptionResetCount(SecurityClient * __unused client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error) { uint64_t exceptionResetCount = SecTrustServerGetExceptionResetCount(error); @@ -404,6 +431,12 @@ static bool SecXPCTrustIncrementExceptionResetCount(SecurityClient * __unused cl } #endif +static bool SecXPC_Valid_Update(SecurityClient * __unused client, xpc_object_t __unused event, + xpc_object_t reply, CFErrorRef *error) { + xpc_dictionary_set_uint64(reply, kSecXPCKeyResult, SecRevocationDbUpdate(error)); + return true; +} + typedef bool(*SecXPCOperationHandler)(SecurityClient *client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error); typedef struct { @@ -433,6 +466,9 @@ struct trustd_operations { SecXPCServerOperation trust_get_exception_reset_count; SecXPCServerOperation trust_increment_exception_reset_count; #endif + SecXPCServerOperation trust_store_set_ca_revocation_additions; + SecXPCServerOperation trust_store_copy_ca_revocation_additions; + SecXPCServerOperation valid_update; }; static struct trustd_operations trustd_ops = { @@ -457,6 +493,9 @@ static struct trustd_operations trustd_ops = { .trust_get_exception_reset_count = { NULL, SecXPCTrustGetExceptionResetCount }, .trust_increment_exception_reset_count = { kSecEntitlementModifyAnchorCertificates, SecXPCTrustIncrementExceptionResetCount }, #endif + .trust_store_set_ca_revocation_additions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreSetCARevocationAdditions }, + .trust_store_copy_ca_revocation_additions = {kSecEntitlementModifyAnchorCertificates, SecXPCTrustStoreCopyCARevocationAdditions }, + .valid_update = { NULL, SecXPC_Valid_Update }, }; static void trustd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) { @@ -618,6 +657,15 @@ static void trustd_xpc_dictionary_handler(const xpc_connection_t connection, xpc server_op = &trustd_ops.trust_increment_exception_reset_count; break; #endif + case kSecXPCOpSetCARevocationAdditions: + server_op = &trustd_ops.trust_store_set_ca_revocation_additions; + break; + case kSecXPCOpCopyCARevocationAdditions: + server_op = &trustd_ops.trust_store_copy_ca_revocation_additions; + break; + case kSecXPCOpValidUpdate: + server_op = &trustd_ops.valid_update; + break; default: break; } diff --git a/trust/trustd/trustd_spi.c b/trust/trustd/trustd_spi.c index 0ed05260..19233f06 100644 --- a/trust/trustd/trustd_spi.c +++ b/trust/trustd/trustd_spi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Apple Inc. All Rights Reserved. + * Copyright (c) 2018-2020 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -73,6 +73,9 @@ struct trustd trustd_spi = { .sec_trust_get_exception_reset_count = SecTrustServerGetExceptionResetCount, .sec_trust_increment_exception_reset_count = SecTrustServerIncrementExceptionResetCount, #endif + .sec_trust_store_set_ca_revocation_additions = _SecTrustStoreSetCARevocationAdditions, + .sec_trust_store_copy_ca_revocation_additions = _SecTrustStoreCopyCARevocationAdditions, + .sec_valid_update = SecRevocationDbUpdate, }; #endif diff --git a/xcconfig/PlatformFeatures.xcconfig b/xcconfig/PlatformFeatures.xcconfig index 17f372c2..35f07f11 100644 --- a/xcconfig/PlatformFeatures.xcconfig +++ b/xcconfig/PlatformFeatures.xcconfig @@ -21,23 +21,23 @@ OCTAGON_ON[sdk=appletv*] = 1 TRUSTEDPEERS_ON = 0 TRUSTEDPEERS_ON[sdk=macosx*] = 1 TRUSTEDPEERS_ON[sdk=iphone*] = 1 -TRUSTEDPEERS_ON[sdk=bridgeos*] = 1 +TRUSTEDPEERS_ON[sdk=bridgeos*] = 0 TRUSTEDPEERS_ON[sdk=watch*] = 1 TRUSTEDPEERS_ON[sdk=appletv*] = 1 // SecureObject Sync should only be on on iOS and macOS, but until we have octagon, its on on watch and TV SECUREOBJECTSYNC_ON[sdk=iphone*] = 1 -SECUREOBJECTSYNC_ON[sdk=bridgeos*] = 1 +SECUREOBJECTSYNC_ON[sdk=bridgeos*] = 0 SECUREOBJECTSYNC_ON[sdk=watch*] = 1 SECUREOBJECTSYNC_ON[sdk=appletv*] = 1 SECUREOBJECTSYNC_ON[sdk=macos*] = 1 -// Shared web credentials is only supported on iOS +// Shared web credentials is supported on iOS and macOS and Catalyst SHAREDWEBCREDENTIALS_ON[sdk=iphone*] = 1 SHAREDWEBCREDENTIALS_ON[sdk=bridgeos*] = 0 SHAREDWEBCREDENTIALS_ON[sdk=watch*] = 0 SHAREDWEBCREDENTIALS_ON[sdk=appletv*] = 0 -SHAREDWEBCREDENTIALS_ON[sdk=macos*] = 0 +SHAREDWEBCREDENTIALS_ON[sdk=macos*] = 1 ABC_BUGCAPTURE_ON[sdk=iphoneos*] = 1 ABC_BUGCAPTURE_ON[sdk=iphonesimulator*] = 0 diff --git a/xcconfig/PlatformLibraries.xcconfig b/xcconfig/PlatformLibraries.xcconfig index 1960abdc..eef498f4 100644 --- a/xcconfig/PlatformLibraries.xcconfig +++ b/xcconfig/PlatformLibraries.xcconfig @@ -1,17 +1,18 @@ - -OTHER_LDFLAGS_MOCK_AKS_LIBRARY = -laks_mock -framework SecurityFoundation + +OTHER_LDFLAGS_AKS_ACL_LIBRARY = -laks_acl + +OTHER_LDFLAGS_MOCK_AKS_LIBRARY = -laks_mock $(OTHER_LDFLAGS_AKS_ACL_LIBRARY) -framework SecurityFoundation -framework ProtocolBuffer OTHER_LDFLAGS_AKS_LIBRARY[sdk=macosx*] = -L$(SDKROOT)/usr/local/lib -laks -laks_real_witness OTHER_LDFLAGS_AKS_LIBRARY[sdk=iphoneos*] = -L$(SDKROOT)/usr/local/lib -laks -laks_real_witness OTHER_LDFLAGS_AKS_LIBRARY[sdk=watchos*] = -L$(SDKROOT)/usr/local/lib -laks -laks_real_witness OTHER_LDFLAGS_AKS_LIBRARY[sdk=appletvos*] = -L$(SDKROOT)/usr/local/lib -laks -laks_real_witness -OTHER_LDFLAGS_AKS_LIBRARY[sdk=iphonesimulator*] = -laks_mock -Wl,-upward_framework,SecurityFoundation -Wl,-upward_framework,ProtocolBuffer +OTHER_LDFLAGS_AKS_LIBRARY[sdk=iphonesimulator*] = -laks_mock $(OTHER_LDFLAGS_AKS_ACL_LIBRARY) -Wl,-upward_framework,SecurityFoundation -Wl,-upward_framework,ProtocolBuffer OTHER_LDFLAGS_MOBILE_KEYBAG[sdk=macosx*] = -framework MobileKeyBag OTHER_LDFLAGS_MOBILE_KEYBAG[sdk=iphoneos*] = -framework MobileKeyBag OTHER_LDFLAGS_MOBILE_KEYBAG[sdk=watchos*] = -framework MobileKeyBag OTHER_LDFLAGS_MOBILE_KEYBAG[sdk=appletvos*] = -framework MobileKeyBag -OTHER_LDFLAGS_AKS_ACL_LIBRARY = -laks_acl OTHER_LDFLAGS_ACM_LIBRARY[sdk=macosx*] = -lACM OTHER_LDFLAGS_ACM_LIBRARY[sdk=iphoneos*] = -lACM @@ -24,8 +25,11 @@ OTHER_LDFLAGS_ACM_LIBRARY[sdk=watchsimulator*] = OTHER_LDFLAGS_AGGREGATEDICTIONARY[sdk=embedded] = -framework AggregateDictionary OTHER_LDFLAGS_APPLESYSTEMINFO[sdk=macos*] = -framework AppleSystemInfo OTHER_LDFLAGS_DIAGNOSTICSMESSAGESCLIENT[sdk=macosx*] = -lDiagnosticMessagesClient -OTHER_LDFLAGS_MOBILEGESTALT[sdk=embedded*] = -lMobileGestalt +OTHER_LDFLAGS_MOBILEGESTALT = -lMobileGestalt OTHER_LDFLAGS_IMG4DECODE[sdk=embedded] = -lImg4Decode +OTHER_LDFLAGS_IMG4DECODE[sdk=macosx*] = -lImg4Decode +OTHER_LDFLAGS_MSUDATAACCESSOR[sdk=embedded] = -framework MSUDataAccessor +OTHER_LDFLAGS_MSUDATAACCESSOR[sdk=macosx*] = -framework MSUDataAccessor OTHER_LDFLAGS_UPWARD_FOUNDATION = -Wl,-upward_framework,Foundation OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER = -Wl,-upward_framework,ProtocolBuffer OTHER_LDFLAGS_UPWARD_SECURITY = -Wl,-upward_framework,Security @@ -70,7 +74,9 @@ OTHER_LDFLAGS_COREFOLLOWUP[sdk=appletvsimulator*] = // The bridge appears to support protocol buffers. OTHER_LDFLAGS_PROTOBUF = -framework ProtocolBuffer +OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=macos*] = OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=iphoneos*] = -framework SharedWebCredentials +OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=iphonesimulator*] = -framework SharedWebCredentials OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=bridgeos*] = OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=watchos*] = OTHER_LDFLAGS_SHAREDWEBCREDENTIALS[sdk=appletvos*] = @@ -87,6 +93,9 @@ OTHER_LDFLAGS_MOBILEASSET[sdk=bridgeos*] = OTHER_LDFLAGS_CORECDP = -weak_framework CoreCDP OTHER_LDFLAGS_CORECDP[sdk=bridgeos*] = +OTHER_LDFLAGS_CLOUDSERVICES = -weak_framework CloudServices +OTHER_LDFLAGS_CLOUDSERVICES[sdk=bridgeos*] = + OTHER_LDFLAGS_SECURITYFOUNDATION = -framework SecurityFoundation OTHER_LDFLAGS_SECURITYFOUNDATION[sdk=bridgeos*] = @@ -98,7 +107,7 @@ OTHER_LDFLAGS_IMCORE[sdk=bridgeos*] = OTHER_LDFLAGS_UserManagement[sdk=iphone*] = -framework UserManagement OTHER_LDFLAGS_UserManagement[sdk=macosx*] = -framework UserManagement OTHER_LDFLAGS_UserManagement[sdk=watch*] = -OTHER_LDFLAGS_UserManagement[sdk=appletv*] = +OTHER_LDFLAGS_UserManagement[sdk=appletv*] = -framework UserManagement OTHER_LDFLAGS_CrashReporterSupport[sdk=iphoneos*] = -framework CrashReporterSupport OTHER_LDFLAGS_CrashReporterSupport[sdk=macosx*] = @@ -112,3 +121,10 @@ OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER_1 = -weak_framework SymptomDiagnosticRep OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER_0 = OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER_ = OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER = $(OTHER_LDFLAGS_SYMPTOMDIAGNOSTICREPORTER_$(ABC_BUGCAPTURE_ON)) + +// Convince Xcode to build platform-specific apps from a single target +OTHER_LDFLAGS_AppFrameworks[sdk=macosx*] = -framework AppKit +OTHER_LDFLAGS_AppFrameworks[sdk=embedded*] = -framework UIKit + +TEST_HOST_BINARY_PATH_IN_BUNDLE[sdk=macosx*] = Contents/MacOS/ +TEST_HOST_BINARY_PATH_IN_BUNDLE[sdk=embedded] = diff --git a/xcconfig/Security.xcconfig b/xcconfig/Security.xcconfig index 195db7c3..7c1df3ce 100644 --- a/xcconfig/Security.xcconfig +++ b/xcconfig/Security.xcconfig @@ -24,7 +24,10 @@ SECURITY_FUZZER_BASE_DIR = /AppleInternal/CoreOS/Fuzzers/Security // Apple Clang - Code Generation CLANG_TRIVIAL_AUTO_VAR_INIT = pattern -WARNING_CFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-error=deprecated-declarations -Wno-error=implicit-retain-self -Wno-error=#warnings -Wno-error=unused-function -Wno-error=unused-variable +CLANG_CXX_LANGUAGE_STANDARD = gnu++2a +GCC_C_LANGUAGE_STANDARD = gnu2x + +WARNING_CFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-error=deprecated-declarations -Wno-error=deprecated-implementations -Wno-error=implicit-retain-self -Wno-error=#warnings -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=documentation WARNING_CFLAGS[sdk=embedded*] = $(WARNING_CFLAGS) -Wformat=2 diff --git a/xcconfig/all_arches.xcconfig b/xcconfig/all_arches.xcconfig deleted file mode 100644 index cf6cff55..00000000 --- a/xcconfig/all_arches.xcconfig +++ /dev/null @@ -1 +0,0 @@ -ARCHS[sdk=macosx*] = $(ARCHS_STANDARD_32_64_BIT) diff --git a/xcconfig/framework_requiring_modern_objc_runtime.xcconfig b/xcconfig/framework_requiring_modern_objc_runtime.xcconfig deleted file mode 100644 index 5c058bc8..00000000 --- a/xcconfig/framework_requiring_modern_objc_runtime.xcconfig +++ /dev/null @@ -1,7 +0,0 @@ - -// For frameworks that should only be built when the modern obj-c runtime is available. -// This file must be updated when new architectures are introduced. - -VALID_ARCHS = armv6 armv7 armv7k arm64 x86_64 x86_64h - -VALID_ARCHS[sdk=*simulator*] = armv6 armv7 armv7k arm64 i386 x86_64 x86_64h diff --git a/xcconfig/lib_ios.xcconfig b/xcconfig/lib_ios.xcconfig index bdbaaffc..334eb30b 100644 --- a/xcconfig/lib_ios.xcconfig +++ b/xcconfig/lib_ios.xcconfig @@ -18,7 +18,7 @@ COPY_PHASE_STRIP = NO SKIP_INSTALL = YES COPY_PHASE_STRIP = NO -GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_C_LANGUAGE_STANDARD = gnu2x HEADERMAP_INCLUDES_FRAMEWORK_ENTRIES_FOR_ALL_PRODUCT_TYPES = NO diff --git a/xcconfig/swift_binary.xcconfig b/xcconfig/swift_binary.xcconfig index a968320e..bd7311fe 100644 --- a/xcconfig/swift_binary.xcconfig +++ b/xcconfig/swift_binary.xcconfig @@ -16,3 +16,7 @@ OCTAGON_FLAG_1 = -D OCTAGON OTHER_SWIFT_FLAGS = $(OCTAGON_FLAG_$(OCTAGON_ON)) SWIFT_VERSION=5 +SWIFT_TREAT_WARNINGS_AS_ERRORS = YES + +TEST_BUILD_STYLE = _APPLEINTERNAL +SYSTEM_FRAMEWORK_SEARCH_PATHS = $(inherited) ${PLATFORM_DIR}/Developer/AppleInternal/Library/Frameworks diff --git a/xcscripts/install-test-framework.sh b/xcscripts/install-test-framework.sh index ae4aae17..26b4b1b0 100644 --- a/xcscripts/install-test-framework.sh +++ b/xcscripts/install-test-framework.sh @@ -8,8 +8,9 @@ for a in ${TEST_FRAMEWORK_SEARCH_PATHS}; do if test -d "${a}/${framework}" ; then dst="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}" - mkdir -p "{dst}" || { echo "mkdir failed with: $?" ; exit 1; } + mkdir -p "${dst}" || { echo "mkdir failed with: $?" ; exit 1; } ditto "${a}/${framework}" "${dst}/${framework}" || { echo "ditto failed with: $?" ; exit 1; } + find "${dst}/${framework}" \( -name Headers -o -name Modules -o -name '*.tbd' \) -delete xcrun codesign -s - -f "${dst}/${framework}" || { echo "codesign failed with: $?" ; exit 1; } found=yes -- 2.45.2